ServiceMix CXF SE

ServiceMix CXF SE component is a JBI Service Engine exposing (annotated) POJO as services on the JBI Bus.

It uses Apache CXF internally to perform service invocations and xml marshaling.

Features:

  • JSR-181 annotations
  • JAXB2/Aegis/XMLBeans databinding
  • WSDL auto generation
  • Java proxy support
  • MTOM / attachments support

Maven Archetype

You can use the servicemix-cxf-se-service-unit archetype to create a CXF SE Service Unit (including a sample POJO):

mvn archetype:create \
  -DarchetypeGroupId=org.apache.servicemix.tooling \
  -DarchetypeArtifactId=servicemix-cxf-se-service-unit \
  -DarchetypeVersion=2010.01 \
  -DgroupId=your.group.id \
  -DartifactId=your.artifact.id \
  -Dversion=your-version

Once you've customized the service unit, simply install the SU:

mvn install
Remember that to be deployable in ServiceMix, the ServiceUnit has to be embedded in a Service Assembly: only the Service Assembly zip file can be deployed in ServiceMix.
To add your SU in a SA, you need to define it in the dependency sets:
<dependency>
  <groupId>your.group.id</groupId>
  <artifactId>your.artifact.id</artifactId>
  <version>your-version</version>
</dependency>

Endpoint Configuration

The CXF SE endpoint provides a property named pojo. You can expose any POJO which contains the @WebService annotation.

A simple example follows:

<cxfse:endpoint>
   <cxfse:pojo>
     <bean class="org.apache.cxf.calculator.CalculatorImpl">
     </bean>
   </cxfse:pojo>
</cxfse:endpoint>

You can use a proxy (see Proxies section of this page):

<cxfse:endpoint>
  <cxfse:pojo>
     <bean class="org.apache.servicemix.cxfse.GreeterImplForClientProxy">
       <property name="calculator">
          <cxfse:proxy service="calculator:CalculatorService" context="#context" type="org.apache.cxf.calculator.CalculatorPortType" />
       </property>
     </bean>
 </cxfse:pojo>
</cxfse:endpoint>
Endpoint Attributes
Name Type Description Required
endpoint String JBI Endpoint name no (will be auto-generated if not specified)
interfaceName QName Interface QName implemented by the JBI endpoint no (will be auto-generated if not specified)
mtomEnabled boolean Enable MTOM / attachment support no (defaults to false)
pojo Object the instanciated POJO to service requests one of pojo or pojoClass
service QName JBI Service name no (will be auto-generated if not specified)
useJBIWrapper boolean Specifies if the endpoint expects to receive the JBI wrapper in the message received from the NMR no (defaults to true,Ignore the value of useSOAPEnvelope if useJBIWrapper is true)
useSOAPEnvelope boolean Specifies if the endpoint expects soap messages when useJBIWrapper is false no (defaults to true)
useXmlBeans boolean Specifies if the endpoint use xmlbeans databinding to marshell/unmarshell message no (defaults to false)
useAegis boolean Specifies if the endpoint use aegis databinding to marshell/unmarshell message no (defaults to false), generally we use aegis databinding with simple frontend
pojoService QName Specifies the servicemodel service name generated from the pojo no (will be auto-generated if not specified)
pojoEndpoint QName Specifies the servicemodel endpoint name generated from the pojo no (will be auto-generated if not specified) pojoService and pojoEndpoint can control the servicemodel generated from pojo, it's equivalent to the annotation in java code, but it's useful when you can't change the java code

Accessing the JBI bus

The prefered way to access the JBI bus is by retrieving a ComponentContext implementation.
If you want to get ComponentContext implementation injected into your POJO, and send a request to another service from your POJO, you need add the following method on your POJO:

private javax.jbi.component.ComponentContext context;

public void setContext(javax.jbi.component.ComponentContext context) {
  this.context = context;
}

By this way, the ComponentContext inject into your POJO automatically
You will be able to use the provided DeliveryChannel to send requests.

