WSDL ファイルは Web サービスの記述です。コード例 1 は、この サービスの WSDL からの抜粋です。開発スタイルとしては、WSDL から始めて、そこから必要な Java[tm] クラスを生成するスタイルを採用しました。このため、WSDL のメッセージ部に適切な型を選択することは非常に重要です。これらの型が、生成される Java インタフェースに含まれるパラメータの型になります。
要求メッセージが type="anyType" と宣言されていることに注意してください。この宣言のため、サービスに対して コード例 2 に示す Java インタフェースが生成され、入力パラメータは Java SOAPElement
型にマッピングされています。また、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:AnyTypePurchaseOrderService">
<complexType name="submitPO">
<sequence>
<element name="BusinessDocumentRequest"
type="anyType" nillable="true"/>
</sequence>
</complexType>
<complexType
name="submitPOResponse">
<sequence>
<element name="result" type="string"
nillable="true"/>
</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="AnyTypePurchaseOrderServiceSEI_submitPO">
<part name="parameters"
element="ns1:submitPO"/>
</message>
<message
name="AnyTypePurchaseOrderServiceSEI_submitPOResponse">
<part name="result"
element="ns1:submitPOResponse"/>
</message>
<message name="InvalidPOException">
<part
name="InvalidPOException" element="ns1:InvalidPOException"/>
</message>
<portType
name="AnyTypePurchaseOrderServiceSEI">
<operation name="submitPO">
<input
message="tns:AnyTypePurchaseOrderServiceSEI_submitPO"/>
<output
message="tns:AnyTypePurchaseOrderServiceSEI_submitPOResponse"/>
<fault
name="InvalidPOException" message="tns:InvalidPOException"/>
</operation>
</portType>
javax.xml.soap.SOAPElement
オブジェクトを受け付ける submitPO()
メソッドがあります。また、アプリケーション定義の例外 InvalidPOException
も WSDL から生成されます。
public interface
AnyTypePurchaseOrderServiceSEI extends Remote {
public String submitPO(SOAPElement
businessDocumentRequest)
throws
InvalidPOException,
RemoteException;
}
コード例 2: サービスエンドポイントインタフェースSOAPElement
として処理されることです。コード例 3 は、エンドポイント実装クラスを示しています。
public class
AnyTypePurchaseOrderServiceBean implements SessionBean {
private SessionContext sc;
private POXMLUtil xmlUtil;
public AnyTypePurchaseOrderServiceBean() {}
public String submitPO(SOAPElement request) throws
InvalidPOException, RemoteException {
String poID = null;
SOAPElement reply = null;
try {
NodeList list = ((Element)request).getElementsByTagName("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){
poID = child.getNodeValue();
}
}
}
} catch (Exception exe) {
throw new EJBException("AnyTypePOService Having
Problems:"+exe.getMessage(), exe);
}
// アプリケーションに固有の例外のスローを紹介することのみを目的としたコード
if(poID.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 poID;
}
// ライフサイクルメソッド
...
}
コード例 3: エンドポイント実装サービス側コードに続いて、このアプリケーションのクライアント側を簡単に説明します。クライアントはコード例 1 の WSD ファイルを使用し、コード例 4 に示すような Java サービスインタフェースを生成します。コード例 5 のクライアントコードで示しているように、この Java インタフェースは注文書をサービスに送信するために使用されます。このクライアントアプリケーションの注文書データは、コード例 6 に示すように、クライアント定義の PurchaseOrder
型にデータを保持する Web アプリケーションからの入力として収集され、この注文書 Java オブジェクトは SOAPElement に変換されてから、サービスに送信されることに注意してください。
public interface
AnyTypePurchaseOrderServiceSEI extends Remote {
public String
submitPO(SOAPElement businessDocumentRequest) throws
com.sun.j2ee.blueprints.docoriented.client.anytypeposervice.InvalidPOException,
RemoteException;
}
public class AnyTypePOServiceBD {
private ServiceLocator serviceLocator;
public AnyTypePOServiceBD(){
serviceLocator = new
ServiceLocator();
}
public String submitPO(PurchaseOrder po) throws
RequestHandlerException {
try {
// このフラグは、WSDL に定義されているように
//ラッパー要素 BusinessDocumentRequest を生成するためのもの
boolean wrapper = true;
AnyTypePurchaseOrderServiceSEI port = (AnyTypePurchaseOrderServiceSEI)
serviceLocator.getServicePort(JNDINames.ANY_TYPE_SERVICE_REF,
AnyTypePurchaseOrderServiceSEI.class);
SOAPElement requestSOAPElem =
po.toXMLSOAPElement(wrapper);
return port.submitPO(requestSOAPElem);
} catch(InvalidPOException
ipe){
ipe.printStackTrace(System.err);
throw new RequestHandlerException("Request Handler Exception: Service
Endpoint Application-Defined Exception "+ipe.getMessage(), ipe);
} catch(RemoteException re){
re.printStackTrace(System.err);
throw new RuntimeException("The web service you are trying to access is
not available. A possible reason could be that the service has not been
deployed yet. "+ re.getMessage(), re);
}
}
}
コード例 5: 注文書 XML ドキュメントを anyType サービスに送信するためのクライアントコードコード例 6 は、クライアントアプリケーションによって生成されるヘルパー PurchaseOrder クラスを示しています。このクライアントアプリケーションでは、Web ページフォームが送信され、PurchaseOrder
にデータが書き込まれます。その後、このクラスは、サービスに送信する注文書 XML ドキュメントの表現の取得に使用されます (コード例 5)。
PurchaseOrder クラスに toXMLSOAPElement()
というメソッドがあることに注目してください。このメソッドは、Java 注文書を変換します。ここで大切なことは、注文書 XML が、このサービスの WSDL に定義されている親要素の BusinessDocumentRequest
内にラップされていることです。このため、anyType を使用してサービスを定義する場合、クライアントは XML ドキュメントを変更し、WSDL に定義されている親要素内にそのドキュメントをラップする必要があります。これは、anyType を使用してサービスと交換するドキュメントを記述するサービスインタフェースを使用するクライアントには多少負担になります。
public class PurchaseOrder
{
private String poId;
private Calendar createDate;
private Address shipTo;
private Address billTo;
private LineItem[] items;
public PurchaseOrder() {}
public PurchaseOrder(String poId, Calendar
createDate,
Address shipTo, Address billTo, LineItem[] items) {
this.poId = poId;
this.shipTo = shipTo;
this.createDate = createDate;
this.billTo = billTo;
this.items = items;
}
...
public SOAPElement toXMLSOAPElement(boolean
wrapper) {
SOAPElement soapElem = null;
try {
// DOM ツリーを作成
DocumentBuilderFactory docBuilderFactory =
DocumentBuilderFactory.newInstance();
docBuilderFactory.setNamespaceAware(true);
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element poElem = doc.createElement("PurchaseOrder");
if(wrapper){
Element docElem = doc.createElement("BusinessDocumentRequest");
doc.appendChild(docElem);
docElem.appendChild(poElem);
}
else{
doc.appendChild(poElem);
}
Element elem = doc.createElement("poId");
elem.appendChild(doc.createTextNode(poId));
poElem.appendChild(elem);
elem
= doc.createElement("createDate");
elem.appendChild(doc.createTextNode((new
SimpleDateFormat("MM-dd-yy")).format(createDate.getTime())));
poElem.appendChild(elem);
elem
= doc.createElement("shipTo");
poElem.appendChild(shipTo.toDOM(doc, elem));
elem
= doc.createElement("billTo");
poElem.appendChild(billTo.toDOM(doc, elem));
for(int i = 0; i < items.length; ++i){
poElem.appendChild(items[i].toDOM(doc));
}
// SOAPElement を作成
SOAPElement parent = SOAPFactory.newInstance().createElement("dummy");
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.transform(new DOMSource(doc), new DOMResult(parent));
soapElem = (SOAPElement) parent.getChildElements().next();
} catch(TransformerException
te) {
te.printStackTrace(System.err);
throw new RuntimeException(te.getMessage(), te);
}
catch(ParserConfigurationException pce) {
pce.printStackTrace(System.err);
throw new RuntimeException(pce.getMessage(), pce);
} catch(SOAPException se) {
se.printStackTrace(System.err);
throw new RuntimeException(se.getMessage(), se);
}
return soapElem;
}
<enterprise-beans>
<session>
<ejb-name>AnyTypePurchaseOrderServiceBean</ejb-name>
<service-endpoint>com.sun.j2ee.blueprints.anytypeposervice.AnyTypePurchaseOrderServiceSEI</service-endpoint>
<ejb-class>com.sun.j2ee.blueprints.anytypeposervice.AnyTypePurchaseOrderServiceBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
コード例 7: ejb-jar.xml 配備記述子からの抜粋
<service-endpoint>
として定義されていることに注意してください。このエンドポイントにはまた、次のような Web サービス配備記述子ファイル webservices.xml も必要です。 <webservice-description>
<webservice-description-name>AnyTypePurchaseOrderService</webservice-description-name>
<wsdl-file>META-INF/wsdl/AnyTypePurchaseOrderService.wsdl</wsdl-file>
<jaxrpc-mapping-file>META-INF/anytypepurchaseorderservice-mapping.xml</jaxrpc-mapping-file>
<port-component>
<description>port component
description</description>
<port-component-name>AnyTypePurchaseOrderService</port-component-name>
<wsdl-port
xmlns:PurchaseOrderns="urn:AnyTypePurchaseOrderService">PurchaseOrderns:AnyTypePurchaseOrderServiceSEIPort</wsdl-port>
<service-endpoint-interface>
com.sun.j2ee.blueprints.anytypeposervice.AnyTypePurchaseOrderServiceSEI
</service-endpoint-interface>
<service-impl-bean>
<ejb-link>AnyTypePurchaseOrderServiceBean</ejb-link>
</service-impl-bean>
</port-component>
</webservice-description>
コード例 8: webservice.xml 配備記述子からの抜粋