Announcement Announcement Module
Collapse
No announcement yet.
JAXB Unmarshalling Exception Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • JAXB Unmarshalling Exception

    Hello,

    Iím working on a project where the customer has provided us with a series of web service contracts (WSDL) that they want us to implement as part of the deliverables. The WSDL files compile using WSImport from the Metro/JAX team, and the resulting annotations allow me to deploy the web services without a hitch using the JAXWS deployment descriptors. I would like to deploy the web services using Spring so that I can take advantage of the Springís AOP functionality, not to mention dependency injection, but I have had several problems getting them up and running using Spring-ws. The major pitfall right now seems to be related to the fact that the parameter names are not related to the operation names. Iím trying to use Springís annotated endpoints, combined with a JAXB marshaller, but when the messages come in I get an unmarshalling error stating that there is an unexpected element. Iíve created an example project to demonstrate the problem Iím having, and Iíve attached it to the message.

    In a search of the forum, I saw some posts that describe the use of the @XmlRootElement annotation as a possible solution for this problem, but I need some assistance in how to use it. As well, I would need to be able to add it automatically during the xjc compilation.

    Any assistance you could provide would be most appreciated,
    Bob


    This is the exception that I'm getting:
    Code:
    JAXB unmarshalling exception: 
    unexpected element (uri:"urn:org:cubrc:test:messages:echoservice", local:"inputElement"). 
    Expected elements are (none); 
    nested exception is javax.xml.bind.UnmarshalException: 
    unexpected element (uri:"urn:org:cubrc:test:messages:echoservice", local:"inputElement"). 
    Expected elements are (none)
    Here are the xsd and wsdl files:

    Code:
    <!-- Echo.xsd --> 
    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="urn:org:cubrc:test:messages:echoservice" targetNamespace="urn:org:cubrc:test:messages:echoservice">
          <xs:element name="inputElement" type="tns:RequestType" />
          <xs:element name="outputElement" type="tns:ResponseType" />
          
          <xs:complexType name="RequestType">
            <xs:sequence>
              <xs:element name="value" type="xs:string"/>
            </xs:sequence>
          </xs:complexType>
          <xs:complexType name="ResponseType">
            <xs:sequence>
              <xs:element name="value" type="xs:string"/>
            </xs:sequence>
          </xs:complexType>
    </xs:schema>
    
    <!-- Echo.wsdl --> 
    <?xml version="1.0" encoding="UTF-8"?>
    <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
      xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
      xmlns:ts="urn:org:cubrc:test:messages:echoservice" xmlns:tns="urn:org:cubrc:test:ws:echoservice" targetNamespace="urn:org:cubrc:test:ws:echoservice" name="EchoService">
    
      <!-- ********** Service XML Descriptions********** -->
      <wsdl:types>
        <xs:schema targetNamespace="urn:org:cubrc:test:ws:echoservice">
          <xs:import namespace="urn:org:cubrc:test:messages:echoservice" schemaLocation="../schemas/Echo.xsd"/>
        </xs:schema>
      </wsdl:types>
    
      <!-- ********** Service Messages ********** -->
      <wsdl:message name="InputMsg">
        <wsdl:part name="input" element="ts:inputElement" />
      </wsdl:message>
      <wsdl:message name="OutputMsg">
        <wsdl:part name="output" element="ts:outputElement" />
      </wsdl:message>
    
      <!-- ********** Service Port Information ********** -->
      <wsdl:portType name="IEchoService">
        <wsdl:operation name="echo">
          <wsdl:input name="input" message="tns:InputMsg" />
          <wsdl:output name="output" message="tns:OutputMsg" />
        </wsdl:operation>
      </wsdl:portType>
    
      <!-- ********** Service Binding Information ********** -->
      <wsdl:binding name="EchoServiceBinding" type="tns:IEchoService">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
        <!-- Operation Name -->
        <wsdl:operation name="echo">
          <soap:operation style="document" />
          <wsdl:input name="input">
            <soap:body use="literal" />
          </wsdl:input>
          <wsdl:output name="output">
            <soap:body use="literal" />
          </wsdl:output>
        </wsdl:operation>
      </wsdl:binding>
    
      <!-- ********** Service Information ********** -->
      <wsdl:service name="EchoService">
        <wsdl:port name="proxy" binding="tns:EchoServiceBinding">
          <soap:address location="http://localhost:18080/spring-echo-service/services/EchoService" />
          <!-- TBD - REPLACE WITH ACTUAL URL -->
        </wsdl:port>
      </wsdl:service>
    </wsdl:definitions>
    Here are the spring config files

    Code:
    <!-- spring-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" xsi:schemaLocation="http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
      <!-- *************** -->
      <!-- Payload Mappers -->
      <!-- *************** -->
    
      <!-- An XML payload-to-endpoint mapping. This class will match the root element to an AbstractEndpoint object -->
      <bean id="payloadMapping" class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
        <property name="endpointMap">
          <map>
            <!--  Change the value of the value-ref attribute to change which endpoint this gets mapped to -->
            <entry key="{urn:org:cubrc:test:messages:echoservice}inputElement" value-ref="annotatedEchoEndpoint" />
          </map>
        </property>
        <!-- This should be used to resolve/choose an endpoint only after EndpointMapping objects of order 1 -->
        <property name="order" value="2" />
      </bean>
    
      <!-- An XML payload-to-endpoint mapping that uses the @PayloadRoot annotation on methods in beans annotated with @Endpoint.  -->
      <bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
        <property name="order" value="1" />
      </bean>
    
      <!-- An endpoint adapter to handle the marshaling of the in/out of the annotated endpoint. -->
      <!--  Only needed for the annotated endpoint.  -->
      <bean class="org.springframework.ws.server.endpoint.adapter.GenericMarshallingMethodEndpointAdapter">
        <constructor-arg ref="marshaller" />
      </bean>
    
    
    
      <!-- ********* -->
      <!-- Endpoints -->
      <!-- ********* -->
    
      <!-- A marshaling echo-service -->
      <bean id="marshallingEchoEndpoint" class="org.cubrc.test.spring.echoservice.MarshalledEchoService">
        <property name="marshaller" ref="marshaller" />
        <property name="unmarshaller" ref="marshaller" />
      </bean>
    
      <!-- An @Endpoint-annotated endpoint. -->
      <bean id="annotatedEchoEndpoint" class="org.cubrc.test.spring.echoservice.AnnotatedEchoService" />
    
      <!-- A JDom-based poker hand evaluation endpoint. -->
      <bean id="jdomEchoEndpoint" class="org.cubrc.test.spring.echoservice.JdomEchoService" />
    
    
    
      <!-- *********** -->
      <!-- Marshallers -->
      <!-- *********** -->
    
      <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller" name="marshaller">
        <property name="classesToBeBound">
          <list>
            <value>org.cubrc.test.messages.echoservice.RequestType</value>
            <value>org.cubrc.test.messages.echoservice.ResponseType</value>
          </list>
        </property>
      </bean>
    
    
    
      <!-- **************** -->
      <!-- WSDL Definitions -->
      <!-- **************** -->
    
      <!--
        SimpleWsdl11Definition to load a pre-defined WSDL. Assuming that MessageDispatcherServlet's transformWsdlLocations init-param is set to true, any location URLs in the pre-defined WSDL will be
        transformed to match the location where the MessageDispatcherServlet is deployed. WSDL's can be accessed at http://host:host-port/package-name/servlet-mapping/bean-name.wsdl
      -->
      <bean id="EchoService" class="org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition">
        <property name="wsdl" value="/wsdl/Echo.wsdl" />
      </bean>
    
    </beans>
    Here is the endpoint class:

    Code:
    @Endpoint
    public class AnnotatedEchoService
    {
                    public AnnotatedEchoService()
                    {
                                    System.out.println("Creating AnnotatedEchoService object");
                    }
                    
                    @PayloadRoot(namespace="urn:org:cubrc:test:messages:echoservice", localPart="inputElement")
                    public JAXBElement<ResponseType> echo(JAXBElement<RequestType> request)
                    {
                                    ResponseType response = new ResponseType();
                                    response.setValue("Echo: " + request.getValue().getValue());
    
                                    ObjectFactory factory = new ObjectFactory();
                                    
                                    JAXBElement<ResponseType> returnValue = factory.createOutputElement(response);
                                    return returnValue;
                    }              
    }

  • #2
    JAXB Configuration

    The problem you're having has to do with your Jaxb2Marshaller. You've configured your marshaller to understand the classes "RequestType" and "ResponseType" but your endpoint is expecting an element whose name is "inputElement". I'm still VERY new to spring and have virtually no experience getting the web services working, so I don't know how to make the mapping between "inputElement" and "RequestType". However, if you change your marshaller definition as follows it will work.

    Code:
        
    <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller" name="marshaller">
        <property name="contextPath"><value>org.cubrc.test.messages.echoservice</value></property>
      </bean>
    Maybe somebody more knowledgeable than me can tell you the what and why, but for now I think that will fix your problem.

    Comment


    • #3
      JAXB contextPath vs. classesToBeBound

      Thanks for the reply.

      The difference in the configuration between your version and my version appears to be simply that you set the "contextPath" member of the marshaller, and I set the "classesToBeBound" member. I read the Spring documentation on the Jaxb2Marshaller and they state that one of the two properties should be set. Is it possible that the contextPath property is not an optional property?

      Has anyone else in the community run into this issue when configuring the JAXB marshaller?

      Many Thanks (again),
      Bob

      Comment

      Working...
      X