Note that only sendSync is allowed for active JBI exchanges (but you have to use send for DONE or ERROR status exchanges).

You can also use the client api:

public void myMethod() {
  ServiceMixClient client = new ServiceMixClientFacade(this.context);
  QName service = new QName("http://servicemix.org/cheese/", "receiver");
  EndpointResolver resolver = client.createResolverForService(service);
  client.send(resolver, null, null, "<hello>world</hello>");
}

You can find a whole context injection test case here

Proxies

You can create java proxies for JBI endpoints, provided that they expose a WSDL.

The basic configuration is the following:

<cxfse:proxy service="calculator:CalculatorService" context="#context" type="org.apache.cxf.calculator.CalculatorPortType" />

You can use it from one of you client bean, or from inside another component, and call the JBI endpoint as a plain Java object.

Proxy attributes
Name Type Description Required
type Class proxy class type yes
endpoint String JBI Endpoint name no (will be auto-generated if not specified)
interfaceName QName Interface QName implemented by the JBI endpoint no (will be auto-generated if not specified)
service QName JBI Service name no (will be auto-generated if not specified)
mtomEnabled boolean Enable MTOM / attachment support no (defaults to false)
useJBIWrapper boolean Specifies if the endpoint expects to receive the JBI wrapper in the message received from the NMR no (defaults to true,Ignore the value of useSOAPEnvelope if useJBIWrapper is true)
useSOAPEnvelope boolean Specifies if the endpoint expects soap messages when useJBIWrapper is false no (defaults to true)

From a CXF SE Service Unit, it could be used as following:

<cxfse:endpoint>
  <cxfse:pojo>
     <bean class="org.apache.servicemix.cxfse.GreeterImplForClientProxy">
       <property name="calculator">
          <cxfse:proxy service="calculator:CalculatorService" context="#context" type="org.apache.cxf.calculator.CalculatorPortType" />
       </property>
     </bean>
 </cxfse:pojo>
</cxfse:endpoint>
private CalculatorPortType calculator;

  public void setCalculator(CalculatorPortType calculator) {
        this.calculator = calculator;
    }

    public CalculatorPortType getCalculator() {
        return calculator;
    }
  public void myMethod() {
    int ret = 0;
        try {
            
            ret = getCalculator().add(1, 2);
                        
        } catch (Exception e) {
            e.printStackTrace();
        }
    ...
  }

You can find a complete proxy test case here

MTOM support

MTOM is a way to handle large amounts of binary data in your services. Unlike attachments, the XML infoset stays the same. MTOM just "optimizes" any base64Binary data you have in your messages. When MTOM is turned on, this base64 data gets sent as a binary attachment saving time and space.

MTOM support can be turned on using:

<cxfse:endpoint mtomEnabled="true" ... />

MTOM is supported for the following classes:

  • DataSource
  • DataHandler
  • byte[]

If you have a bean with the following method:

public String echo(String msg, DataHandler binary) {
  ...
}

you will be able to call it using the following requests:

<echo xmlns:xop='http://www.w3.org/2004/08/xop/include'>
  <msg>hello world</msg>
  <binary>
    <xop:Include href='binary'/>
  </binary>
</echo>

provided that the JBI message contains an attachment named "binary".

You can find a complete MTOM test case here

Interceptors Configuration

Since cxfse is using Apache CXF internally, so you can configure cxf se endpoint with inteceptors which follow cxf inteceptor api.
example per as below

<cxfse:endpoint>
  <cxfse:inFaultInterceptors>
    <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
  </cxfse:inFaultInterceptors>
  <cxfse:inInterceptors>
    <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
  </cxfse:inInterceptors>
  <cxfse:outFaultInterceptors>
    <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
  </cxfse:outFaultInterceptors>
  <cxfse:outInterceptors>
    <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
  </cxfse:outInterceptors>
  <cxfse:pojo>
    <bean class="org.apache.cxf.calculator.CalculatorImpl">
    </bean>
  </cxfse:pojo>
</cxfse:endpoint>

Can find document for CXF interceptors here