Poor Response performance with Axiom
(Let me apologize in advance for my poor English)
Hello,
First, i come from Axis2, and i'm trying to use Jibx with Spring-WS.
I have configured spring to use the StAX "optimised" factory :
Code:
<bean id="messageFactory" class="org.springframework.ws.soap.axiom.AxiomSoapMessageFactory">
<property name="payloadCaching" value="false" />
</bean>
But this is the point : i've compared performance between Axis2 and Spring-Ws with the same JibX beans implementation.
I've figure out that the unmarshalling (request) is fine, but the response is far slower than Axis2. Especially with large SOAP response (>50k)
For the tests, i've used an Axis2 client, with the same jibx beans too. I've put a System.nanoTime() before each send in client side, and in the process Layer in server side. Both client and server (Tomcat 6) are on the same computer.
Axis2 : Request time 50ms, Response time 60ms
Spring-Ws : Request time 50ms, Response time 200ms
So i've taken a look at the code and found some misconception with Jibx marshalling...
Code:
protected void marshalSaxHandlers(Object graph, ContentHandler contentHandler, LexicalHandler lexicalHandler)
throws XmlMappingException {
try {
// JiBX does not support SAX natively, so we write to a buffer first, and transform that to the handlers
ByteArrayOutputStream os = new ByteArrayOutputStream();
marshalOutputStream(graph, os);
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
Transformer transformer = transformerFactory.newTransformer();
SAXResult saxResult = new SAXResult(contentHandler);
saxResult.setLexicalHandler(lexicalHandler);
transformer.transform(new StreamSource(is), saxResult);
}
As you can see, it appears to be time consuming...
This is how JibxMarshaller marshalls the response :
- AxiomResult extends a SaxResult, this is why JibxMarshaller.marshalSaxHandlers() is called
- Jibx beans are marshalled in a ByteArrayOutputStream => OK
- Then this ByteArray goes through a SAXParser, which builds the axiom SOAP Body, using a SoapFactory...
- And then the SOAP envelope is serialized in the TransportOutputStream... (not shown here)
Beans =>(XmlPull)=> ByteArray => SAX => Axiom(StAX) => Result => Stream
Knowing that Jibx does a good job, could we marshall the beans directly inside the SOAP Body ?
This is how Axis2 proceed :
Code:
private org.apache.axiom.om.OMElement mappedChild(Object value, org.apache.axiom.om.OMFactory factory) {
org.jibx.runtime.IMarshallable mrshable = (org.jibx.runtime.IMarshallable) value;
org.apache.axiom.om.OMDataSource src = new org.apache.axis2.jibx.JiBXDataSource(mrshable, bindingFactory);
int index = mrshable.JiBX_getIndex();
org.apache.axiom.om.OMNamespace appns = factory.createOMNamespace(bindingFactory.getElementNamespaces()[index], "");
return factory.createOMElement(src, bindingFactory.getElementNames()[index], appns);
}