Announcement Announcement Module
Collapse
No announcement yet.
Unmarshalling 2 root elements problem with Spring WS and JiBX Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Unmarshalling 2 root elements problem with Spring WS and JiBX

    Hello,

    I am having trouble unmarshalling a request using Spring Web Services with JiBX. The error I get is JiBX unmarshalling exception: No unmarshaller for element {namespace}getInfo

    The soapUI request looks as follows:

    <ns1:getInfo>
    <ns2:query>
    <ns2:category>
    <ns2:type>
    ...
    </ns2:query>
    </ns1:getInfo>

    As you can see, I've got two root tags but I'm binding only the <query> tag and its inner elements in the JiBX mapping. I believe the
    <getInfo> tag should be automatically resolved by Spring-WS as it represents the element mapped on the WSDL operation and the payload bound by JiBX should start at the <query>. I know that Axis and XFire can map the root tag which represents the operation automatically without the need to bind it with Jibx but is it possible to accomplish this with Spring WS?

    I was able to fix this problem by binding the <getInfo> element in JiBX but if I do that then I would have to change all the interfaces linked to the
    service class and pass a 'wrapper' object request as an argument, which is what I would like to avoid. I am now thinking about writing an interceptor which would intercept the request and remove the root tag on the fly but this may cause some overhead I guess.

    Here you have the ws-servlet.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schem...-beans-2.0.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd">

    <!-- JIBX MARSHALLER/UNMARSHALLER -->
    <bean id="marshaller" class="org.springframework.oxm.jibx.JibxMarshaller ">
    <description>
    The Jibx marshaller is used by the endpoints.
    </description>
    <property name="targetClass">
    <value>com.james.Query</value>
    </property>
    </bean>

    <bean id="unmarshaller" class="org.springframework.oxm.jibx.JibxMarshaller ">
    <description>
    The Jibx unmarshaller is used by the endpoints.
    </description>
    <property name="targetClass">
    <value>com.james.Response</value>
    </property>
    </bean>

    <!-- ENDPOINT -->
    <bean id="myEndPoint" class="com.james.MyEndPoint">
    <description>
    </description>
    <property name="myService" ref="myServiceProxy" />
    </bean>


    <!-- ENDPOINT MAPPINGS -->
    <bean class="org.springframework.ws.server.endpoint.mapp ing.PayloadRootAnnotationMethodEndpointMapping">
    <description>
    Detects @PayloadRoot annotations on @Endpoint bean methods.
    </description>
    <property name="interceptors">
    <list>
    <bean class="org.springframework.ws.server.endpoint.inte rceptor.PayloadLoggingInterceptor"/>
    </list>
    </property>
    <property name="order" value="1"/>
    </bean>



    <!-- ENDPOINT ADAPTER -->
    <bean class="org.springframework...GenericMethodMarshall ingEndpointAdapter">
    <description>
    This adapter allows for methods that need and returns marshalled jibx objects.
    </description>
    <constructor-arg ref="marshaller"/>
    <constructor-arg ref="unmarshaller"/>
    </bean>


    <!-- ===================== WSDL DEFINITION ============================== -->
    <bean id="myWsdl" class="org.springframework.ws.wsdl.wsdl11.SimpleWs dl11Definition">
    <constructor-arg value="/WEB-INF/james.wsdl"/>
    </bean>


    the endpoint class:

    public class MyEndpoint {

    private MyService myService;

    /* to be placed in interface later on */
    private final String GET_INFO_REQUEST = "getInfo";
    private final String NAMESPACE = "http://www.james.com/services";


    @PayloadRoot(localPart = GET_INFO_REQUEST, namespace = NAMESPACE)
    public Response getInfo(Query request) {
    ...
    return response;
    }

    As for the WSDL and JiBX all seem perfectly mapped except for the getInfo element.
    Thanks for any help.
    Last edited by James Equalizer; Nov 22nd, 2007, 01:22 PM. Reason: Adding more precise information

  • #2
    Spring Web Services doesn't do anything with the payload element. So if your soapmessage contains

    Code:
    <ns1:getInfo>
    <ns2:query>
    <ns2:category>
    <ns2:type>
    ...
    </ns2:query>
    </ns1:getInfo>
    you must configure marshallers, mappings, etc., to deal with the getInfo element.

    This is different than other stacks, which treat the payload root element as the method name, and the underlying elements as method parameters. This is also known as the "document/wrapped" style, and as such turn the SOAP XML messaging mechanism into an RPC-like model. You can do this with spring-ws, but it's really up to you how you want to deal with the XML.

    Comment


    • #3
      Hi Arjen,

      Thanks for your answer. I've added the JiBX binding, mapping n' stuff... but now I'm stuck on this error: Endpoint invocation resulted in exception -responding with SOAP Fault
      java.lang.IllegalArgumentException: argument type mismatch. What's happening is that the endpoint class is expecting the newly created java object and JiBX bound element GetInfo as the request parameter. But as I am going document 'wrapped' literal all the way, I guess the request parameter should remain com.james.Query, wouldn't it? You said that document wrapped is supported by Spring Web Services but do I need to add additional annotations or are there any other parameters I should set to make document wrapped style work? I've reviewed my WSDL but all seems to be looking good as it has been previously used on a XFire implementation, document wrapped as well.

      Many thanks,
      James

      Comment


      • #4
        You should expect the GetInfo to be passed in, as a single parameter. Generally, Spring-WS operates on the payload (i.e. the first child of the SOAP Body).

        What I meant with Spring-WS supporting the wrapped style is that you can create messages which have the wrapped style, perhaps to facilitate clients which use wrappped/literal.

        Comment


        • #5
          Hello Arjen,

          What I meant with Spring-WS supporting the wrapped style is that you can create messages which have the wrapped style, perhaps to facilitate clients which use wrappped/literal.

          Please correct me if I'm wrong but by binding the root element and therefore changing the related java classes and service interface it seems to me that we are kind of losing one of the many purposes of wrapped/literal style which is the abstraction of the method call at the service level, aren't we? Anyhow, the workaround to this I've put up is an xsl interceptor which gets rid of the root element before the request reaches the endpoint, thanks to Spring WS flexibility.
          Any other workaround suggestions?

          Thanks in advance, -J
          Last edited by James Equalizer; Nov 26th, 2007, 01:54 PM.

          Comment


          • #6
            Originally posted by James Equalizer View Post
            Please correct me if I'm wrong but by binding the root element and therefore changing the related java classes and service interface it seems to me that we are kind of losing one of the many purposes of wrapped/literal style which is the abstraction of the method call at the service level, aren't we?
            If you consider a Web service to expose an existing object, I suppose you are right. However, I generally consider SOAP a messaging protocol, where messages are sent with a specific message payload. If you read the SOAP specs (which I don't recommend ) you will not find a single mention of the word "method" or "operation". It's WSDL that introduced this RPC-like model, and Microsoft introduced the wrapped style to turn document/literal into something which can be used for method invocation.

            Comment


            • #7
              Axiom messageFactory with payloadCaching screwing things up...

              What I meant with Spring-WS supporting the wrapped style is that you can create messages which have the wrapped style, perhaps to facilitate clients which use wrappped/literal.

              Hello Arjen,
              So I've found a solution to this wrapped document/literal case by removing the getInfo root element using an XSL interceptor so that Spring-WS wouldn't complain about the missing getInfo jibx binding. However I am now using the Axiom message factory with payloadCaching set to true and I am back to the same error 'No unmarshaller for element getInfo". It seems like the payload caching is kind of skipping my xsl interceptor somewhere. Any idea?

              If my xsl solution cannot be implemented with the axiom payload caching, is there a way to intercept messages more earlier in the process than with xsl interceptors so that the message would ALWAYS not contain the root element when Spring-WS comes to unmarshalling the request? I really need to use the payload caching in my web service.

              Thanks again,
              James

              Comment


              • #8
                If you disable payload caching, you can only read the payload once. So that rules out the option of using a stylesheet.

                Comment

                Working...
                X