processing element

Writing a Custom Processing Element

Version: 17.07

Overview

Project-X Framework provides you the ability to write your own Processing Elements for any custom requirement and use them in the Integration Flows. This documentation describes how to write a custom processing element and use it in your integration flows easily.

Writing a Custom Processing Element

You can write a custom processing element using the Ultra Studio by going through the following steps. In this guide we will be developing a custom processing element that will obtain an input, i.e. the user name from the user as a parameter and write Hello ${username} to the console whenever a message goes through it.

Create a new Processing Element class

First within the src/main/java directory of your Ultra Project, create a new Java package (com.acme.esb as in this example) and then create a new processing element by right clicking on the package name, and selecting New → Processing Element. Specify ConsoleLogger as the element Name.

After that a Java class will be created as follows.

package com.acme.esb;

import org.adroitlogic.x.api.ExecutionResult;
import org.adroitlogic.x.api.XMessageContext;
import org.adroitlogic.x.annotation.config.Processor;
import org.adroitlogic.x.api.config.ProcessorType;
import org.adroitlogic.x.base.processor.AbstractProcessingElement;

@Processor(displayName = "", type = ProcessorType.CUSTOM)
public class ConsoleLogger extends AbstractProcessingElement {

    @Override
    public ExecutionResult process(XMessageContext msgContext) {
        //TODO: execute any processing logic
        return ExecutionResult.SUCCESS;
    }
}

As you can see, ConsoleLogger class is extended from the AbstractProcessingElement class. Whenever you write a custom processing element, you must extend from this class since it abstract out all the functionalities required by Project-X framework to use the custom processing element properly.

Configure @Processor annotation

Further, there is an annotation named @Processor associated with the class. This annotation is used to obtain information about this processing element in the design view. The following properties of this annotation should be configured correctly based on the functionalities of the new processing element.

type

This represent the subcategory that the custom processing element belongs to under the processors category. You can specify any value (GENERIC, TRANSFORMER, FLOW_CONTROLLER, VALIDATOR, CUSTOM, EIP, SCOPE) under org.adroitlogic.x.api.config.ProcessorType enum.

displayName

This value is showed in the component pallet to represent the processing element along with the icon of the element.

iconFileName

Name of the icon file to be assigned with this custom processing element.

The icon file name MUST match the file name in the icon repository and the extension of the icon should be .svg.

scope

Mainly there are Integration Flows and Sub Flows. You can specify any value (ALL, NONE, INTEGRATION_FLOW, SUB_FLOW) from the org.adroitlogic.x.api.config.ScopeType enum. If you specify INTEGRATION_FLOW, then this element will be shown only in integration flow file’s component pallet, and same goes for SUB_FLOW as well. Default value is ALL i.e. the particular component will be shown in all flow files.

description

A brief description to explain the functionality of your element. This will be shown under documentation tab in the property pane.

requireConfiguration

If the value is true, when a user add this component to the design canvas, the property pane will be shown automatically and if the value is false, the property container will not be shown after adding this component to the design pane.

Now let’s modify this annotation properties as below.

@Processor(displayName = "Console Logger",
           type = ProcessorType.CUSTOM,
           requireConfiguration = true,
           description = "This element adds a log line to the console")

Get parameters from user

First of all we need the user’s name as an input for our custom logic. Hence, we can add a String type class variable and annotate it with @Parameter annotation as below.

@Parameter(displayName = "User Name",
           inputType = InputType.TEXT_BOX,
           placeHolder = "John",
           propertyName = "userName",
           description = "Specify the username to be displayed on the console")
private String userName;
When an Parameter is added to a processing element, the corresponding setter method should also be added.

The following properties of this annotation should be configured based on the parameters usage.

displayName

The name to be displayed for the parameter in the property pane.

order

If there are more than one parameter, the order in which this property should be shown on the user interface.

inputType

The type of expected input. You can use any of the follwing values,

  • TEXT_BOX - Simple text box

  • SELECT - Dropdown select list

  • CHECK_BOX - check box input

  • RESOURCE - dropdown list which contains resource bean ID’s in the project.xpml

  • FILE - File Path, with a file browser

or any other value under org.adroitlogic.x.api.config.InputType enum.

description

A small description about the parameter, which will be displayed along with the parameter input in the property pane.

propertyName

Name of the property name to be used if the particular parameter should be externalized.

placeholder

A placeholder value for the parameter.

possibleValues

