View Source

{section}
{column}

{warning}This version must be installed on [Petals ESB 5.3.0|petalsesb530:Petals ESB 5.3.0]+{warning}

{warning}Previous service units are no more compliant with this component version and must be migrated. See [Migrating service units developped for previous versions|#migration]{warning}

h1. Exposing a Java class as a POJO service (Provides mode)

h2. Usage

The POJO that you want to develop must follow certain constraints :
* no specific interface implementation is required.
* if a {{public setComponentContext(ComponentContext context)}} setter method is defined, the component set its {{ComponentContext}} instance with this method at the initialization of the Service Unit.
* if a {{public setDeliveryChannel(DeliveryChannel channel)}} setter method is defined, the component set its {{DeliveryChannel}} instance with this method at the initialization of the Service Unit.
* if a {{public setLogger(Logger logger)}} setter method is defined, the component set its {{Logger instance}} with this method at the initialization of the Service Unit.
* if a {{public void init()}} method is defined, the component invoke it at the initialization of the Service Unit.
* a {{public boolean onExchange(Exchange exchange, Optional<Boolean> currentFlowTracingActivation, AbstractJBIListener jbiLIstener)}} MUST be provided.
* a {{public boolean onAsyncExchange(Exchange subExchange, AsyncContext asyncContext, AbstractJBIListener jbiListener)}} CAN be provided, optionally.
* a {{public void onExpiredAsyncExchange(Exchange subExchange, AsyncContext asyncContext, AbstractJBIListener jbiListener)}} CAN be provided, optionally.
* all methods can throw exceptions.
* FaultException is used to represent business faults (as declared in the WSDL contract): the XML content of the Fault is passed to the constructor of the exception,
* only one instance of the POJO class is instanciated by the component, so the POJO must be state-less and thread-safe,
* to prevent memory leak, using of the singleton pattern is to prohibit.

When building such a Service Unit using Maven, the classes {{ComponentContext}} and {{DeliveryChannel}} are provided by the dependency {{petals-jbi}}, {{AbstractJBIListener}} and {{AsyncContext}} by {{petals-cdk-core}}, and {{Exchange}} by {{petals-cdk-api}}. These dependencies must be defined using the scope {{provided}} as they are provided by the container.

{column}
{column:width=25%}
{panel:title=Table of contents}{toc:outline=true}{panel}
{panel:title=Contributors}{contributors:order=name|mode=list|showAnonymous=true|showCount=true|showLastTime=true}{panel}
{column}
{section}

h3. Process a service in the synchronous way

A sample class following the above rules for processing service in the synchronous way:
{code:java}
package test;
import java.util.logging.Level;
[...]
import org.ow2.petals.component.framework.listener.AbstractJBIListener;

public class SamplePojoService {
Logger logger;
ComponentContext ctx;

public void setComponentContext(ComponentContext ctx) {
this.ctx = ctx;
}
public void setLogger(Logger logger) {
this.logger = logger;
}

public boolean onExchange(Exchange exchange, Optional<Boolean> currentFlowTracingActivation, AbstractJBIListener jbiListener)
throws MessagingException {
[...]
jbiListener.sendSync(anotherExchange);
[...]
return true;
}

public void init() {
logger.log(Level.INFO, "Sample Pojo inits.");
}
}
{code}

The method {{onExchange(Exchange exchange, Optional<Boolean> currentFlowTracingActivation, AbstractJBIListener jbiListener)}} is invoked when an exchange is received from the component that is addressed to the current POJO endpoint.
The POJO must process the service in that method.
The POJO can invoke any 'sub-service' during its processing by synchronous invocations using the {{jbiListener}} instance.
If the POJO service must reply with a message {{OUT}} or {{FAULT}}, according to the MEP, the method must build and set the message to the current exchange.
Then, the method must return {{true}} to delegate the effective send back of the response or acknowledgment (according to the MEP) to the CDK.
The exceptions should be handled properly during the processing of the method, and set accordingly as error or fault to the exchange.
However, mishandled exceptions will be handled by the CDK as generic exceptions.

h3. Process a service in the asynchronous way

A sample class following the above rules for processing service in the asynchronous way:
{code:java}
package test;
import java.util.logging.Level;
[...]
import org.ow2.petals.component.framework.listener.AbstractJBIListener;

public class SamplePojoService {
Logger logger;
ComponentContext ctx;

public void setComponentContext(ComponentContext ctx) {
this.ctx = ctx;
}
public void setLogger(Logger logger) {
this.logger = logger;
}

public boolean onExchange(Exchange exchange, Optional<Boolean> currentFlowTracingActivation, AbstractJBIListener jbiListener)
throws MessagingException {
[...]
MyAsyncContext myAsyncContext = new MyAsyncContext(...);
[...]
jbiListener.sendASync(anotherExchange, myAsyncContext);
[...]
return false;
}

public boolean onAsyncExchange(Exchange subExchange, AsyncContext asyncContext, AbstractJBIListener jbiListener)
throws MessagingException {
[...]
Exchange originalExchange = asyncContext.getOriginalExchange();
[...]
jbiListener.send(originalExchange);
[...]
return true;
}

public void onExpiredAsyncExchange(Exchange subExchange, AsyncContext asyncContext, AbstractJBIListener jbiListener)
throws MessagingException {
[...Handle here the subExchange timeout...]
}

public void init() {
logger.log(Level.INFO, "Sample Pojo Async inits.");
}
}
{code}
Processing a service in asynchronous way is the best approach when targeting performance, but it's more tedious to develop, and demands an average level in Petals development.
Basically, all is in the data that permit to correlate asynchronous sent exchange and their asynchronous response.
The original exchange is the received by the component and the process of the service start in the {{onExchange(Exchange exchange, AbstractJBIListener jbiListener)}} method.
The method create an asynchronous context, to set the data.
The method can create any 'sub-exchange' and send then asynchronously, with the asynchronous context as parameter.
Then the {{onExchange(Exchange exchange, Optional<Boolean> currentFlowTracingActivation, AbstractJBIListener jbiListener)}} returns {{false}}, as the response or the acknowledgment of the original exchange is not yet ready to be sent back.
Any asynchronous response from the 'sub-exchange' comes back in the {{onAsyncExchange(Exchange subExchange, AsyncContext asyncContext, AbstractJBIListener jbiListener)}} method. During the process of this method, the 'sub-exchange' must be handled according to the MEP, and the returns {{true}} of the method let the CDK send the 'sub-exchange' to the partner.
Once all 'sub-exchanges' are received, the 'original' exchange can be retrieve from the asynchronous context and the response or acknowledgement send back explicitly.
If a 'sub-service' do not response at time, the {{onExpiredAsyncExchange(...)}} method will be invoked automatically. You must handle the timeout of the 'sub-exchange' in this method.
Note that once a {{sendAsync(...)}} has expired, the POJO does not have the ownership of the exchange anymore (because it was sent but never came back) and can't access anything else than the exchangeId and the exchange status! The {{AsyncContext}}, which can be subclassed when needed, is there to store needed information in these situations.

h3. Invoking a service provider from your POJO

A service provider can be invoked from your POJO when processing the incoming request in method {{onExchange(Exchange exchange, Optional<Boolean> currentFlowTracingActivation, AbstractJBIListener jbiListener)}}.

First you should retrieve the service consumer associated to the service provider to invoke as following:
{code:java}
final Consumes consume = jbiListener.getComponent().getServiceUnitManager().getConsumesFromDestination(CONSUMED_ENDPOINT, CONSUMED_SERVICE, CONSUMED_INTERFACE, CONSUMED_OPERATION);
{code}
Next, you can create the exchange as following:
{code:java}
final Exchange subExchange = jbiListener.createExchange(consume, MEPPatternConstants.IN_OUT, currentFlowTracingActivation);
{code}
where {{jbiListener}} and {{currentFlowTracingActivation}} are parameters of method {{onExchange(...)}}.

h3. Accessing placeholders

If some configuration parameters are needed for your service provider, you will use properties defined in the properties file configured at component level (see parameter {{properties-file}}).

And so your properties can be accessed through the following API:
{code:lang=java}
jbiListener.getComponent().getPlaceHolders().getProperty("your-property-name")
{code}
where {{jbiListener}} is the JBI listener transmitted through methods {{onExchange(...)}}, {{onAsyncExchange(...)}} or {{onExpiredAsyncExchange(...)}} of your POJO class.

h2. Service provider configuration

The POJO used as service provider implementation is defined and configured in a service unit descriptor.

The POJO JBI descriptor must contain a {{Provides}} section for each POJO to expose, and it is recommend to add a {{Consumes}} section for each service provider invoked from the POJO service.

h3. Configuration

All needed information must be defined in the service-unit JBI descriptor. This JBI descriptor is configured through parameters divided in following groups:
* *JBI parameters* that defines the service provider identification,
* *CDK parameters* that are parameters driving the service provider implementation at CDK layer,
* *CDK interceptor parameters* that are parameters driving interceptors at CDK layer,
* *Dedicated parameters* that are parameters driving the service provider implementation at component layer.

h4. CDK parameters defining service provider implementation
The following parameters correspond to the CDK configuration of the service provider implementation.

{include:0 CDK SU Provide Configuration 5.8.0}

h4. CDK parameters driving interceptors
The following parameters drive interceptors at CDK layer.

{include:0 CDK SU Interceptor configuration 5.8.0}

h4. Dedicated configuration

{table-plus}
|| Attribute || Description || Default value || Required ||
| class-name | The name of the Java class to expose as a service. | {center}\-{center} | {center}Yes{center} |
{table-plus}

h4. Service Unit content

The POJO class(es) and their depending libraries must be set as JAR(s) file(s) at the root directory of the POJO service unit package.

The service unit must contain the following elements, packaged in the archive:
* the META-INF/jbi.xml descriptor file as described above,
* it is also highly recommended to provide a WSDL description for service provider embedded in the service-unit,
* at least one JAR containing the POJO class to expose.

{code}
service-unit.zip
+ META-INF
- jbi.xml (as defined above)
- mypojoclasses.jar (as defined above)
- service.wsdl (recommended)
{code}

h4. Example

An example of a Service Unit descriptor to provide a POJO service:
{code:lang=xml}
<?xml version="1.0" encoding="UTF-8"?>
<jbi:jbi version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jbi="http://java.sun.com/xml/ns/jbi"
xmlns:pojo="http://petals.ow2.org/components/pojo/version-2.0"
xmlns:cdk="http://petals.ow2.org/components/extensions/version-4.0"
xmlns:generatedNs="http://petals.ow2.org/pojo"
xmlns:notifyService="http://petals.ow2.org/samples/notifyService">

<jbi:services binding-component="false">

<jbi:provides endpoint-name="POJOServiceEndpoint"
interface-name="generatedNs:POJO" service-name="generatedNs:POJOService">

<!-- CDK specific elements -->
<cdk:wsdl>MyFileTransferService.wsdl</cdk:wsdl>
<cdk:validate-wsdl>true</cdk:validate-wsdl>

<!-- Component specific elements -->
<pojo:class-name>test.SamplePojoService</pojo:class-name>
</jbi:provides>

<!-- A service consumer declared to invoked another ervice provider from the POJO servcice -->
<jbi:consumes
interface-name="notifyService:emailNotifyTravelRequest"
service-name="notifyService:emailNotifyTravelRequestService">
<cdk:mep>InOnly</cdk:mep>
<cdk:operation>notifyService:travelRequestApproved</cdk:operation>
<cdk:timeout>${email.notifications.timeout}</cdk:timeout>
</jbi:consumes>
</jbi:services>
</jbi:jbi>
{code}

h1. Configuring the component

The component can be configured through the parameters of its JBI descriptor file. These parameters are divided in following groups:
* *JBI parameters* that have not to be changed otherwise the component will not work,
* *CDK parameters* that are parameters driving the processing of the CDK layer,
* *Dedicated parameters* that are parameters specific to this component.

h2. CDK parameters
The component configuration includes the configuration of the CDK. The following parameters correspond to the CDK configuration.

{include:0 CDK Component Configuration Table 5.8.0}

h2. Interception configuration
{include:0 CDK Component Interceptor configuration 5.8.0}

h2. Dedicated configuration

No dedicated configuration parameter is available.

h1. Monitoring the component

h2. Using metrics

Several probes providing metrics are included in the component, and are available through the JMX MBean '{{org.ow2.petals:type=custom,name=monitoring_*<component-id>*}}', where {{*<component-id>*}} is the unique JBI identifier of the component.

h3. Common metrics

{include:0 CDK Component Monitoring Metrics 5.8.0}

h3. Dedicated metrics

No dedicated metric is available.

h2. Receiving alerts

Several alerts are notified by the component through notification of the JMX MBean '{{org.ow2.petals:type=custom,name=monitoring_*<component-id>*}}', where {{*<component-id>*}} is the unique JBI identifier of the component.

{tip}To integrate these alerts with Nagios, see [petalsesbsnapshot:Receiving Petals ESB defects in Nagios].{tip}

h3. Common alerts

{include:0 CDK Component Monitoring Alerts 5.6.0}

h3. Dedicated alerts

No dedicated alert is available.

h1. Business monitoring

h2. MONIT traces

{include:0 CDK SE Business Monitoring Traces 5.8.0}

h2. Flow tracing activation

{include:0 CDK SE Business Monitoring Flow Tracing Activation 5.8.0}

h2. Flow tracing propagation

{include:0 CDK SE Business Monitoring Flow Tracing Propagation 5.8.0}

{anchor:migration}
h1. Migrating service units developped for previous versions

As constraints on POJO class have changed with this new version of the Petals SE POJO, service units developped for previous versions must be updated with new POJO APIs.

Only one API has changed:
{code}
onExchange(Exchange exchange, AbstractJBIListener jbiLIstener)
{code}
that is becommed:
{code}
onExchange(Exchange exchange, Optional<Boolean> currentFlowTracingActivation, AbstractJBIListener jbiLIstener)
{code}

So you can migrate your POJO classes adding the new parameter '{{currentFlowTracingActivation}}' to the API '{{onExchange(...)}}'.