Create a Robotic Process

An Appian RPA robot is the result of the integration of all Appian RPA platform components.

Sometimes, a robotic process's operation may take a long time. Applications have been designed for humans, and it is not unusual that, under long execution conditions with a very high processing speed, a problem may arise causing that application to fail, even though the robot is properly developed.

It is for just this reason that there are three characteristics that any Appian RPA robot must have:

  • It must be reliable: the principle is "what the robot does, it must be well done." Without this guarantee, the robot should not go on. A robot that processes important information must always be confident of what it is doing. For example, if it is not on the window it should be at a given time, data loss could occur. Usually Appian RPA robots, unlike other software, operate directly on production environments, so reliability is a very important feature not only on production, but on development itself.
  • It must be reentrant: robots must be designed so that you can stop its execution at a given time and resume it without manual intervention on the execution machine. This feature is especially important for robots whose operation takes a long time or that handle a large number of items to process. If execution stops, either manually or due to an error, it must allow to be resumed.
  • It must be thorough: a robot must do everything it's supposed to do, and what it does must be reflected somewhere. At least, it must be reflected in the execution log, although its medium can be adjusted for easier reading and interpretation by the developer. In case the end user wants to access the log, it is advisable to previously gather the information that the robot should put into the log, so that it can be included into the robot's code during the development phase.

Creating a robotic process based on one in another environment? Learn how to export and import robotic processes.

Create a robot in Appian RPA Console

After you've set up your development environment, you're ready to create your first robot. This page show you how to use a template to create a robotic process in the Appian RPA Console.

In the Robotic processes menu, click on the Create robotic process icon 2235137.png in the toolbar.

rpa-create-process.png

  • Identifier: Robot identifier in the console and in our Maven project. This value must be unique and can't be changed.
  • Technology: In this case, choose Java.
  • Template: In this example, we will use the template "Hello World". You don't have to use a template.
    • Last version: Ensures that the selected template matches the last API version available in our console.
  • Group: Location of the Maven project in Nexus. We use the default value, although it can be modified.
  • Version: Version of the robot in Nexus. As in the previous case, the default value will be used.
  • Repository: Choose the URL used in the Maven configuration and write in the welcome email.

Download source code

When you use a template to create an Appian RPA robot, the source code of the robot is downloaded to your computer. In addition, the Maven project will be automatically deployed in the Nexus repository.

More on Maven setup.

A zip file with the source code is available. Copy this file into the folder where you will develop the robots.

Configure the new robot

Now you have the new robot created in the Appian RPA console and it is ready to be executed. Next, you'll configure the robotic process's workflow and technical details.

See Configuring a Robotic Process to get started.

Execute and monitor the robotic process

Now let's launch the robot. Remember that the resource must be activated for execution to be successful.

  1. Open the Robotic processes tab and you'll see the new robot.
  2. Click the Start Execution Button rpa-execute-icon.png.
  3. Confirm the execution in the screen that is shown.

    rpa-execution-options-2.png

  4. The agent will download the robot and its dependencies in the resource and start the execution.
  5. You can monitor the robot's execution through the Appian RPA console. rpa-execution-list.png rpa-execution-log.png
  6. When the execution ends, we can check the result of the complete execution. rpa-result-log.png

To learn more about execution options, see Executing a Robotic Process.

Copy a robotic process

To clone a robot identical to a previously created robot on the console, access the robot section and, within the Actions column, click on the icon 2228581.png .

A confirmation pop-up appears to ask you for the new robot identifier and its functional name. By default, it will be the same as the robot you are cloning.

rpa-copy-process.png

You can also clone its executions, thus keeping one robot's executions log on its clone. By default, executions will be included, so if you don't want to copy them you should uncheck the Include executions option.

MyRobot class

An Appian RPA robot is a Java class that implements the Client module interface IRobot.

On the project that we have loaded into Eclipse, let's open the file MyRobot.java. The file MyRobot.java is in the project's package com.novayre.jidoka.tutorial.

By double clicking, we open it in the Eclipse editor (following image). 951604.png

Annotation @Robot

Analyzing the code of the class MyRobot, the first thing that catches our attention is the annotation @Robot. This annotation, together with the interface IRobot, allows the Appian RPA API to identify our class as a robot.

Actions

Just after the variables declaration, we can find the code:

