This documentation is for WSO2 ESB version 4.5.0. View documentation for the latest release.

Writing Tasks Sample

This page describes how to write a custom task. To better illustrate the topic, we provide instructions based on the example.

The created task will read a text file at a specified location and places orders for stocks that are given in the text file is created. The text file has entries such as this one:

IBM,100,120.50

Each line in the text file contains details for a stock order:

  • symbol
  • quantity
  • price

The "PlaceStockOrderTask" will read the text file, a line at a time, and create orders using the given values to be sent to a sample Axis2 server. The text file will then be tagged as processed to include a system time stamp. The task will be scheduled to run every 15 seconds.

The main steps while writing a task are as follows:

  1. Write the Task class
  2. Customize the task
  3. Compile and bundle the task
  4. Add the task to the WSO2 ESB class path
  5. Configure and schedule the task in ESB Console

Step 1. Write the Task Class

The PlaceStockOrderTask class implements org.apache.synapse.startup.Task. Each task should therefore implement the Task interface. This interface has a single execute() method. This method contains the code that is to be run at the specified intervals.

The execute() method contains the following actions:

  1. Check whether the file exists at the desired location.
  2. If it does, then read the file line by line composing place order messages for each line in the text file.
  3. Individual messages are then injected to the synapse environment with the given To endpoint reference.
  4. Set each message as OUT_ONLY since it is not expected any response for messages.

In addition to the execute() method, it is also possible to make the class implement a JavaBean interface. The WSO2 ESB console can then be used to configure the properties of this JavaBean.

The complete code listing of the Task class is provided below:

public class PlaceStockOrderTask implements Task, ManagedLifecycle {
private Log log = LogFactory.getLog(PlaceStockOrderTask.class);
private String to;
private String stockFile;
private SynapseEnvironment synapseEnvironment;

public void execute() {
log.debug("PlaceStockOrderTask begin");

if (synapseEnvironment == null) {
log.error("Synapse Environment not set");
return;    }

if (to == null) {
log.error("to not set");
return;    }

File existFile = new File(stockFile);

if(!existFile.exists()) {
log.debug("waiting for stock file");
return;    }

try {

// file format IBM,100,120.50

BufferedReader reader = new BufferedReader(new FileReader(stockFile));
String line = null;

while( (line = reader.readLine()) != null){
line = line.trim();

if(line == "") {
continue;
}

String[] split = line.split(",");
String symbol = split[0];
String quantity = split[1];
String price = split[2];
MessageContext mc = synapseEnvironment.createMessageContext();
mc.setTo(new EndpointReference(to));
mc.setSoapAction("urn:placeOrder");
mc.setProperty("OUT_ONLY", "true");
OMElement placeOrderRequest = createPlaceOrderRequest(symbol, quantity, price);
PayloadHelper.setXMLPayload(mc, placeOrderRequest);
synapseEnvironment.injectMessage(mc);
log.info("placed order symbol:" + symbol + " quantity:" + quantity + " price:" + price);
}

reader.close();
}

catch (IOException e) {
throw new SynapseException("error reading file", e);
}

File renamefile = new File(stockFile);
renamefile.renameTo(new File(stockFile + "." + System.currentTimeMillis()));
log.debug("PlaceStockOrderTask end");  }

public static OMElement createPlaceOrderRequest(String symbol, String qty, String purchPrice) {
OMFactory factory   = OMAbstractFactory.getOMFactory();
OMNamespace ns      = factory.createOMNamespace("http://services.samples/xsd", "m0");
OMElement placeOrder= factory.createOMElement("placeOrder", ns);
OMElement order     = factory.createOMElement("order", ns);
OMElement price     = factory.createOMElement("price", ns);
OMElement quantity  = factory.createOMElement("quantity", ns);
OMElement symb      = factory.createOMElement("symbol", ns);
price.setText(purchPrice);
quantity.setText(qty);
symb.setText(symbol);
order.addChild(price);
order.addChild(quantity);
order.addChild(symb);
placeOrder.addChild(order);
return placeOrder;
}

public void destroy() {
}

public void init(SynapseEnvironment synapseEnvironment) {
this.synapseEnvironment = synapseEnvironment;
}

public SynapseEnvironment getSynapseEnvironment() {
return synapseEnvironment;
}

public void setSynapseEnvironment(SynapseEnvironment synapseEnvironment) {
this.synapseEnvironment = synapseEnvironment;
}

public String getTo() {
return to;
}

public void setTo(String to) {
this.to = to;
}

public String getStockFile() {
return stockFile;
}

public void setStockFile(String stockFile) {
this.stockFile = stockFile;
}
}

