具有通用负载XML类型“Any”的Web服务

时间:2013-09-06 21:14:08

标签: spring web-services java-ee wsdl tibco

我开发了一个Web服务,它接受并响应一个通用的消息结构。意思是,这个消息结构是通用的。我们使其通用的方式是使用以下XML模式:

<xs:complexType name="HeaderType">
<xs:complexType name="MessageType">
<xs:complexType name="PayloadType">

其中PayloadType如下:

<xs:complexType name="PayloadType">
        <xs:annotation>
            <xs:documentation>Payload container</xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:choice>

                <xs:element name="CreateExceptionSeverity" type="cmsmsg:ExceptionSeverity" minOccurs="0">
                    <xs:annotation>
                        <xs:documentation>CreateExceptionSeverity is a hello world operation that takes in a app id, id, name, and description where the web service creates a new entry in EXCEPTIONSEVERITY table.</xs:documentation>
                    </xs:annotation>
                </xs:element>
                <xs:element name="OperationSet" type="cmsmsg:OperationSet" minOccurs="0">
                    <xs:annotation>
                        <xs:documentation>Each operation set is a collection of operations that may require operational-integrity and/or sequence control.</xs:documentation>
                    </xs:annotation>
                </xs:element>
                <xs:element name="Compressed" type="xs:string" minOccurs="0">
                    <xs:annotation>
                        <xs:documentation>For compressed and/or binary, uuencoded payloads</xs:documentation>
                    </xs:annotation>
                </xs:element>
                **<xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax" namespace="##other">**
                            <xs:annotation>
                                <xs:documentation>For XML payloads, usually CIM profiles defined using an XSD in a profile-specific namespace.</xs:documentation>
                            </xs:annotation>
                </xs:any>
            </xs:choice>
            <xs:element name="Format" type="xs:string" minOccurs="0">
                <xs:annotation>
                    <xs:documentation>Hint as to format of payload, e.g. XML, RDF, SVF, BINARY, PDF, ...</xs:documentation>
                </xs:annotation>
            </xs:element>
        </xs:sequence>
    </xs:complexType>

所以,行:

<xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax" namespace="##other">

使这个结构足够灵活,可以在调用Web服务时以及Web服务发回响应时发送数据。此Web服务部署在TIBCO服务器上(使用Tomcat),将通过SOAP / HTTP调用。

此Web服务的客户端是Java Spring Web应用程序。我的问题是:Java代码如何处理这个Any元素,因为它需要一个具体的XML类型,如整数,字符串或复杂类型?这里的任何方向将非常感谢。

1 个答案:

答案 0 :(得分:3)

请不要这样做。我之前使用过这种“通用”Web服务,它们相当于拥有一个java API,每个方法都有签名

public Object methodName(Object o);

是的,这一切都非常通用,但它没有传达如何使用它的信息(一个设计良好的界面传达了它应该如何使用,就像茶壶的手柄暗示应该拿起茶壶一样)通过句柄)。当有人想开发一个消耗你服务的应用程序时,他们如何找出要发送的内容以及他们将得到什么?如果它在其他文档中,那么您基本上创建了自己的定制Web服务描述语言,它不会与任何工具(如Spring或Axis-2)集成,并且需要编写大量额外的手动代码。

此外,您将不得不在服务实现中编写额外的代码来验证有效负载的内容。这意味着需要额外的工作来维持和更高的缺陷机会。

请为您的Web服务操作使用具体的XML输入和响应,并删除any。它不仅可以使您的代码更简单,而且消费者的代码更简单,它还可以解决您在如何从Spring中使用它的问题。

你必须来这里询问如何使用你创建的网络服务这一事实应该会引发你的警钟。在创建任何类型的界面时,如果您难以使用,那么其他任何人都将非常难以使用。为了确保我的Web服务易于使用,我做的第一件事(在创建WSDL或实现之前)是创建一个简单的程序,作为测试的一部分调用服务(例如,JUnit或Cucumber-JVM等) ,仅传入所需的数据(仅此而已),仅检查所需的响应数据(仅此而已)。然后我研究Web服务实现,直到测试通过。这总是会产生简单易用的服务,而不是使用高度复杂模式的大型繁重服务,其中只使用了1%(我确信他们将其他99%的模式放在那里并且不使用它,只是为了引导服务的新用户误入歧途)。

就要包含在消息中的元数据(即messageType和headerType信息)而言,请考虑根据SOAP Headers使用Messaging Metadata SOA Pattern。它们允许您包含额外信息,而不会污染您的邮件正文。

最后,如果您需要在消息结构上应用某种一致性(因为由于某些奇怪的原因,SOAP信封不够,您需要将自己的定制信封放入SOAP信封中),请考虑使用{{ 3}},然后你abstract base types来满足方法的特殊需求。这将允许您应用一致性,而不需要您的服务使用者猜测“任何”实际可能是什么。

旁注。我工作过的一个客户端有一个通用的消息结构,比如你的。其中一个原因是他们希望以一致的方式报告其Web服务响应中的成功或错误。因此,在他们的定制反应中,信封是一个表明成功或失败的因素,一切都很好......

...除了服务的消费者,现在需要编写额外的代码,不仅要检查SOAP错误,还要检查是否设置了定制的错误标志。

...除了我们想在我们的服务前放置负载均衡器之外,因为它本身不支持我们的定制错误元素。但它支持SOAP故障和http状态代码:/

<强>更新

更简单的方法。该操作违反了extend

如果一个操作接受“Any”,我应该期望我传递给该操作的任何有效的xml元素都能正常工作。但是,只允许某些XML元素。了解允许哪些类型的唯一方法是了解操作的详细信息。换句话说,该操作的灵活性不如宣传的那么灵活。

上述更新已在Liskov substitution principle

的优秀答案中进行了修改