Saturday, June 26, 2010

Mule: Transport of Larger Responses in CXF

Upon calling a remote web service via a CXF endpoint in Mule I was presented with the following error:
Caused by: javax.xml.bind.UnmarshalException
- with linked exception:
[com.ctc.wstx.exc.WstxIOException: Connection reset]
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(UnmarshallerImpl.java:426)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:362)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:339)
at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:537)
... 96 more

At first, I thought either my request or the response from the remote server was malformed XML since the exception class and stack trace seems to suggest a marshalling problem. On the other hand, the exception mentions a connection reset.

To help spare you kind readers the details of my investigation, it turns out the above problem only manifested itself when a large amount of data was being transferred between the services.

The Mule CXF Transport documentation lists an attribute, mtomEnabled, that can be enabled on the definition of the outbound endpoint for the remote service:

    <cxf:endpoint name="remoteService"
address="http://constanza.com/service/architectureService"
clientClass="com.costanza.ArchitectureService"
wsdlPort="ArchitectureServicePort"
wsdlLocation="http://constanza.com/service/architectureService?wsdl"
operation="getBlueprint"
mtomEnabled="true"/>

The attribute turns on the SOAP Message Transmission Optimization Mechanism which encodes the response payload for travel between the services. The Mule documentation refers to this allowing for data to be sent as an attachment. At the very least it tells CXF to be on the look out or to handle a potentially large response.

Tuesday, June 22, 2010

WSDLs and Message Parts not recognized

I recently ran into an interesting problem consuming a web service where a call to the service produced the following error message:

Message part {http://myservice.com/}getSets was not recognized.  (Does it exist in service WSDL?)

I originally tested the service using soapUI with no problem, but when I tried to invoke the service from elsewhere I was presented with the error.

My service WSDL was auto-generated by CXF. Here I found I had to tweak it a little to help it better conform to the doc/literal style. The message part declaration for the getSets operation originally looked something like this (nothing special):

<wsdl:message name="getSets">
<wsdl:part element="tns:getSets" name="parameters">
</wsdl:part>
</wsdl:message>

The definition of the referenced getSets element is where the problem was hiding. The element declaration contained a reference to a complexType instead of having the complexType defined within, or as part of, the element declaration.

The original element defintion:

<xs:element name="getSets" type="tns:getSets"/>
<xs:complexType name="getSets">
<xs:sequence>
<xs:element minOccurs="0" name="shipment" type="xs:string"/>
</xs:sequence>
</xs:complexType>

The new definition that allows calls from both soapUI and another client to work:

<xs:element name="getSets">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="shipment" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>

Hopefully this can help someone out who runs into something similar.