Free cookie consent management tool by TermsFeed Context Robotic Task Tutorial [Appian RPA v9.4]
Context Robotic Task Tutorial
The capabilities described on this page are included in Appian's standard capability tier. Usage limits may apply.

The following content is based on the previous version of the robotic task screen.

In this tutorial, we are going to implement a robotic task whose main goal is to show how to work properly with the context across executions of the same robotic task.

The context class allows storing persistent information across executions. The use of this functionality permits a new robotic task execution to know about the final conditions of the previous one, which makes it easier to implement reentrant robotic tasks, that is, those capable to resume a process from the last item in which the previous execution stopped.

However, to illustrate this example we have used in another way, showing how to read, update or reset the context. Specifically, this robotic task is in charge of checking the web driver versions used to connect Selenium with the browsers supported by Appian RPA Browser module. In case that a new version is found in the download pages, the execution will finish with a warning for the corresponding browser. For this reason, the items to process here will be the browsers. A possible use of this robotic task would be the creation of an alert when this happens, making it possible to notify that a new driver has been released for a specific browser.

Source Code and Support Files

Description Link
Source Code robot-tutorial-context.zip
Chrome Driver v2.35 chromedriver.exe

Review Browser module architecture page for other browser versions.

Configuration

Environment

  • Development:
    • IDE: Eclipse
    • JDK 1.8
    • Maven 3
    • Appian RPA modules:
      • Client
  • Host Machine:
    • OS: Windows
    • JRE 1.8
    • Applications:
      • Firefox or Chrome browser

Eclipse Project

You must import the Eclipse project included in the zip file attached at the beginning of this tutorial. After importing the project, it is very important to modify the pom.xml file. You have to fill in the parent tag with the version of Appian RPA you are using, and change the profile tag with the configuration of your repository.

Workflow

The robotic task will navigate to each web driver download page and check the last released version for each one.

Once this information is extracted, it will retrieve the last version of each browser stored in the Appian RPA server context and will compare it with each of the just found on the pages. Depending on this comparison, it will set an OK for the browsers (items) which version has not changed, whilst a warning will be set for those browsers for which a new version exists.

rpa-context-workflow.png

You can import this workflow using this file. To import the workflow, you have to click in the import button (2233684.png), and paste the data included in the file.

Support Files

This robotic task will use Chrome, thus needing its driver, chromeWebDriver, as a support file to work. It could also be added as a global support file instead.

2230664.png

Implementation

Before going on, we should know that the context is only read once at the beginning of an execution. This way, any change made on it will not be reflected until the next execution.

In this implementation, we have created a context class, called DriverContext, that is the type of the object to use for keeping the data persisted in the Appian RPA server. This class contains only two variables of type String with the driver version as their corresponding values.

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
38
39
40
41
42
43
44
45
46
47
48
49
50
/**
 * Class to store the context across robotic task executions.
 */
public class DriverContext implements Serializable  {

    /**
     * Serial.
     */
    private static final long serialVersionUID = 1L;
    
    /**
     * Default value when the context is created by the first time or it is
     * reset.
     */
    private static final String DEFAULT_VALUE_EMPTY = "empty";
    
    /**
     * Variable to store Chrome driver version into the context.
     */
    private String lastChromeDriverVersion;
    
    /**
     * Variable to store Firefox driver version into the context.
     */
    private String lastFirefoxDriverVersion;
    
    /**
     * Initialization to the default value.
     */
    public DriverContext() {
        lastChromeDriverVersion = DEFAULT_VALUE_EMPTY;
        lastFirefoxDriverVersion = DEFAULT_VALUE_EMPTY;
    }
    
    public String getLastChromeDriverVersion() {
        return lastChromeDriverVersion;
    }
    
    public void setLastChromeDriverVersion(String lastChromeDriverVersion) {
        this.lastChromeDriverVersion = lastChromeDriverVersion;
    }
    
    public String getLastFirefoxDriverVersion() {
        return lastFirefoxDriverVersion;
    }
    
