Spring WS - Part 4

Another interesting and essential feature is the attachment part. Now I found two things out here. The attachment can be inline within the SOAP message body (suitable as long as the attachment size is not too long) or we can enable MTOM feature within the marshaller and leverage the MTOM-XOP feature.

For the attachment to be inline with the SOAP message body, no actual configuration are required, everything is being taken care by the Spring WS framework, except the following:


 <xs:element name="getCountryRequest">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="name" type="xs:string"/>
                <xs:element name="file" type="xs:base64Binary" xmime:expectedContentTypes="application/octet-stream"></xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

In the request type, I have declared an element named file of type type="xs:base64Binary" and Content Type xmime:expectedContentTypes="application/octet-stream"></xs:element>, and the name xmime namespace has been defined as xmlns:xmime="http://www.w3.org/2005/05/xmlmime".
Now on using JAXB2 maven plugin, the type for the request that gets generated, has the following:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "name",
    "file"
})
@XmlRootElement(name = "getCountryRequest")
public class GetCountryRequest {

    @XmlElement(required = true)
    protected String name;
    @XmlElement(required = true)
    @XmlMimeType("application/octet-stream")
    protected DataHandler file;
 .............................
 .......................................

Now, here you can see that file element now has the type DataHandler and it is annotated with @XmlMimeType("application/octet-stream") .
Now we are going to use it in our Client and Service end to extract the Data. if we examine the SOAPMessage which is being logged by both,
1) SoapEnvelopeLoggingInterceptor.java
2) PayloadLoggingInterceptor.java


then, we would see that, the attachment is withing the body of the SOAPMessage as a binary stream, but as said earlier, this approach is not applicable, if the size of the attachment is large, and in that case we have to leverage MTOM-XOP feature, which provides optimum performances in this type of situation.

In order to use MTOM-XOP we need to bring out the following changes in the configuration.
* The configured mrshaller should have the MTOM feature enables i.e.
 @Bean
 public Jaxb2Marshaller marshaller()
 {
  Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
  jaxb2Marshaller.setContextPath("io.spring.guides.gs_producing_web_service");
  jaxb2Marshaller.setMtomEnabled(true);
  return jaxb2Marshaller;
 }

This marshaller is being used in WebServiceTemplate bean to set the mershaller and unmarshaller. This bean we will be using in our Web Based Client(which we will discuss in our coming Posts).
 @Bean
 public WebServiceTemplate webServiceTemplate() throws Exception
 {
  WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
  webServiceTemplate.setMarshaller(marshaller());
  webServiceTemplate.setUnmarshaller(marshaller());
  webServiceTemplate.setDefaultUri("http://localhost:8080/ws/countryService/countries");
  webServiceTemplate.setInterceptors(new ClientInterceptor[]{wss4jSecurityInterceptorClient()});
  webServiceTemplate.setMessageFactory(messageFactory());
  return webServiceTemplate;
 }


Then we have define a SOAPMessageFactory of the following type following by DefaultMethodEndpointAdapter and a marshallingPayloadMethodProcessor.
 @Bean
 public SaajSoapMessageFactory messageFactory() throws Exception
 {
  SaajSoapMessageFactory saajSoapMessageFactory = new SaajSoapMessageFactory(MessageFactory.newInstance());
  saajSoapMessageFactory.setSoapVersion(SoapVersion.SOAP_11);
  return saajSoapMessageFactory;
  
 }
 
 @Bean
 public DefaultMethodEndpointAdapter defaultMethodEndpointAdapter()
 {
  DefaultMethodEndpointAdapter defaultMethodEndpointAdapter = new DefaultMethodEndpointAdapter();
  List  list = new ArrayList();
  List  list2 = new ArrayList();
  list.add(marshallingPayloadMethodProcessor());
  defaultMethodEndpointAdapter.setMethodArgumentResolvers(list);
  defaultMethodEndpointAdapter.setMethodReturnValueHandlers(list2);
  return defaultMethodEndpointAdapter;
 }
 
 
 @Bean
 public MarshallingPayloadMethodProcessor marshallingPayloadMethodProcessor()
 {
  MarshallingPayloadMethodProcessor marshallingPayloadMethodProcessor = new MarshallingPayloadMethodProcessor(marshaller());
  return marshallingPayloadMethodProcessor;
 }

When using the MTOM-XOP feature we need to define the messageFactory implementation, which is to be used in order to create the SOAPMessage.
We can see that this messageFactory implementation is being used in the WebServiceTemplate bean, which is used in the client side, to invoke the Web Service.

We need to define DefaultMethodEndpointAdapter bean because here the MarshallingPayloadMethodProcessor does the trick of resolving the attached message containing MTOM-XOP to the Request type at the service end.

Since we are only sending messages in the request, so we are setting MarshallingPayloadMethodProcessor in list1 i.e. list of type List.

Had there been any need to attach anything in the response then we need to use MarshallingPayloadMethodProcessor in list2 i.e. List of type List

The SOAPMessage can also be viewed by configured Loggers as mentioned above. There we can see that instead of a binary stream, there is a link, which refers to the XOP package containing the attachment.

WS Security with Spring WS

Comments

Post a Comment

Popular posts from this blog

Use of @Configurable annotation.

Spring WS - Part 5