1
public void init() throws Exception {

As you can see, there is a method, init. This will be the initial method of the robot. The way Appian RPA determines that this is the initial method is through the console, by associating the name of this method with an initial action.

We can call the initial method in any way, although it is advisable to use start or init.

Each task in the workflow is a method that, in Appian RPA terminology, corresponds to the concept of an action. Let's remember the types of actions that can be found within a workflow:

  • Start: the action that defines the initial action of the workflow.
  • Generic: common in-between action of the workflow.
  • Conditional: in-between action representing a fork.
  • End: the action that defines the finishing action of the workflow.

There are several conditions that must be met by a method to be used as an action:

  1. If it is a conditional action (represents a fork in the workflow) the method must be public, it cannot accept parameters, and it must return a String type object. This returned value will represent the path specified in the workflow from the console, through the corresponding literal of the output transitions of the conditional action.
  2. If it is not a conditional action, the method must be public, it cannot accept parameters, and it cannot return anything.
  3. In both cases the method may declare that it will throw any kind of exception.

In the previous example of a real workflow, there are two possible outputs from the conditional action "Has more registers". One of them, labeled with the literal "yes", goes to the generic action "Process", whereas the other one, labeled with the literal "No", would lead the flow towards the action "Close Notepad".

The code could look like this:

1
2
3
public String hasMoreRegisters() throws Exception {
    return hay ? "yes" : "no";  
}

As we will see later, the code of the method hasMoreRegisters for our example robot will be simpler.

The interface IRobot

1
2
@Robot
public class MyRobot implements IRobot {

The class MyRobot implements the interface IRobot, located in the package com.novayre.jidoka.client.api.

For now, it is sufficient to know that every Appian RPA Robot must implement the interface IRobot.

Among the Maven dependencies of our project, the dependency jidoka-client-api-x.y.z.jar is included by default, because that is how it is defined in the parent POM.

This dependency contains the interfaces and classes that make it easier to develop the robot. In section 4 Client module, the content of this module is explained in more detail.

IJidokaServer and IWindows

Continuing with the analysis of the class MyRobot, we see the following attributes and constants definition:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
 * Pause between actions to mimic human behavior.
 */
private static final int PAUSE = 500;

/**
 * Server
 */
private IJidokaServer<?> server;

/**
 * Windows module.
 */
private IWindows windows;

/**
 * Current item index. The first index is 1.
 */
private int currentItemIndex = 1;

The value 500 of the PAUSE constant determines the number of milliseconds that the delay will last. It can take any other value. In our case, we have initialized it to the value 500, which is equivalent to half a second.

We will use this constant when we need our robot to pause.

The Appian RPA robots operate continuously, without a rest. A pause is justified because the working speed of the robot on the applications is very fast, and the applications are designed for human use, so we need to adapt our robot's working speed to imitate humans' behavior. This way, the applications accessed by the robots can work properly.

In the previous declarations, one of them deserves special attention, the one that declares the object server:

1
private IJidokaServer<?> server;

This is the object responsible for the communication with the Appian RPA Server and, therefore, with the console. As well as sending log messages to the console, there are three important things this object must notify to perform an optimal robot monitoring from the console: the number of items to process, the time when an item processing starts and the time when an item processing ends.

Let's go back to the analysis of the code of our example robot declaring the instance of the interface IWindows.

1
private IWindows windows;

This is the Windows module declaration. IWindows inherits from IJidokaRobot and has methods that make it easier for a robot to operate on a Windows operating system. Later we will pay much more attention to the Appian RPA modules.

1
private int currentItemIndex = 1;

The variable currentItemIndex will store the number of the item that is being processed and will be used in other places in our code. We initialize the variable to 1 (not 0) because that is the value that represents the item position within the set of items to be processed.

Our robot starts working

Below we are going to detail the robot actions, describing what each method does and how. If we want to, we can resume to this point once we have successfully been able to execute the robot.

The next important detail we can find in our robot's code is the method init, that is, the one that was specified as initial point in the console:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
 * Action 'Init'.
 * 
 * @throws Exception
 */
public void init() throws Exception {
    
    server = (IJidokaServer<?>) JidokaFactory.getServer();
    
    windows = IJidokaRobot.getInstance(this);
    
    // Standard pause after typing or using the mouse.
    windows.typingPause(PAUSE);
    windows.mousePause(PAUSE);
    
    // Parameter log example.
    server.getParameters().entrySet().forEach((e) -> {
        server.debug(String.format("ParĂ¡metro [%s] = [%s]",
            e.getKey(), e.getValue()));
    });

    // Other log examples.
    server.warn("Warn example");
    server.error("And error example");

    /*
     * Set the number of items.
     * 
     * In a real robot, this number can be obtained by managing an
     * application, a sheet in an input Excel, etc.
     * 
     * It is very important to use this method as soon as we figure out
     * this * information, because it helps the platform to calculate
     * accurate * statistics and time measures.
     */
    server.setNumberOfItems(1);
}

In this method, you can see many of the concepts that are going to be analyzed.

Typically, the necessary modules and variables are initialized here.

The declaration of the method init meets the requirements for being used as an action, that is, it is a public method, it returns no value (void) and it receives no parameters.

1
public void init() throws Exception {

Then, the object IWindows windows and the object IJidokaServer<?> server are initialized. In the object server declaration, we can see that it uses generics. This allows to work with the Appian RPA context, a way to persist information across executions. We go in depth on this concept in IJidokaServer.

The object windows is initialized here though IJidokaRobot.getInstance(this). As we said, IWindows inherits from IJidokaRobot and can also be initialized this way: windows = IWindows.getInstance(this);

1
2
3
// Set the standard pause after typing or using the mouse.
windows.typingPause(PAUSE);
windows.mousePause(PAUSE);

These two lines are simple: they establish the pause that our robot must make after entering text or performing any action with the mouse. This is important to adapt robot's speed to the applications being used, which are typically designed for being used by humans, and may not be ready for the speed of use a robot can reach, eventually resulting in some errors. For example, think of running a robot that must access an application, but it does not wait the time it takes for the application window to open.

1
2
3
4
5
// Parameter log example.
server.getParameters().entrySet().forEach((e) -> {
    server.debug(String.format("ParĂ¡metro [%s] = [%s]",
            e.getKey(), e.getValue()));
});

Above you can see an example of execution parameter retrieval of a robot. The method getParameters that belongs to the interface IJidokaContext returns a Map<String, String> with the execution parameters of the robot sent by the server.

The next line sends information about the parameters to the server (name and value). This information will be shown in the execution log.

1
2
server.warn("Warn example");
server.error("And error example");

Other log examples that can be sent to the server and will be shown in the execution log: IJidokaServer inherits from Log (org.apache.commons.logging) and therefore it can send the same types of log sent by this class.

The next line is important. It is one of the notifications that every Appian RPA Robot must send to the server:

1
server.setNumberOfItems(1);

We are notifying the server that the total number of items to be processed is 1. This is an example robot, and in a real robot the number of items will be obtained depending on the type of task that the robot must accomplish, for example, from a database, an Excel file, or an input file.

The number of items to be processed is not always known at this moment, but it is necessary for the server to know this number before processing the items, to gather statistics related to processing time, and to show information in the execution log.

When the method ends, Appian RPA knows that the next method to be executed will be openNotepad, since it was specified this way in the workflow from the console. In this method, we will use some text input functions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
 * Action 'Open Notepad'.
 * 
 * @throws Exception
 */
public void openNotepad() throws Exception {
    
    windows.pause(PAUSE);

    // Win+R
    windows.typeText(windows.getKeyboardSequence()
            .pressWindows().type("r").releaseWindows());
    
    // Type "notepad"
    windows.typeText("notepad");
    
    // Type enter
    windows.typeText(windows.getKeyboardSequence().typeReturn());
    
    windows.showWindow(windows.getWindow("Sin.*").gethWnd(),
            EShowWindowState.SW_MAXIMIZE);

    // Explicit pause
    windows.pause(PAUSE);
}

The first thing we can see is the method pause to adapt the robot's speed to the applications it uses.

1
windows.pause(PAUSE);

Remember we had initialized the PAUSE variable to the value 500, which represents the milliseconds that the pause will last, so the previous line pauses the robot's execution for half a second (500 milliseconds). Below we can see three examples of keyboard use by the robot, through the method typeText() of the class IJidokaRobot.

What we are doing is emulating the use of a keyboard by a human.

1
2
3
4
5
6
7
8
9
// Win+R
windows.typeText(windows.getKeyboardSequence()
        .pressWindows().type("r").releaseWindows());

// Type "notepad"
windows.typeText("notepad");

// Type enter
windows.typeText(windows.getKeyboardSequence().typeReturn());

The method typeText from IJidokaRobot is overloaded and in the previous code snippet we can see the two ways we can use it:

  • void typeText(String text); which prints the text specified in the parameter.
  • void typeText(IKeyboardSequence sequence); which emulates a more or less complex keystroke sequence depending on our needs.

Let's have a look at the following code from our example:

1
2
3
// Win+R
widows.typeText(windows.getKeyboardSequence().pressWindows().type("r")
.releaseWindows());

The input parameter's type is IKeyboardSequence and first an instance of IKeyboardSequence is obtained through windows.getKeyboardSequence(), then the necessary actions are added to the keystroke sequence to be made.

Finally, the sequence consists of "pressing the Windows key + pressing the R key + releasing the Windows key". What we have done is to emulate the simultaneous keying of Windows + R to open the Windows dialog box Run.

Next, the robot types the text "notepad" in the Windows dialog box Run, and finally it will enter a new IKeyboardSequence consisting in this case of pressing the Return key. We have just opened the Notepad in one of the different ways available to do so.

IKeyboardSequence also provides easy access to usual and relatively frequent keystrokes sequences. Some examples follow:

  • typeTab(): imitates the Tab keystroke.
  • typeTab(int repetition): the same as above, but you can specify how many times the Tab key will be pressed.
  • pressAlt(), releaseAlt(), typeAlt(), typeAlt(int repetition): which respectively imitate the keystrokes for pressing the Alt key, releasing the Alt key, pressing (and releasing) the Alt key, and a number of keystrokes specified by the parameter repetition.
  • typeAltF(int numberF): provides the use of the Alt + F sequences.

In short, the list of methods from IKeyboardSequence for emulating keystroke sequences is quite large. There are methods to emulate sequences involving the Ctrl, Up, Down, Left, Right keys, and even for the Select all action (Ctrl + E for a Spanish keyboard), etc.

Once this method ends, our robot can go on in the process with processItem.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 * Action 'Process Item'.
 * 
 * @throws Exception
 */
public void processItem() throws Exception {

    String item = "this is a test";

    // Notify the start of the item processing.
    server.setCurrentItem(currentItemIndex, item);
    
    // Type the text in notepad
    windows.typeText(item);
    
    // Press intro
    windows.typeText(windows.getKeyboardSequence().typeReturn());

    // Notify the server the result of the item processing
    server.setCurrentItemResultToOK();
    
    // Send a screenshot to the log
    server.sendScreen(String.format("Snapshot over %s", item));
}

This method will process the items.

As a basic robot, we had informed the server that the number of items would be 1, but remember that a real robot will have to determine the number of items depending on the task it should accomplish.

For simplicity, in this example we have created an item, which will be the string item:

1
String item = "this is a test";

Immediately after this, we can see a very important line, because it is the line that tells the server that we are starting to process an item. This method should be called as soon as an item's processing begins, so that its processing time can be properly measured. This is essential to gather accurate statistical data, that will be shown in the console.

1
2
// Notify the start of the item processing.
server.setCurrentItem(currentItemIndex, item);

The method setCurrentItem(int itemIndex, String itemKey) receives two parameters:

  • itemIndex: which indicates the item occurrence to be processed, in this case, 1. This method expects to be called in sequence, that is, the first call should use index 1, then 2, etc. The first valid value for the index is 1.
  • itemKey: which is a String type object that describes the item.

In our example, the parameters are currentItem and item.

It should be highlighted that, although the parameter itemKey can be any text, the parameter itemIndex must contain the item's position on the list of items that is going to be processed.

Of course, the variable itemIndex is expected to increase by 1 every time an item is processed and the next one starts its processing.

This information will be shown in the robot's execution log.

1
2
3
4
5
// Type the text in notepad
windows.typeText(item);

// Press intro
windows.typeText(windows.getKeyboardSequence().typeReturn());

The code snippet above corresponds to the item's processing itself.

Remember that we had opened the Notepad with the previous method, and now we are just writing the item and pressing the Return key.

Besides the interface IKeyboardSequence, there is a simplified version available: the interface IKeyboard.

The next line is the third important notification that we must send to the Server. This time we are notifying that we have finished processing an item and the result of the process. This should be done immediately after the item's processing has ended, so that the statistics reflect accurate data in the console.

1
2
// Notify the server the result of the item processing
server.setCurrentItemResultToOK();

In this case, we are notifying the server that the item has been processed with no errors.

When an item is processed, the possible results are:

  • void setCurrentItemResultToOK(): the item has been completely processed with no errors.
  • void setCurrentItemResultToWarn(): the item has been completely processed, but a warning has been detected.
  • void setCurrentItemResultToFail(): the item's processing has failed.
  • void setCurrentItemResultToIgnore(): the item's processing has been ignored.

The previous methods are overloaded:

  • void setCurrentItemResultToOK(String detail)
  • void setCurrentItemResultToWarn(String detail)
  • void setCurrentItemResultToFail(String detail)
  • void setCurrentItemResultToIgnore(String detail)

so that, besides informing the server about an item's processing result, an appropriate message will be sent in the parameter detail. It is up to us to decide what result should be sent.

Let's review these concepts, which are essential for a proper robot's monitoring from the console. There are three notifications that must be sent to the server:

  • The number of items: server.setNumberOfItems(int numberOfItems)
  • The beginning of an item's processing: server.setCurrentItem(int itemIndex, String itemKey)
  • The result of an item's processing, which depends on the result:
    • void setCurrentItemResultToOK()
    • void setCurrentItemResultToWarn()
    • void setCurrentItemResultToFail()
    • void setCurrentItemResultToIgnore()

or their overloaded versions, which allow us to send a message.

All these methods make up the interface IJidokaStatistics.

Finally, this method includes a screen shot of what our robot is doing, because sometimes it may be interesting to know what is happening in the resource in which the robot is operating.

1
2
// Send a screenshot to the log
server.sendScreen(String.format("Snapshot over %s", item));

We use the method sendScreen(String description) which belongs to the interface IJidokaContext. The parameter String description is the description of the screen shot that we have just made.

The method processItem has ended, so our robot will go on its workflow to run the method hasMoreRegisters.

1
2
3
4
5
6
7
8
/**
 * Action 'More Registers?'.
 * 
 * @throws Exception
 */
public String hasMoreRegisters() throws Exception {
    return "no";
}

In this method, we find something new: it is a conditional action, that is, it creates a fork in the robot's workflow. The path that will follow our robot will depend on the value returned by the method hasMoreRegisters. A conditional action can define multiple branches.

In our robot, the method hasMoreRegisters returns "no" without further verifications. Typically, a more complex robot should determine if there are any items left to be processed and return the appropriate value.

Assuming that our robot takes the path labeled with "no", the next method in the execution is closeNotepad (remember that this robot always returns "no" in the previous conditional action, hence it has no other choice; however, in any conditional action there must be always at least one second path).

1
2
3
4
5
6
7
8
9
10
11
/**
 * Action 'Close Notepad'.
 * 
 * @throws Exception
 */
public void closeNotepad() throws Exception {
    
    // alt+F4 + pause + "n"
    windows.typeText(windows.getKeyboardSequence()
            .typeAltF(4).pause().type("n"));
}

This method will close the notepad by sending the keystroke sequence Alt+F4. To do so, it uses the method IKeyboardSequence typeAltF(int numberF) from IKeyboardSequence. This method emulates this kind of key combinations.

Alt+F4 will close the notepad, but the application will ask if we want to save the file. By adding type("n") to the keystroke sequence, we will be choosing the option "No" in the dialog box. Notice that just before that key, we have entered a pause with the method pause().

As we have mentioned earlier, this pause is necessary to adapt the robot's processing speed to the time needed by the application to open the dialog box, a pause that a human user would do.

Finally, the robot will reach the final action of the workflow.

1
2
3
4
5
6
7
/**
 * Action "End".
 * 
 * @throws Exception
 */
public void end() throws Exception {
}

This is a void method that marks the end of the workflow.

The method cleanUp

1
2
3
4
@Override
public String[] cleanUp() throws Exception {
    return null;
}

The method cleanUp is declared by default within the interface, therefore we don't need to implement it in our class.

Appian RPA will always call this method, whether the workflow has ended without errors, or some exception has been thrown, or the user has canceled the robot's execution from the console.

This method is ideal for releasing resources, deleting temporary files and eventually uploading files to the server. To upload files to the server, it must return an array String[] containing the full paths to the files you want to upload.

It is a good practice to leave the resource in which the robot has run in the same status as it was before the execution. For example, if the robot has opened a browser, it should close it after ending its process.

Open in Github

On This Page

FEEDBACK