使用 xsd:any 表示服务接口中的 XML 文档:设计详细信息
本文档以 java.net 中 bpcatalog 项目下的面向文档的应用程序为例,说明了在设计以文档为中心的接口和端点时使用 xsd:any 作为文档类型的策略。此应用程序具有一个服务端点,旨在将 xsd:any 用作文档类型。XML 文档以客户端发送的订单表示。
该应用程序由以下主要实体组成:
- WSDL 文件:此文件描述了将 XML 文档作为 xsd:any 接收的服务接口。
- AnyPurchaseOrderServiceSEI.java:这是服务端点接口。
- AnyPurchaseOrderServiceImpl.java:这是接口的端点实现。
- 一些部署描述符。
服务的 WSDL 文件
代码示例 1 中的 WSDL 文件描述了 Web 服务。我们选择的开发形式是从 WSDL 开始的,并基于 WSDL 生成必要的 Java[TM] 类。因此,为消息部分在 WSDL 中选择正确的类型是非常重要的,因为 WSDL 文件中的这些类型会在生成的 Java 代码中产生参数类型。请注意,<any/>
类型是为以参数形式发送到 submitPO 方法的文档以及返回值指定的。此外,还请注意在 WSDL 中声明的应用程序定义的服务异常。
<types>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="urn:AnyPurchaseOrderService">
<complexType name="submitPO">
<sequence>
<any/>
</sequence>
</complexType>
<complexType name="submitPOResponse">
<sequence>
<any/>
</sequence>
</complexType>
<complexType
name="InvalidPOException">
<sequence>
<element name="message" type="string"
nillable="true"/>
</sequence>
</complexType>
<element name="submitPO" type="tns:submitPO"/>
<element name="submitPOResponse"
type="tns:submitPOResponse"/>
<element name="InvalidPOException"
type="tns:InvalidPOException"/>
</schema>
</types>
<message name="AnyPurchaseOrderServiceSEI_submitPO">
<part name="parameters"
element="tns:submitPO"/>
</message>
<message name="AnyPurchaseOrderServiceSEI_submitPOResponse">
<part name="result"
element="tns:submitPOResponse"/>
</message>
<message name="InvalidPOException">
<part name="InvalidPOException"
element="tns:InvalidPOException"/>
</message>
<portType name="AnyPurchaseOrderServiceSEI">
<operation name="submitPO">
<input
message="tns:AnyPurchaseOrderServiceSEI_submitPO"/>
<output
message="tns:AnyPurchaseOrderServiceSEI_submitPOResponse"/>
<fault name="InvalidPOException"
message="tns:InvalidPOException"/>
</operation>
</portType>
代码示例 1:服务的 WSDL 的代码片段
服务端点接口
由于我们是从 WSDL 开始的,因此会基于 WSDL 中包含的信息生成代码示例 2 中的服务端点接口。服务端点接口具有一个接收 SubmitPO
对象的 submitPO()
方法。类 SubmitPO
与包含 WSDL 中定义的 xsd:any 的复杂类型相对应,它是一个 JavaBeans[TM] 组件,基本上只是一个包含表示 XML 订单文档的 javax.xml.soap.SOAPElement 的封装类。请注意,响应类型是使用 xsd:any 指定的,因此返回的 XML 文档也具有一个名为 SubmitPOResponse
的 JavaBeans 封装类,该类包含了作为 SOAPELement 的订单 XML 文档。应用程序定义的异常 InvalidPOException
也是从 WSDL 生成的。
public interface
AnyPurchaseOrderServiceSEI extends Remote {
public SubmitPOResponse submitPO(SubmitPO
parameters) throws
InvalidPOException,
RemoteException;
}
代码示例 2:服务端点接口
代码示例 3 显示了从 WSDL 生成的 SubmitPO
类。此 JavaBean 封装类包含作为 SOAPElement 的订单 XML 文档。
public class SubmitPO {
protected javax.xml.soap.SOAPElement _any;
public SubmitPO() {
}
public SubmitPO(javax.xml.soap.SOAPElement _any) {
this._any = _any;
}
public javax.xml.soap.SOAPElement get_any() {
return _any;
}
public void set_any(javax.xml.soap.SOAPElement _any) {
this._any = _any;
}
}
代码示例 3:SubmitPO 封装类包含了作为 SOAP 元素的订单 XML 文档,该元素是从 WSDL 生成的
Java 端点实现
对于此应用程序,我们选择使用 Web 组件实现服务接口。代码示例 4 显示了端点实现类。还可以使用 Enterprise JavaBeans[TM] (EJB[TM]) 组件实现端点。两种选择均可。需要特别注意的是,订单 XML 被作为 SOAPElement 处理,并在为代码示例 3 中显示的 SubmoitPO 包装类调用 get 方法后使用。
public class
AnyPurchaseOrderServiceImpl implements
AnyPurchaseOrderServiceSEI,
ServiceLifecycle {
private ServletEndpointContext context;
private POXMLUtil xmlUtil;
public void init(Object context) {
this.context =
(ServletEndpointContext) context;
xmlUtil = new POXMLUtil();
}
public void destroy() {}
public SubmitPOResponse submitPO(SubmitPO request)
throws InvalidPOException, RemoteException {
String id = null;
SubmitPOResponse reply =
null;
try{
SOAPElement requestdata= request.get_any();
//extract the PO ID
NodeList list =
((Element)requestdata).getElementsByTagNameNS("urn:AnyTypePurchaseOrderService",
"poId");
for
(int loop = 0; loop < list.getLength(); loop++) {
Node node = list.item(loop);
if (node != null) {
Node child = node.getFirstChild();
if ((child != null) && child.getNodeValue() != null){
id = child.getNodeValue();
}
}
}
SOAPElement replydata = xmlUtil.createSOAPMessage(id);
reply = new SubmitPOResponse();
reply.set_any(replydata);
} catch(Exception exe){
throw new RuntimeException("AnyPOService Having
Problems:"+exe.getMessage(), exe);
}
//this is done just to
illustrate throwing an application specific exception
if(id.equals("100"))
throw new InvalidPOException("Invalid ID for the purchase order!!! " +
"For demo purposes, we throw " +
"an application defined exception for the ID value of 100.");
return reply;
}
}
代码示例 4:端点实现
部署描述符
将 Java[TM] 2 Platform, Enterprise Edition(J2EE[TM] 平台)中的 Web 服务打包为 war 或 ear 文件之类的部署模块。在此应用程序中,我们将其打包为一个 war 文件。Web 服务端点的可移植打包需要多个部署描述符以及 Java 类。下面是端点部署描述符中的一些代码片段:
<servlet>
<description>Endpoint for AnyPO Web
Service</description>
<display-name>AnyPurchaseOrderServiceImpl</display-name>
<servlet-name>AnyPurchaseOrderServiceImpl</servlet-name>
<servlet-class>com.sun.j2ee.blueprints.anyposervice.AnyPurchaseOrderServiceImpl</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
代码示例 5:web.xml 部署描述符中的代码片段
该端点还需要一个 Web 服务部署描述符文件 webservices.xml,显示如下:
<webservice-description>
<webservice-description-name>AnyPurchaseOrderService</webservice-description-name>
<wsdl-file>WEB-INF/wsdl/AnyPurchaseOrderService.wsdl</wsdl-file>
<jaxrpc-mapping-file>WEB-INF/anypurchaseorderservice-mapping.xml</jaxrpc-mapping-file>
<port-component>
<description>port component
description</description>
<port-component-name>AnyPurchaseOrderService</port-component-name>
<wsdl-port
xmlns:anypons="urn:AnyPurchaseOrderService">anypons:AnyPurchaseOrderServiceSEIPort
</wsdl-port>
<service-endpoint-interface>com.sun.j2ee.blueprints.anyposervice.AnyPurchaseOrderServiceSEI
</service-endpoint-interface>
<service-impl-bean>
<servlet-link>AnyPurchaseOrderServiceImpl</servlet-link>
</service-impl-bean>
</port-component>
</webservice-description>
代码示例 6:webservice.xml 部署描述符中的代码片段
Web 服务部署描述符文件包含有关服务的信息,例如 WSDL 文件和 JAX-RPC 映射文件的名称以及服务端点接口和服务实现类的名称。
© Sun Microsystems 2005。Java BluePrints Solutions Catalog 中的所有内容受版权保护,未经 Sun Microsystems 的明确书面许可,不得在其他产品中发布。