An array of strings with possible values for the parameters.

This should be only used along with the SELECT inputType to specify the inputs in the select List.

validator

This is a regular expression which will be validated against the user input. You can specify your own regular expression to validate the user input.

isOptional

Specifies whether this parameter is optional. Default is false.

category

The name of the tab in which this parameter should be included in the property pane.

defaultValue

Any default value which should be displayed.

Writing custom logic

Now we can move on to writing our custom logic. We need to write our logic within the process(XMessageContext messageContext) method of the processing element because, when the framework execute the message flow, this method will get executed. Within the process() method, you will get the messageContext as a method parameter.

Let’s write a simple info level log line to log the user name to the console each time a message is received.

@Override
public ExecutionResult process(XMessageContext messageContext) {
    logger.info("Hello {}", userName);
    return ExecutionResult.SUCCESS;
}

Passing Message Context to the next element

After executing our logic, we need to pass the message context to the another processing element in the message flow. This step is optional. Alternatively you can write an element which can be used as the last processing element of the flow as well. In-order to add a next element, you need to add a XProcessingElement type class variable with @Outport annotation as below.

When an Outport is added to a processing element, the corresponding getter and setter methods should also be added.
@OutPort(displayName = "Next Element",
       description = "Success output from the ConsoleLogger")
XProcessingElement nextElement;

The following properties of the @outport annotation should be configured.

displayName

The name to be displayed when user hover on the outport.

description

A brief description about under what circumstance an output will be emitted through this outport. This description will be shown in the documentation tab on the property pane.

Now the process method can be modified as below to send the Message Context to the next outport after processing.

@Override
public ExecutionResult process(XMessageContext messageContext) {
    logger.info("Hello {}", userName);
    return nextElement.processMessage(messageContext);
}

Complete class and compiling

Following is the complete class of the processing element we developed so far.

package com.acme.esb;

import org.adroitlogic.x.annotation.config.OutPort;
import org.adroitlogic.x.annotation.config.Parameter;
import org.adroitlogic.x.annotation.config.Processor;
import org.adroitlogic.x.api.ExecutionResult;
import org.adroitlogic.x.api.XMessageContext;
import org.adroitlogic.x.api.config.InputType;
import org.adroitlogic.x.api.config.ProcessorType;
import org.adroitlogic.x.api.processor.XProcessingElement;
import org.adroitlogic.x.base.processor.AbstractProcessingElement;

@Processor(displayName = "Console Logger",
           type = ProcessorType.CUSTOM,
           requireConfiguration = true,
           description = "This element adds a log line to the console")
public class ConsoleLogger extends AbstractProcessingElement {

    @OutPort(displayName = "Next Element",
            description = "Success Output from the ConsoleLogger")
    XProcessingElement nextElement;

    @Parameter(displayName = "User Name",
               inputType = InputType.TEXT_BOX,
               placeHolder = "John",
               propertyName = "userName",
               description = "Specify the username to be displayed on the console")
    private String userName;

    @Override
    public ExecutionResult process(XMessageContext messageContext) {
        logger.info("Hello {}", userName);
        return nextElement.processMessage(messageContext);
    }

    public XProcessingElement getNextElement() {
        return nextElement;
    }

    public void setNextElement(XProcessingElement nextElement) {
        this.nextElement = nextElement;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

Now Let’s compile the project via mvn clean install command. After the compilation is done, open the desired Integration Flow and in the component pallet, under processors/custom you can see our new processing element.

When you add the new element to the design pane, you can see that the property pane is automatically opened and there is a property named User Name. Specify your name and save the property and modify the flow as shown below.

custom processor screenshot

Now let’s run the project and send a new message. If you inspect the console log, you can see our custom message is printed with the user specified property.

Sequenced Processing Element

A sequenced processing element is a processing element that has a single Outport (except for the On Exception outport), and its task is to perform a specific processing on the Message Context and forward the resulting context to that single outport.

If you are writing a such Sequenced Processing Element, you can extend the Java class of the processing element from the super class org.adroitlogic.x.base.processor.AbstractSequencedProcessingElement instead of AbstractProcessingElement. And implement the method sequencedProcess(XMessageContext messageContext) instead of process(XMessageContext messageContext) method as we did in this guide.

Extending from AbstractSequencedProcessingElement will automatically add a next Outport to the processing element and the Message Context will be automatically forwarded to this outport once the sequencedProcess() method is done.

In this topic
In this topic
Contact Us