Announcement Announcement Module
Collapse
No announcement yet.
Deserializing String sequence problem. Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Deserializing String sequence problem.

    My application has to interface with a third-party Web Service. I'm using JAX-RPC with Axis, they are using the standard .NET runtime. The problem is that there is a method on the third-party service that returns a sequence of String instead of a SOAP string array.
    Here's some relevant bit of WSDL:

    Code:
        <s&#58;complexType name="ArrayOfString">
            <s&#58;sequence>
                 <s&#58;element minOccurs="0" maxOccurs="unbounded" name="string" nillable="true" type="s&#58;string" />
             </s&#58;sequence>
         </s&#58;complexType>
    
          <s&#58;element name="GetLatestGPSEntryResponse">
              <s&#58;complexType>
                     <s&#58;sequence>
                          <s&#58;element minOccurs="0" maxOccurs="1" name="GetLatestGPSEntryResult" type="tns&#58;ArrayOfString" />
                     </s&#58;sequence>
               </s&#58;complexType>
           </s&#58;element>
    
        <wsdl&#58;operation name="GetLatestGPSEntry">
          <soap&#58;operation soapAction="http&#58;//amss.com.au/wtracker/WTService/GetLatestGPSEntry" style="document" />
          <wsdl&#58;input>
            <soap&#58;body use="literal" />
          </wsdl&#58;input>
          <wsdl&#58;output>
            <soap&#58;body use="literal" />
          </wsdl&#58;output>
        </wsdl&#58;operation>
    The function is called GetLatestGPSEntry, and as you can see it returns a sequence custom type called ArrayOfString, which is a sequence of String.

    Now, I have Spring all setup to use JaxRpcPortProxyFactoryBean, and all the other functions in this web service work properly. Because I haven't registered a serializer/deserializer I get the exception I would expect:

    Exception:
    org.xml.sax.SAXException: Deserializing parameter 'GetLatestGPSEntryResult': could not find deserializer for type {http://amss.com.au/wtracker/WTService}ArrayOfString
    But that is not the problem. The problem is that the stubs generated by WSDL2Java work fine, but I can't seem to translate it into a clean Spring solution. If you are familiar with the code generated by WSDL2Java, heres the relevant section:

    Code:
            oper = new org.apache.axis.description.OperationDesc&#40;&#41;;
            oper.setName&#40;"GetLatestGPSEntry"&#41;;
            param = new org.apache.axis.description.ParameterDesc&#40;new javax.xml.namespace.QName&#40;"http&#58;//amss.com.au/wtracker/WTService", "Token"&#41;, org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName&#40;"http&#58;//www.w3.org/2001/XMLSchema", "long"&#41;, long.class, false, false&#41;;
            oper.addParameter&#40;param&#41;;
            param = new org.apache.axis.description.ParameterDesc&#40;new javax.xml.namespace.QName&#40;"http&#58;//amss.com.au/wtracker/WTService", "unitid"&#41;, org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName&#40;"http&#58;//www.w3.org/2001/XMLSchema", "int"&#41;, int.class, false, false&#41;;
            oper.addParameter&#40;param&#41;;
            oper.setReturnType&#40;new javax.xml.namespace.QName&#40;"http&#58;//amss.com.au/wtracker/WTService", "ArrayOfString"&#41;&#41;;
            oper.setReturnClass&#40;java.lang.String&#91;&#93;.class&#41;;
            oper.setReturnQName&#40;new javax.xml.namespace.QName&#40;"http&#58;//amss.com.au/wtracker/WTService", "GetLatestGPSEntryResult"&#41;&#41;;
            param = oper.getReturnParamDesc&#40;&#41;;
            param.setItemQName&#40;new javax.xml.namespace.QName&#40;"http&#58;//amss.com.au/wtracker/WTService", "string"&#41;&#41;;
            oper.setStyle&#40;org.apache.axis.constants.Style.WRAPPED&#41;;
            oper.setUse&#40;org.apache.axis.constants.Use.LITERAL&#41;;
            _operations&#91;14&#93; = oper;
    I see that it is just using String[] as the return class, so I have overridden JaxRpcPortProxyFactoryBean and registered what I think is the appropriate serializer/deserializer:

    Code:
    public class AmssAxisPortProxyFactoryBean extends JaxRpcPortProxyFactoryBean &#123;
        public void postProcessJaxRpcService&#40;Service service&#41; &#123;
            TypeMappingRegistry registry = service.getTypeMappingRegistry&#40;&#41;;
            TypeMapping mapping = registry.getDefaultTypeMapping&#40;&#41;;
            QName xmlType = new QName&#40;"http&#58;//amss.com.au/wtracker/WTService", "ArrayOfString"&#41;;
            mapping.register&#40;
                    String&#91;&#93;.class, 
                    xmlType, 
                    new ArraySerializerFactory&#40;String&#91;&#93;.class, xmlType&#41;, 
                    new ArrayDeserializerFactory&#40;xmlType&#41;
                    &#41;;
                    
        &#125;
    &#125;
    However running this code gives me the following exception:
    Exception:
    org.xml.sax.SAXException: Found character data inside an array element while deserializing
    at org.apache.axis.encoding.ser.ArrayDeserializer.cha racters(ArrayDeserializer.java:489)
    at org.apache.axis.encoding.DeserializationContext.ch aracters(DeserializationContext.java:966)
    at org.apache.axis.message.SAX2EventRecorder.replay(S AX2EventRecorder.java:177)
    at org.apache.axis.message.MessageElement.publishToHa ndler(MessageElement.java:1140)
    at org.apache.axis.message.RPCElement.deserialize(RPC Element.java:236)
    at org.apache.axis.message.RPCElement.getParams(RPCEl ement.java:384)
    at org.apache.axis.client.Call.invoke(Call.java:2448)
    at org.apache.axis.client.Call.invoke(Call.java:2347)
    at org.apache.axis.client.Call.invoke(Call.java:1804)
    at org.springframework.remoting.jaxrpc.JaxRpcPortClie ntInterceptor.performJaxRpcCall(JaxRpcPortClientIn terceptor.java:492)
    at org.springframework.remoting.jaxrpc.JaxRpcPortClie ntInterceptor.invoke(JaxRpcPortClientInterceptor.j ava:451)
    at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :144)
    at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:174)
    at $Proxy7.GetLatestGPSEntry(Unknown Source)
    If anyone could point me in the right direction it would be greatly appreciated. I would rather have a nice clean Spring solution than use the Axis stubs.

  • #2
    I looked at a stub created by Axis's WSDL2JAVA tool and noticed that they construct a ArrayDeserializerFactory but without specifying the QName parmeter. I tried that and it worked. So just change your "new ArrayDeserializerFactory(xmlType)" to "new ArrayDeserializerFactory()".

    Comment

    Working...
    X