Search code examples
apache-axisaxismtom

AXIS Client v.s. AXIS2 Service


I must implement an AXIS 1.4 client which consume an AXIS2 1.4 method. AXIS 1.4 client is made by creating the stubs. The client send a request and get back a response from service with some attachment (MTOM). When I call the method (operation) by AXIS 1.4 port type object I got an error:

org.xml.sax.SAXException: SimpleDeserializer encountered a child element, which is NOT expected, in something it was trying to deserialize.

I think MTOM messed up with AXIS. So here is the question: how did I get the attachment the AXIS2 1.4 (MTOM) web service return me back? TIA.

Francesco

P.S: here is the code. There are stubs generated by WSDL. The problem is: i get the exception when I call the port's stub method. There are attachments in the message I get back.

String codistat = "CODISTAT";    
OrdinanzeViabilitaLocator ovlocretreive = new OrdinanzeViabilitaLocator();
ovlocretreive.setOrdinanzeViabilitaHttpSoap11EndpointEndpointAddress(".. the service url + action..");
try {
  OrdinanzeViabilitaPortType ovretreive = ovlocretreive.getOrdinanzeViabilitaHttpSoap11Endpoint();
  ((Stub) ovretreive)._setProperty(javax.xml.rpc.Call.USERNAME_PROPERTY, "username");
  ((Stub) ovretreive)._setProperty(javax.xml.rpc.Call.PASSWORD_PROPERTY, "password");            
  //problems began here
  MessageReqOrdinanze mrq = new MessageReqOrdinanze();
  mrq.setCodistat(codistat);
  Calendar date_from = Calendar.getInstance();
  date_from.setTimeInMillis(0);
  Calendar date_to = Calendar.getInstance();
  date_from.setTimeInMillis(0);
  mrq.setDate_from(date_from);
  mrq.setDate_to(date_to);
  // the next line generate the exception
  MessageOrdinanze mretreive = ovretreive.getOrdinanze(mrq);
  } catch (AxisFault e) {
        e.printStackTrace();
  } catch (RemoteException e) {
        e.printStackTrace();
  } catch (FileNotFoundException e) {
        e.printStackTrace();
  } catch (IOException e) {
        e.printStackTrace();
  } catch (ServiceException e) {
        e.printStackTrace();
  }

The message I get back has a

<xop:include href="cid... >...< ../xop/include"/>

tag inside, it's MTOM (it cause the exception I guess). Hope this helps.


Solution

  • There are two things that need to be done to make MTOM work on the client side:

    1. Ensure that in the stubs, the xs:base64Binary type is mapped to java.activation.DataHandler instead of byte[].
    2. Set up a (runtime) type mapping for xs:base64Binary and java.activation.DataHandler that uses JAFDataHandlerSerializer and JAFDataHandlerDeserializer (which support MTOM).

    The second part is fairly easy. Simply set up a client-config.wsddfile with the following type mapping:

    <typeMapping languageSpecificType="java:javax.activation.DataHandler" qname="xs:base64Binary"
                 deserializer="org.apache.axis.encoding.ser.JAFDataHandlerDeserializerFactory"
                 serializer="org.apache.axis.encoding.ser.JAFDataHandlerSerializerFactory" 
                 encodingStyle=""/>
    

    The first part is more tricky because the tooling (wsdl2java) in Axis 1.4 doesn't support changing the Java type associated with a given XML type. There are several ways to work around that limitation:

    • Edit the generated stubs by hand and change byte[] to javax.activation.DataHandler. Depending on how you manage generated code in your project, that may or may not be an acceptable solution.
    • It is probably possible (although I didn't test that) to trick wsdl2java into using javax.activation.DataHandler by giving it a modified WSDL where the type {http://www.w3.org/2001/XMLSchema}base64Binary is replaced by {java}javax.activation.DataHandler.
    • I fixed the tooling in the current Axis trunk so that it supports this type of configuration. Note however that this is only implemented in the wsdl2java Maven plugin (but not in the Ant task or the command line tool). You could use the 1.4.1-SNAPSHOT version of that plugin; the generated code would still work with Axis 1.4. You can find some documentation here.