    public void setLastFirefoxDriverVersion(String lastFirefoxDriverVersion) {
        this.lastFirefoxDriverVersion = lastFirefoxDriverVersion;
    }
}

Looking at the robotic task variables definition, we want to stop at the declaration of an object of type IJidokaServer, that we will use to indicate the context class to use by the robotic task: DriverContext.

1
2
3
4
/**
 * Server.
 */
private IJidokaServer<DriverContext> server;

The two first methods navigate to the different pages to look for the last version of each driver, they extract them to store them in the corresponding attributes and write in the execution log the found version. These methods call other private methods in charge of doing these tasks: checkDriver, extractDriverVersion and infoDriver.

1
2
3
4
5
6
7
8
9
10
11
12
/**
 * Checks the Chrome web driver version.
 */
public void checkChrome() {
    
    WebElement we = checkDriver(URL_CHROME,
            XPATH_CHROME_DRIVER);
    
    currentChromeDriverVersion = extractDriverVersion(we, REGEX_CHROME);
    
    infoDriver(currentChromeDriverVersion);
}
1
2
3
4
5
6
7
8
9
10
11
12
/**
 * Checks the Firefox web driver version.
 */
public void checkFirefox() {
    
    WebElement we = checkDriver(URL_FIREFOX,
            XPATH_FIREFOX_DRIVER);
    
    currentFirefoxDriverVersion = extractDriverVersion(we, null);
    
    infoDriver(currentFirefoxDriverVersion);
}

The two first methods navigate to the different pages to look for the last version of each driver, they extract them to store them in the corresponding attributes and write in the execution log the found version. These methods call other private methods in charge of doing these tasks: checkDriver, extractDriverVersion and infoDriver.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
 * Checks the URL passed by parameter, access it and evaluates the XPath
 * expression specified to get an HTML containing the information of the web
 * driver.
 * 
 * @param url
 *            URL to access to
 * @param xpathExpression
 *            expression to evaluate
 * @return the containing the driver information to be
 *         processed later
 */
private WebElement checkDriver(String url, String xpathExpression) {

    // Navigate to the driver page
    browser.navigate(url);

    // WebElement containing the driver version
    return browser.getElement(By.xpath(xpathExpression));
}

The checkDriver method navigates to the URL passed as a parameter and evaluates the XPath expression, also passed as a parameter, to get an object of type WebElement containing information about the web driver version. This object will be used later by the method extractDriverVersion to extract the web driver version. The XPath expressions to obtain each WebElement are defined as constants in the class.

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
/**
 * Extracts the web driver version contained in the
 * specified. If a regular expression is specified, it is applied to get the
 * web driver version.
 * 
 * @param we
 *            the with the web driver information
 * @param regex
 *            the regular expression to evaluate
 * @return the extracted version
 */
private String extractDriverVersion(WebElement we, String regex) {
    
    // If no regular expression is present, return
    if (regex == null) {
        return we.getText();
    }
    
    // A regular expression must be evaluated
    server.info(String.format(
            "Serching web driver using the regular expression %s", regex));
    // Search with regular expression
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(we.getText()); 
    if (m.find()) {
        // The version extracted from the method parameter 'we'
        return m.group();
    }
    
    // Nothing found using the regular expression
    throw new JidokaFatalException(String.format(
            "Web driver not found using the regex %s", regex));
}

The private method extractDriverVersion will use the WebElement object returned by checkDriver to extract the specific version of each browser. If it is not necessary to treat the text contained in parameter we, it will be returned directly using getText(). In other case, it will evaluate the specified regular expression on that text to find the web driver version. The regular expressions used are defined as constants in the class.

1
2
3
4
5
6
7
8
9
10
11
/**
 * Print an INFO message to the execution log to show the driver version.
 * 
 * @param driverVersion
 *            the driver version
 */
private void infoDriver(String driverVersion) {

    server.info(String.format(
            "The current web driver version is %s", driverVersion));
}

