Queues Robot Template

The Queues template details how to create a robotic process that evaluates and treats items within a queue. Think of a queue as a container. Within the container, there are a series of items that represent different elements that the robotic process will interact with. Each item contains two sets of attributes: data about the state of the item in the queue, and functional data.

This template is similar to the Excel Data Provider template in that your robotic process will iterate through a series of items; however, instead of using an Excel file to source your items, you will use a queue. The primary benefit to using queues is that several robotic processes can take part in processing the items, allowing for an even faster automation.

When you use a template to create your robotic process, you are provided with a ZIP file containing your source code and a pre-built workflow in the Robotic process configuration page. This page explains the contents of the workflow and the source code generated by the template. For more information on process queues, see the Process queues module.

Workflow

queues-robot-workflow.png

The Queues template's workflow contains seven actions: Start, Select queue, More items?, Log functional data, Update queue item, Close queue, and End. Similar to an Appian process model, each workflow has a start and end action.

The rest of the actions are related to opening a queue and then processing its items. If you click the list icon 951644.png on any action, you'll see it is associated with a method. These methods are in the source code generated from the template. Within the source code, Appian has provided an outline of how you can configure each method.

This workflow assumes the queue is already created and ready to be used. To create a queue for your own robotic process, go to the Monitoring tab in the console.

Source code

The source code contains a class named RobotQueuesTemplate that implements the IRobot interface and is annotated with @Robot. Every Appian RPA robotic process must have the IRobot interface and @Robot annotation to allow the Appian RPA API to identify the class as a robot.

RobotQueuesTemplate includes several methods and attributes. Some of the methods are directly associated with workflow actions; however, the template also generates additional methods that are called by the platform to prepare a robotic process or clean up a resource after the process ends.

The class contains the following methods:

Method Description Associated Action
startUp() Called by the platform prior to the execution of the actions in the workflow. -
start() Provides initial information to the process. Start
selectQueue() Retrieves the queue to use in a robotic process. Select queue
hasMoreItems() Implements the workflow-guided loop and reserves an item. More items?
logFunctionalData() Sends the functional data of an item to the server. Log functional data
updateItemQueue() Releases the reserved item and changes the item's status. Update queue item
closeQueue() Closes the queue once all items have been processed. Close queue
end() Provides any final information to the process. End
cleanUp() Called by the platform after all workflow actions have been executed, regardless of the execution's results. -

Attributes

The first few lines in the template's source code reference the attributes related to the robotic process:

  • IJidokaServer (line 34) creates an instance of IJidokaServer. The interface IJidokaServer is responsible for communicating with the Appian RPA Server. The server is what communicates information to the console.
  • IQueueManager (line 37) creates an instance of IQueueManager. The interface IQueueManager contains all the methods an Appian RPA robotic process needs to use queues.
  • private IQueue currentQueue; (line 40) indicates the current queue. The interface IQueue represents a queue.
  • private int currentItemIndex; (line 42) indicates the current item index within the array of items.
  • private IQueueItem currentItemQueue; (line 44) indicates the current item in the queue. The interface IQueueItem represents an item in a process queue.
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@Robot
public class RobotQueuesTemplate implements IRobot {

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

/** The IQueueManager instance. */
private IQueueManager qmanager;

/** The current queue. */
private IQueue currentQueue;
/** The current item index. */
private int currentItemIndex;
/** The current item queue. */
private IQueueItem currentItemQueue;

startUp() method

The startUp() method can be used to verify conditions on your resource before executing the actions in your workflow. For example, you can verify if an application is available, determine the screen resolution, or verify that the robotic process can be executed. This is also where you can initialize the different instances needed by the robotic process.

In this template, the startUp() method is where the instances of IJidokaServer (line 54) and IQueueManager (line 56) are initialized.

53
54
55
56
57
58
public boolean startUp() throws Exception {
	server = (IJidokaServer<?>) JidokaFactory.getServer();
	// initialize the QueueManager
	qmanager = server.getQueueManager();
	return IRobot.super.startUp();
}

start() method

The start() method is used to define the initial actions of the workflow and is associated with the Start action. This is also where you can initialize objects that will be used by the robotic process if you do not want to use the startUp() method.

In this template, the start() method is used to send a log message of type info to the server indicating that the process is starting (line 66).

65
66
67
public void start() throws Exception {
		server.info("Starting process");
	}

selectQueue() method

The selectQueue() method retrieves the queue to use in the process using its unique identifier. This method uses conditional logic to select a queue so it can handle exceptions that occur when a queue is not available. Additionally, you can use this method to communicate to the server how many items your process will be iterating through.

Before you can use this method to retrieve a queue, you first need to select one from the Appian RPA Console.

To select a queue from the console:

  1. Open the robotic process's configuration and click the Execute icon. The Execute robotic process page appears.
  2. In the Execution options window, use the Queue field to select a queue.

rpa-select-queue-method.png

Once you've selected a queue in the console, the queue's ID can be retrieved using the selectQueue() method.

To ensure a queue was selected in the console, the template starts with an if-else statement to notify the server if a queue was not selected.

  • qmanager.preselectedQueue() (line 75) identifies the pre-selected queue by its unique ID.
  • server.warn("No queue selected"); (line 76) sends a log message of type warn to the server.

Otherwise, if the selected queue is not empty, then an instance of IQueue is returned using the queue's unique identifier.

  • String selectedQueueID = qmanager.preselectedQueue(); (line 79) return the identifier of the selected process queue and assigns it to selectedQueueID.
  • server.info("Selected queue ID: " + selectedQueueID); (line 80) sends a log message of type info to the server with a message indicating the ID of the selected queue.
  • currentQueue = getQueueFromId(selectedQueueID); (line 81) returns the IQueue instance from the IQueueManager object using the queue's unique identifier. This value is then assigned to currentQueue.

Another if statement is included to handle a situation in which the unique identifier does not match an existing queue's ID. If currentQueue has a value of null, then a log message of type debug is sent to the server indicating that the queue was not found (line 83).

Lastly, this method calls server.setNumberOfItems() (line 87) to inform the server about the number of items to process from the queue. The parameter currentQueue.pendingItems() retrieves the number of pending items to process from the queue defined in currentQueue.

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
public void selectQueue() throws Exception {

	if (StringUtils.isBlank(qmanager.preselectedQueue())) {
		server.warn("No queue selected");
		throw new Exception("No queue selected");
	} else {
		String selectedQueueID = qmanager.preselectedQueue();
		server.info("Selected queue ID: " + selectedQueueID);
		currentQueue = getQueueFromId(selectedQueueID);

		if (currentQueue == null) {
			server.debug("Queue not found");
			return;
		}
		server.setNumberOfItems(currentQueue.pendingItems());
	}
}

hasMoreItems() method

The hasMoreItems() method iterates through the queue's items. This method implements the workflow-guided loop and is associated with a conditional action.

Unlike generic actions, conditional actions can only return string or boolean values because the values must match the output labels on your conditional workflow action. For example, if the hasMoreItems() method returned a boolean value, there would only be two possible outputs for the condition and the output labels would be true and false.

However, the More Items? action in the template's workflow returns two outputs with the labels yes and no, so the method needs to return a string value. When the method returns a string, there can be two or more outputs, and the outputs must match the output labels.

This method begins by calling currentItemQueue = getNextItem(currentQueue); (line 99), which asks the server for the next item to process by calling the reserveItem() method. The item is then assigned to currentItemQueue.

Using an if statement, the method then determines which output to return. If currentItemQueue is not null, then the output is yes. The server.setCurrentItem(currentItemIndex++, currentItemQueue.key()); (line 103) will inform the server that the item is going to start being processed. The setCurrentItem() method includes the position of the item within the list of items (currentItemIndex++), and the item's identifying functional data (currentItemQueue.key()). If currentItemQueue is null, then the output is no and the process will move to the next action.

97
98
99
100
101
102
103
104
105
106
107
public String hasMoreItems() throws Exception {
	// retrieve the next item in the queue
	currentItemQueue = getNextItem(currentQueue);
	
	if (currentItemQueue != null) {
		// set the stats for the current item
		server.setCurrentItem(currentItemIndex++, currentItemQueue.key());
		return "yes";
	}
	return "no";
}

logFunctionalData() method

The logFunctionalData() method sends the item's functional data in a log message of type info to the server (line 113).

The functional data of an item is a map of strings in a key-value form. These pairs are dependent on each queue since the information stored is relative to the processed item and will be modified according to the process. If the item's functional data has changed, the data will be updated on the item that is loaded on the queue. You will see an example of this in the next method.

112
113
114
	public void logFunctionalData() {
		server.info(currentItemQueue.functionalData());
	}

updateItemQueue() method

Once a reserved item has been processed, the updateItemQueue() method is called to release the item. This method uses the releaseItem() method to remove the reserve of the item and change the status.

In this template, this method also changes the functional data included in the item using the following functions:

  • Map<String, String> funcData = currentItemQueue.functionalData(); (line 125) creates a map object called funcData.
  • String firstKey = funcData.keySet().iterator().next(); (line 127) iterates through the list of keys associated with funcData. This is stored in firstKey.
  • funcData.put(firstKey, funcData.get(firstKey) + " - MODIFIED"); (line 131) associates the value funcData.get(firstKey) + " - MODIFIED" with the key firstKey.

After modifying the functional data, the item is released:

  • ReleaseItemWithOptionalParameters rip = new ReleaseItemWithOptionalParameters(); (line 134) creates an instance of ReleaseItemWithOptionalParameters.
  • rip.functionalData(funcData); (line 135) fills the new object with the newly defined map. This object will be the return parameter in the release function call.
  • rip.setProcess(EQueueItemReleaseProcess.FINISHED_OK); (line 136) determines that the item must finish with a status of OK.
  • server.setCurrentItemResultToOK(currentItemQueue.key()); (line 139) sets the item result to OK.
  • qmanager.releaseItem(rip); (line 140) calls the releaseItem() method, which unlocks and releases the item in the queue.
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
public void updateItemQueue() throws JidokaQueueException {

	// override the functional data in the queue item
	Map<String, String> funcData = currentItemQueue.functionalData();

	String firstKey = funcData.keySet().iterator().next();

	try {	
		funcData.put(firstKey, funcData.get(firstKey) + " - MODIFIED");
		// release the item. The queue item result will be the same
		// as the currentItem
		ReleaseItemWithOptionalParameters rip = new ReleaseItemWithOptionalParameters();
		rip.functionalData(funcData);
		rip.setProcess(EQueueItemReleaseProcess.FINISHED_OK);
			
		// Is mandatory to set the current item result before releasing the queue item
		server.setCurrentItemResultToOK(currentItemQueue.key());
		qmanager.releaseItem(rip);

	} catch (Exception e) {
		throw new JidokaQueueException(e);
	}
}

closeQueue() method

The closeQueue() method is responsible for closing the queue once all pending items have been processed.

If the queue is assigned to several robotic processes concurrently, only the instance of the robotic process handling the last item needs to close the queue or perform other actions like generating an output file, sending an email, etc.

To know if the instance is processing the last item, it needs exclusive access to the queue using the reserveQueue() method.

  • ReserveQueueParameters rqp = new ReserveQueueParameters(); (line 158) creates an instance of ReserveQueueParameters.
  • rqp.setQueueId(currentQueue.queueId()); (line 159) sets the queue ID attribute of the ReserveQueueParameters object to the ID of the currentQueue.
  • IReservedQueue reservedQueue = qmanager.reserveQueue(rqp); (line 160) creates an instance of IReservedQueue.

If reservedQueue returns a null value, meaning an instance of IReservedQueue was not created, then a log message of type debug is sent to the server indicating the queue with the specified ID cannot be reserved (line 163).

If the queue is successfully reserved, then the robotic process checks if there are any pending items to finish processing:

  • If there are pending items (pendingItems > 0), then the robotic process will release the queue (qmanager.releaseQueue(releaseQP);) without closing it (releaseQP.closed(false);). This way, the queue's status is still IN_PROCESS so that other robotic processes can continue to treat the items (line 174). A log message of type info will also be sent to the server indicating the queue was released, but not closed.
  • If there are no more pending items, then the queue will be released (qmanager.releaseQueue(releaseQP);) and closed (releaseQP.closed(true);) (line 180). A log message of type info will also be sent to the server indicating the queue was released and closed.
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
public void closeQueue() {

	try {
		// First we reserve the queue (other robots can't reserve the queue at the same time)
		ReserveQueueParameters rqp = new ReserveQueueParameters();
		rqp.setQueueId(currentQueue.queueId());
		IReservedQueue reservedQueue = qmanager.reserveQueue(rqp);
			
		// Robot can't reserve the current queue
		if (reservedQueue == null) {
			server.debug("Can't reserve the queue with ID: " + currentQueue.queueId());
			return;
		}

		// check for pending items.
		int pendingItems = reservedQueue.queue().pendingItems();

		ReleaseQueueParameters releaseQP = new ReleaseQueueParameters();
		server.info(String.format("The queue has %s pending items", pendingItems));

		if (pendingItems > 0) {
			// release the queue without closing
			releaseQP.closed(false);
			server.info("Queue released without closing");
		} else {

			// release the queue closing it
			releaseQP.closed(true);
			server.info("Queue closed and released");
		}
		qmanager.releaseQueue(releaseQP);

	} catch (Exception e) {
		throw new JidokaFatalException(e.getMessage(), e);
	}
}

end() method

The end() method is used to define the final actions of the workflow and is associated with the End action. In the template, the end() method is used to send a log message of type info to the server indicating that the process has ended (line 195).

194
195
196
	public void end() {
		server.info("Ending process");
	}

cleanUp() method

The cleanUp() method is invoked by the platform when all actions in the workflow have finished their execution, or if the process ended with errors or failed. The purpose of this method is to leave the resource in the same state it was before the robotic process started its execution.

In this template, no special configurations were made in the cleanUp() method because the queue was already closed; however, in your own robotic process, this is where you can add tasks to clean up the resource, like closing an application or logging out.

194
195
196
197
	@Override
	public String[] cleanUp() throws Exception {
		return IRobot.super.cleanUp();
	}

This version of the Appian RPA documentation was written for Appian 20.4, and does not represent the interfaces or functionality of other Appian versions.
Open in Github Built: Mon, Nov 15, 2021 (03:03:53 PM)

On This Page

FEEDBACK