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:
- jsr181 annotations
- jaxb2 binding
- wsdl auto generation
- java proxy support
- MTOM / attachments support
Installation
Installing the servicemix-cxf-se component can be done in several ways:
- drop the installer zip in an hotdeploy directory monitored by ServiceMix
- using ant tasks
Note that when using ant tasks, the component is not started, you will have to start it manually using ant tasks or a console.
Deployment
You can deploy Service Units containing a file named xbean.xml for activating consumer and provider endpoints.
This xml file should respect the given syntax, though this is a spring based xml configuration file
See a full example here. Note that you have to define the cxf-se namespace with
<beans xmlns:cxfse="http://servicemix.apache.org/cxfse/1.0">
...
</beans>
Any numbers of endpoints can be specified in the xbean.xml file.
As the main purpose is to expose a POJO, you will have to include the needed class files / jars in the service unit and reference them using the following tags in your xbean.xml configuration file:
<classpath>
<location>.</location>
</classpath>
This will add the content of the location tags (relative to the unzipped service unit) to the classpath. The previous configuration will just add the class files contained in the service unit, as if it is a plain jar.
If you want to embed jars, just use something like
<classpath>
<location>lib/foo.jar</location>
</classpath>
Endpoint
A few examples:
<cxfse:endpoint>
<cxfse:pojo>
<bean class="org.apache.cxf.calculator.CalculatorImpl">
</bean>
</cxfse:pojo>
</cxfse:endpoint>
<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) |
|
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:, "receiver");
EndpointResolver resolver = client.createResolverForService(service);
client.send(resolver, null, null, "<hello>world</hello>");
}
You can find a whole context injection test case here
Lightweight mode
The servicemix-cxf-se component can also be configured in a spring/xbean configuration file, for use in an embedded ServiceMix.
Here is an example of such a configuration:
<sm:activationSpec>
<sm:component>
<cxfse:component>
<cxfse:endpoints>
<cxfse:endpoint>
<cxfse:pojo>
<bean class="org.apache.cxf.calculator.CalculatorImpl"/>
</cxfse:pojo>
</cxfse:endpoint>
</cxfse:endpoints>
</cxfse:component>
</sm:component>
</sm:activationSpec>
| Classpath issues when embedding servicemix-cxf-se component
When using the servicemix.xml configuration file to create cxfse endpoints, you must include the servicemix-cxfse-xxx.jar in your classpath.
You will find this file inside the component installer (./components/servicemix-cxfse-xxx.zip).
Failing this, an IllegalArgumentException will be thrown with the following message:
Component name: xxxxxx is bound to an object which is not a JBI component, it is of type: javax.xml.namespace.QName
or aanother exception with |
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 cxfse 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:pojo>
<bean class="org.apache.cxf.calculator.CalculatorImpl">
</bean>
</cxfse:pojo>
<cxfse:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
</cxfse:inInterceptors>
<cxfse:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
</cxfse:outInterceptors>
<cxfse:inFaultInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
</cxfse:inFaultInterceptors>
<cxfse:outFaultInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
</cxfse:outFaultInterceptors>
</cxfse:endpoint>
Can find document for CXF interceptors here