Version: 17.07
Developer Guide
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.
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.
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.
@Processor
annotationFurther, 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.
|
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
|
||
|
This value is showed in the component pallet to represent the processing element along with the icon of the element. |
||
|
Name of the icon file to be assigned with this custom processing element.
|
||
|
Mainly there are Integration Flows and Sub Flows. You can specify any value (ALL, NONE, INTEGRATION_FLOW, SUB_FLOW) from
the |
||
|
A brief description to explain the functionality of your element. This will be shown under documentation tab in the property pane. |
||
|
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")
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.
|
The name to be displayed for the parameter in the property pane. |
||
|
If there are more than one parameter, the order in which this property should be shown on the user interface. |
||
|
The type of expected input. You can use any of the following values,
or any other value under |
||
|
A small description about the parameter, which will be displayed along with the parameter input in the property pane. |
||
|
Name of the property name to be used if the particular parameter should be externalized. |
||
|
A placeholder value for the parameter. |
||
|
An array of strings with possible values for the parameters.
|
||
|
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. |
||
|
Specifies whether this parameter is optional. Default is |
||
|
The name of the tab in which this parameter should be included in the property pane. |
||
|
Any default value which should be displayed. |
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;
}
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.
|
The name to be displayed when user hover on the outport. |
|
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);
}
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.
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 Extending from |