JAXB + Spring WS : "No adapter for endpoint" while using JAXBElement

13,958

Solution 1

It is XSD related issue, you need to correct your XSD. Generally, when you are playing with JAXB, this problem will occur, you need to define request and response correctly.

This issue is resolved. For example if your input request element is 'InsertRequest' so need to define like

<xs:element name="InsertRequest">
<xs:annotation>
<xs:documentation>Root element for Record Insert Request</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="GeneralDetails" type="tns:GenralDetailsType"></xs:element>
<xs:element name="FullDetails" type="tns:FullDetailsType"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>

Previously I was defined this as mentioned below:- so when I am creating JAXB beans it always creates two elements for this, which element (InsertRequest or InsertRequestType) need to refer in endpoint, this was the issue.

<element name="InsertRequest" type="tns:InsertRequestType"></element>


<complexType name="InsertRequestType">
<sequence>
<element name="GeneralDetails" type="tns:GenralDetailsType"></element>
<element name="FullDetails" type="tns:FullDetailsType"></element>
</sequence>
</complexType>

Solution 2

When I had this problem, the answer turned out to be that I had forgotten to include the element class in the list of classesToBeBound for the Spring Jaxb2Marshaller. Adding these to the list fixed the problem - but our elements were already set up with an inline complex type.

Share:
13,958
Dave
Author by

Dave

Updated on July 07, 2022

Comments

  • Dave
    Dave almost 2 years

    I have a web service that I am trying to implement using Spring and Jaxb. I already have a handful of working services using both of these - but this particular service is giving me a hard time due to the format of the response. In my XSD, the response is defined like this (notice that it is a single element):

    <!-- Response definition -->
    <element name="ServiceResponse" type="Q1:Outcome"/>
    
    
    <!-- Outcome definition -->
    <complexType name="Outcome">
        <sequence>
            <element name="ErrorCode">
                <simpleType>
                    <restriction base="string">
                        <maxLength value="8"/>
                    </restriction>
                </simpleType>
            </element>
            <element name="ErrorText">
                <simpleType>
                    <restriction base="string">
                        <maxLength value="1000"/>
                    </restriction>
                </simpleType>
            </element>
            <element name="DocumentId">
                <simpleType>
                    <restriction base="string">
                        <maxLength value="30"/>
                    </restriction>
                </simpleType>
            </element>
        </sequence>
    </complexType>
    

    I have a service method that looks like this:

    @PayloadRoot( localPart = SERVICE_REQUEST, namespace = NAMESPACE )
    public Outcome processFileRequest( ServiceRequest requestObject )
    

    I end up with an exception that looks like this:

    java.lang.IllegalStateException: No adapter for endpoint [public dortman.xsd.objects.Outcome dortman.annotated.MyTestEndpoint.processFileRequest(dortman.xsd.objects.ServiceRequest)]: Does your endpoint implement a supported interface like MessageHandler or PayloadEndpoint?

    After finding some related posts on the Spring forum and Stackoverflow, it seems that return objects need to either have the XmlRootElement annotation or be wrapped in a JAXBElement. To try the first, I changed the response in the XSD to:

    <!-- Response definition -->
    <element name="ServiceResponse">
        <complexType>
            <sequence>
                <element name="FileSize" type="long"/>
            </sequence>
        </complexType>
    </element>  
    

    That works, as JAXB then generates a ServiceResponse class which has the XmlRootElement annotation. Unfortuantely, I don't necessarily have the latitude the alter the XSD - which means I need to pursue the other option. So I tried that. My new service method looks like this:

    @PayloadRoot( localPart = SERVICE_REQUEST, namespace = NAMESPACE )
    public JAXBElement<Outcome> processFileRequest( ServiceRequest requestObject )
    

    And I then wrap my return object using the method that was created on ObjectFactory:

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link Outcome }{@code >}}
     * 
     */
    @XmlElementDecl(namespace = "http://www.dortman.com/MyTestService", name = "ServiceResponse")
    public JAXBElement<Outcome> createServiceResponse(Outcome value) {
        return new JAXBElement<Outcome>(_ServiceResponse_QNAME, Outcome.class, null, value);
    }
    

    I file up the server expecting this to resolve the problem. But instead I get:

    java.lang.IllegalStateException: No adapter for endpoint [public javax.xml.bind.JAXBElement dortman.annotated.MyTestEndpoint.processFileRequest(dortman.xsd.objects.ServiceRequest)]: Does your endpoint implement a supported interface like MessageHandler or PayloadEndpoint? at org.springframework.ws.server.MessageDispatcher.getEndpointAdapter(MessageDispatcher.java:283) at org.springframework.ws.server.MessageDispatcher.dispatch(MessageDispatcher.java:226) at org.springframework.ws.server.MessageDispatcher.receive(MessageDispatcher.java:169) at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection (WebServiceMessageReceiverObjectSupport.java:89) at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle (WebServiceMessageReceiverHandlerAdapter.java:57) at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:231) at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2174) at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1446) at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201) at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)

    Apparently it was not impressed by my use of JAXBElement. Has anybody else encountered this problem?

    My configuration file (which is already working with ~6 web services, it's just that none of them exhibit this particular XSD variation) contains the following:

    <!-- JAXB marshaller to be used by the annotated web services -->
    <bean class="org.springframework.ws.server.endpoint.adapter.MarshallingMethodEndpointAdapter">
    <constructor-arg>
    <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
      <property name="contextPath" value="dortman.xsd.objects" />
      <property name="mtomEnabled" value="true"/>
    </bean> 
    </constructor-arg>
    </bean> 
    
    <bean id="messageFactory" class="org.springframework.ws.soap.axiom.AxiomSoapMessageFactory">
    <property name="payloadCaching" value="true"></property>
    <property name="attachmentCaching" value="true"></property>
    </bean>
    
  • Dave
    Dave about 13 years
    Yeah, I thought the same. The URI looks right. Fortunately, I soon realized that if I just inlined the XSD element, JAXB would then generate classes that don't need JAXBElement and the generated XML still conforms to the unaltered XSD. So I sidestepped the problem. ;)
  • Spring
    Spring over 10 years
    @rjsang Could you please have a look at this question thank you! stackoverflow.com/questions/19032798/…