The last one of this set of private methods is infoDriver, which will use the extracted text of the web driver version to write in the execution log.

Below, we are going to see the method used to retrieve the versions previously stored in the context and compare them with those obtained in the current execution: compareDriversVersions. This way, it is possible to check if any change has been made in any version of the drivers, thus establishing its new value in the context.

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
38
/**
 * Action 'Compare Versions with Context'.
 * 
 * Checks all drivers versions and compares them to those saved previously
 * in the context.
 *
public void compareDriversVersions() {
    
    //Get the context
    DriverContext driverContext = server.getPersistentContextValue();

    if (driverContext == null) {
        server.info("The context does not exist. It was reset or this is is the first time the robotic task is executed");
        driverContext = new DriverContext();
    } else {
        
        server.info("Context retrieved successfully");
        server.info(String.format("ChromeDriverVersion %s",
                driverContext.getLastChromeDriverVersion()));
        server.info(String.format("FirefoxDriverVersion %s",
                driverContext.getLastFirefoxDriverVersion()));
    }

    // Chrome
    server.setCurrentItem(1, "Chrome");
    compareVersion(driverContext.getLastChromeDriverVersion(),
            currentChromeDriverVersion);
    driverContext.setLastChromeDriverVersion(currentChromeDriverVersion);
    
    // Firefox
    server.setCurrentItem(2, "Firefox");
    compareVersion(driverContext.getLastFirefoxDriverVersion(),
            currentFirefoxDriverVersion);
    driverContext.setLastFirefoxDriverVersion(currentFirefoxDriverVersion);
    
    // Set the context
    server.setPersistentContextValue(driverContext);
}

This method delegates in the private method compareVersion to actually make the comparison between the just obtained version and the one stored in previous executions. To do so, it calls this method once per each browser.

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
/**
 * Method to compare the value obtained from the driver web to the values
 * retrieved from the context.
 * 
 * 
 * If there is some differences, the item will be set to WARN.
 * If there is not any difference, the item will be set to OK.
 *  
 *
 * @param previousVersion
 *            version stored in the context
 * @param currentVersion
 *            version obtained from the web
 */
private void compareVersion(String previousVersion, String currentVersion) {
    
    if (currentVersion.equals(previousVersion)) {

        server.info(String.format(
                "The web driver has not changed: '%s'", currentVersion));
        server.setCurrentItemResultToOK(currentVersion);
    } else {
        
        String wrnMsg = String.format(
                "The web driver has changed. Previous version was '%s', New version is %s'",
                previousVersion, currentVersion);
        server.info(wrnMsg);
        server.setCurrentItemResultToWarn(wrnMsg);
    }
}

Finally, in the method end, apart from closing the browser, the context is reset in case that it is specified as an input variable in the robotic task.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * Action 'End'.
 * 
 * Resets the context in case the robotic task execution indicates so.
 */
public void end() {
    
    Map<String, String> parameters = server.getWorkflowParameters();
    
    boolean reset = Boolean.parseBoolean(
            parameters.get(RESET_CONTEXT_PARAM));
    
    if (reset) {
        server.resetPersistenContextValue();
        
        server.info("The context was reset");
    }
    
    // Close the browser
    browser.close();
}

Execution

Once the robotic task is implemented, it will be deployed to the Appian RPA repository.

mvn clean deploy

Optionally, when the robotic task is going to be launched, it is possible to specify an additional input variable of type boolean to try to reset the context at the end of the execution. This is done to help to understand how this functionality works.

rpa-context-exec-options.png

Below, it is shown the log trace of the first execution of this robotic task or when the context was reset in a previous execution, that is, when the context is not set.

2230680.png

Once the context has been set, and assuming that the extracted versions don't change, this would be the result:

2230681.png

In subsequent executions, the result will be like the last one until some of the driver versions change.

Open in Github Built: Fri, Feb 23, 2024 (09:13:35 PM)

Context Robotic Task Tutorial

FEEDBACK