This is a bean implementing two properties - To and StockFile. These are used to configure the task.

Implementing ManagedLifecycle for Initialization and Cleanup

Since a task implements ManagedLifecyle interface, ESB will call the init() method at the initialization of a Task object and destroy() method when a Task object is destroyed:

public interface ManagedLifecycle {
public void init(SynapseEnvironment se);
public void destroy();
}

In PlaceStockOrderTask it is stored the Synapse environment object reference in an instance variable for later use with the init() method. The SynapseEnvironment is needed to inject messages into the ESB.


Step 2. Customize the Task

It is possible to pass values to a task at run time using property elements. In this example, the location of the stock order file and its address was given using two properties within the Task object.

The properties can be:

  • String type
  • OMElement type

Tip

For OMElement type, it is possible to pass XML elements as values in the configuration file.

When creating a Task object, WSO2 ESB will initialize the properties with the given values in the configuration file.

For example, the following properties in the Task class

public String getStockFile() {
return stockFile;
}
public void setStockFile(String stockFile) {
this.stockFile = stockFile;
}

are initialized with the given values within the property element of the task in the configuration.

<syn:property xmlns="http://ws.apache.org/ns/synapse" name="stockFile"value="/home/upul/test/stock.txt"/>

For those properties given as XML elements, properties need to be defined within the Task class using the following format:

public void setMessage(OMElement elem) {
message = elem;}

It can be initialized with an XML elmenent as follows:

(OMElement comes from Apache AXIOM which is used by WSO2 ESB. AXIOM is an object model similar to DOM. To learn more about AXIOM, see the AXIOM tutorial.) 

<property name="message">
<m0:getQuote xmlns:m0="http://services.samples/xsd">
<m0:request>
<m0:symbol>IBM</m0:symbol>
</m0:request>
</m0:getQuote>
</property>

Step 3. Compile and Bundle the Task

Assemble the compiled class Task as a JAR file.


Step 4. Add to the WSO2 ESB Class Path

After compiling and bundling the Task class, you need to add it to the WSO2 ESB class path. Place the JAR file to the repository/components/lib directory of the ESB.

The Task class will be available for use from the next time you start WSO2 ESB.

Notice

It is required to restart the ESB for the JAR containing the task implementation to be picked up by the server runtime. An OSGi bundle containing the task implementation will be created automatically and it will be deployed in the server.


Step 5. Configure and Schedule in ESB Console

After adding the Task class to class path and restarting the WSO2 ESB, you can add configuration settings using the ESB console. Follow the steps given below (for the detailed information on how to schedule tasks see Adding and Scheduling Tasks):

1. Log in to the ESB console.

2. Click the "Main" button to access the "Manage" menu.

3. Click "Scheduled Tasks" in the "Manage" group.

4. Click "Add Task."

5. The "New Scheduled Task" page will open. Enter "placeOrder" as "Task Name."

6. Enter "org.wso2.esb.tutorial.tasks.PlaceStockOrderTask" as "Task Implementation."

7. Click "Load Task Properties."

8. ESB console will load the custom Task class and show you the properties it finds.

9. Enter http://localhost:9000/soap/SimpleStockQuoteService for "To" property. Keep property type as "Literal."

10. Copy the stockfile.txt to a new directory. The stockfile.txt will contain the following entries:

IBM,100,120.50
MSFT,200,70.25
SUN,400,60.758.

Enter stock.txt file location for the stockFile property. Keep property type as "Literal."

11. Select the "Trigger Type" as "Simple."

12. Enter 15000 to "Interval."

13. Click "Schedule."