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

发布于 2024-10-17 13:57:38 字数 4890 浏览 1 评论 0原文

我有一个 Web 服务,我正在尝试使用 Spring 和 Jaxb 来实现。我已经有一些使用这两种服务的工作服务 - 但由于响应的格式,这个特定的服务给我带来了困难。在我的 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) 在 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>

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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情定在深秋 2024-10-24 13:57:38

这是 XSD 相关问题,您需要更正您的 XSD。一般在玩JAXB的时候都会出现这个问题,需要正确定义request和response。

此问题已解决。例如,如果您的输入请求元素是“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 时,它总是为此创建两个元素,哪个元素(InsertRequest 或 InsertRequestType) 需要在端点中引用,这就是问题所在。

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

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>
你是年少的欢喜 2024-10-24 13:57:38

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

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.

孤单情人 2024-10-24 13:57:38

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

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

You are seeing this error because JAXB doesn't know what name to give the root element when you return an object of type Outcome. If you are generating your elements from the schema I would expect you to have a ServiceResponse class that you could return instead.

If you can't get a ServiceResponse object, I would have thought your approach of wrapping the Outcome in a JAXBElement should work. Have you checked that _ServiceResponse_QNAME is constructed with the correct namespace URI?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文