JAXB + Spring WS:"没有端点适配器"使用JAXBElement时

时间:2011-02-12 01:33:39

标签: java web-services jaxb spring-ws

我正在尝试使用Spring和Jaxb实现的Web服务。我已经使用这两种方法提供了一些工作服务 - 但由于响应的格式,这项特殊服务给我带来了困难。在我的XSD中,响应定义如下(注意它是单个元素):

<!-- 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>

我有一个看起来像这样的服务方法:

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

我最终得到一个如下所示的异常:

java.lang.IllegalStateException: 没有端点适配器[public dortman.xsd.objects.Outcome dortman.annotated.MyTestEndpoint.processFileRequest(dortman.xsd.objects.ServiceRequest)]:您的端点是否实现了MessageHandler或PayloadEndpoint等受支持的接口?

在Spring论坛和Stackoverflow上找到一些相关帖子后,似乎返回对象需要具有XmlRootElement注释或包含在JAXBElement中。为了尝试第一个,我将XSD中的响应更改为:

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

这是有效的,因为JAXB然后生成一个具有XmlRootElement注释的ServiceResponse类。不幸的是,我没有必要改变XSD - 这意味着我需要追求另一种选择。所以我试过了。我的新服务方法如下:

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

然后我使用在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);
}

我提交服务器,期望这样解决问题。但我得到了:

java.lang.IllegalStateException: 端点没有适配器[public javax.xml.bind.JAXBElement dortman.annotated.MyTestEndpoint.processFileRequest(dortman.xsd.objects.ServiceRequest)]: 您的端点是否实现了MessageHandler或PayloadEndpoint等受支持的接口?         在org.springframework.ws.server.MessageDispatcher.getEndpointAdapter(MessageDispatcher.java:283)         在org.springframework.ws.server.MessageDispatcher.dispatch(MessageDispatcher.java:226)         在org.springframework.ws.server.MessageDispatcher.receive(MessageDispatcher.java:169)         at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection (WebServiceMessageReceiverObjectSupport.java:89)         在org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle (WebServiceMessageReceiverHandlerAdapter.java:57)         在org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:231)         在weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2174)         在weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1446)         在weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)         在weblogic.work.ExecuteThread.run(ExecuteThread.java:173)

显然,我对JAXBElement的使用并没有给人留下深刻的印象。还有其他人遇到过这个问题吗?

我的配置文件(已经使用~6个Web服务,只是它们没有显示这个特定的XSD变体)包含以下内容:

<!-- 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>

3 个答案:

答案 0 :(得分:7)

这是XSD相关问题,您需要更正您的XSD。通常,当您使用JAXB时,会出现此问题,您需要正确定义请求和响应。

此问题已解决。例如,如果您的输入请求元素是“InsertRequest”,那么需要定义类似

<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>

以前我的定义如下所述: - 所以当我创建JAXB bean时,它总是为此创建两个元素,哪个元素(InsertRequestInsertRequestType)需要在端点中引用,这个是问题。

<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>

答案 1 :(得分:1)

当我遇到这个问题时,答案结果是我忘记在Spring Jaxb2Marshaller的classesToBeBound列表中包含元素类。将这些添加到列表中可以解决问题 - 但我们的元素已经设置为内联复杂类型。

答案 2 :(得分:0)

您看到此错误,因为当您返回Outcome类型的对象时,JAXB不知道为根元素指定的名称。如果您要从模式生成元素,我希望您有一个可以返回的ServiceResponse类。

如果你无法获得ServiceResponse对象,我认为你在JAXBElement中包装Outcome的方法应该有效。您是否检查过_ServiceResponse_QNAME是否使用正确的命名空间URI构建?