Creating a codelet

Printer-friendly version

A codelet is a simple way of performing operations on task data using Java. In this tutorial, I will create a simple codelet based on the example codelet and explain how to use codelets in workflows. The codelet I am going to create will receive an int as an input variable and the output will be a random number, the maximum being the input number. Of course it is possible to do much more complicated work with codelets, for example load and save data to a database, but the recommended method for that would be an external database gateway.

 

After starting your favourite IDE, you should create a new project and add the standalone .jar of your YAWL version to the libraries of the project. Next you should create a new class and choose a package for the codelet. The default package for YAWL codelets is "org.yawlfoundation.yawl.resourcing.codelets", wich I will be using. The codelet you create should extend the abstract codelet to work properly. We will be creating a constructor for the new codelet and at least two methods. Here is the the constructor for my RandomIntCodelet:

 

    public RandomIntCodelet(){
        super();
        setDescription("This codelet returns a random int, its maximum being the input int.<br> " +
                "Required parameters:<br> " +
                "Input: max (int) - maximum value of randomized number<br>" +
                "Output: r (int)");
    }

The "setDesciption" method lets you define the text, that will be displayed in the codelet menu in the editor for your codelet.

The method, that will be called, when the codelet is executed is "execute":

    public Element execute(Element inData, List<YParameter> inParams,
            List<YParameter> outParams) throws CodeletExecutionException {
        // set the inputs passed in the base class
        setInputs(inData, inParams, outParams);
        
        int max;
        
        try{
            max = Integer.parseInt((String) getParameterValue("max"));
        }
        catch (ClassCastException cce) {
            throw new CodeletExecutionException("Exception casting input values to " +
                                                "int types.") ;
        }
        
        
        //create a random number between 1 and max (input)
        Random generator = new Random();
        int r = generator.nextInt(max) + 1;
        
        //set the value for the output parameter
        setParameterValue("r", String.valueOf(r));
        
        return getOutputData();
    }

As you can see, the method is quite simple in this example. The arguments for the method are the calling workitem's data "inData", the input parameters "inParams", and the output parameters "outParams". If you have input parameter for your codelet, you need to cast or transform them, so you can use them. They are accessed by the "getParameterValue" method (the argument being the name of the input variable). In my codelet, I needed to transform the input to the type "int", which I did in the try block. After that I generated a random number. This is basically the place, where you insert your own code. Finally, if you have output parameters, you need to set them via the "setParameterValue" method for each parameter.

If your codelet will be long running you will need to define the "cancel" method, that will be called if the task is cancelled while being processed. My codelet is rather short so it doesn't really need it:

public void cancel(){}

The last method is the "getRequiredParams" method. It is called when the codelet is selected in the editor and helps to automatically add the needed task variables to the task, so you only need to define the mappings to the task:

    public List<YParameter> getRequiredParams() {
        List<YParameter> params = new ArrayList<YParameter>();

        YParameter param = new YParameter(null, YParameter._INPUT_PARAM_TYPE);
        param.setDataTypeAndName("int", "max", XSD_NAMESPACE);
        param.setDocumentation("maximum random number");
        params.add(param);

        param = new YParameter(null, YParameter._OUTPUT_PARAM_TYPE);
        param.setDataTypeAndName("int", "r", XSD_NAMESPACE);
        param.setDocumentation("randomized number");
        params.add(param);
        return params;
    }

One after another, the parameters are created and defined. If the parameter is of the input type, you use "YParameter._INPUT_PARAM_TYPE" in the constructor otherwise "YParameter._OUTPUT_PARAM_TYPE", the first argument stays "null" in this case. Next the data type and name is set, here both parameters are of the type int and their names being "max" for the input parameter and "r" for the putput parameter. Following this is the documentation and adding the parameter to the parameter list.

After you have compiled your codelet, you need to copy it to correct location in your YAWL installation in my case "[YAWL INSTALL DIR]\engine\apache-tomcat-6.0.18\webapps\resourceService\WEB-INF\classes\org\yawlfoundation\yawl\resourcing\codelets". If the editor is connected to the engine, you can select the codelet from the list of codelets and use it in your workflows.

 

(Notice: This tutorial is based on  YAWL version 2.2.x)

Comments

I placed the file in the specified directory, but it doesn't appear in the editor. What is required for the new class to appear in the editor?

fmannhardt's picture

Did you restart YAWL?  Which version of YAWL do you use? You also need to start the YAWL Engine as mentioned here:

If the editor is connected to the engine, you can select the codelet from the list of codelets and use it in your workflows.

I have tried codelet for RandomIntCodelet and SampleCodelet(In built in the list) in latest version of YAWL(2.3.5) It is giving me below error:

Exception in thread "18.1:unnamed:codelet"
java.lang.abstractMethodError:
org.yawlfoundation.yawl.resourcing.codelets.AbstractCodelet.execute(Lord/jdom2/Element;Ljava/util/ListLjava/util/List;)Lord/jdom2/Element;

But the same Specification and Codelet is working in YAWL2.3 version.

Hey,
when i put your RandomIntCodelet.class into the specified folder everything works just fine. But if load the .java into my IDE (Eclipse luna) and create my own .class, put it to the folder again it doesnt work. No more codelets are shown in the editor at all. Same happens if i create my own desired codelet. So what did i do wrong while creating the class file out of the java file? (your .class file is also bigger regarding the kB)

YAWL Version: 2.3.5 (works neither on 2.2.x)
Java Version: 1.7

ahense's picture

This tutorial explains the way of working in YAWL 4.1:

http://www.yaug.org/content/creating-and-using-codelets