View Source

{section}
{column}

{warning}This version must be installed on Petals ESB 5.0.2+{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 setJBIListener(AbstractJBIListener jbiListener)}} setter method is defined, the component set its {{JBIListener}} 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)}} MUST be provided.
* an {{public boolean onAsyncExchange(Exchange exchange, AsyncContext asyncContext)}} CAN be provided, optionally.
* all methods can throw exceptions.
* FaultException are 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 thread-safe
* to prevent memory leak, using 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 {
AbstractJBIListener jbiListener;
Logger logger;
ComponentContext ctx;

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

public boolean onExchange(Exchange exchange)
throws MessagingException {
[...]
jbiListener.sendSync(anotherExchange);
[...]
return true;
}

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

The method {{onExchange(Exchange exchange)}} 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 {
AbstractJBIListener jbiListener;
Logger logger;
ComponentContext ctx;

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

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

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

public void onExpiredAsyncJBIMessage(Exchange subExchange, AsyncContext asyncContext)
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)}} 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)}} 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)}} 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 {{onExpiredAsyncJBIMessage(...)}} method will be invoked by the CDK. 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.



h2. Service Configuration

h3. Service Unit descriptor

The POJO JBI descriptor must contain a {{Provides}} section for each POJO to expose in the JBI bus.

An example of the POJO SU:

{code:xml}
<?xml version="1.0" encoding="UTF-8"?>
<!-- JBI descriptor for PEtALS' "petals-se-pojo" (POJO), version 2.0 -->
<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:petalsCDK="http://petals.ow2.org/components/extensions/version-4.0"
xmlns:generatedNs="http://POJO/test">
<!-- Import a Service into PEtALS or Expose a PEtALS Service => use a BC. -->
<jbi:services binding-component="false">
<!-- Import a Service into PEtALS => provides a Service. -->
<jbi:provides
interface-name="generatedNs:POJO"
service-name="generatedNs:POJOService"
endpoint-name="POJOServiceEndpoint">
<!-- CDK specific elements -->
<petalsCDK:wsdl xsi:nil="true" />
<!-- Component specific elements -->
<pojo:class-name>test.SamplePojoService</pojo:class-name>
</jbi:provides>
</jbi:services>
</jbi:jbi>
{code}

{include:0 CDK SU Provide Configuration}
\\
{table-plus}



{center}{*}Configuration of a Service Unit to provide a service (POJO)*{center}
|| Parameter || Description || Default || Required ||
| class-name | The name of the Java class to expose as a service. | {center}\-{center} | {center}Yes{center} |
{table-plus}

{include:0 CDK SU Interceptor configuration}

h3. 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 an ZIP archive:
* The META-INF/jbi.xml descriptor file, has described above.
* At least one jar containing the POJO class to expose
{code}
service-unit.zip
+ META-INF
- jbi.xml (as defined above)
- mypojoclasses.jar
{code}

h1. Component Configuration

{include:0 CDK Component Configuration Table 5.6.0}
{include:0 CDK Parameter scope}
{include:0 CDK Component Interceptor configuration}

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.6.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.