The WSDL file describes the web service. Code
Example 1 contains a
snippet from the WSDL for this service. The development style we
chose was to start with WSDL and generate the necessary Java[TM]
classes
from it. So choosing the proper types for the message parts in the WSDL
is very important, since these types will result in the types of the
parameters in the generated Java interface. Note that the request
message is declared to be type="anyType",
which results
in the generated Java interface shown in Code Example 2 of the service,
which maps the
input parameter to the Java SOAPElement
type. Also, note an application-defined service exception declared in
the 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>
submitPO()
method that accepts a
javax.xml.soap.SOAPElement
object.
Also, the application defined exception InvalidPOException
is generated from the WSDL.public interface
AnyTypePurchaseOrderServiceSEI extends Remote {
public String submitPO(SOAPElement
businessDocumentRequest)
throws
InvalidPOException,
RemoteException;
}
Code Example 2: The Service Endpoint InterfaceSOAPElement
.
The endpoint implementation class is shown in Code
Example 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);
}
//this is done just to
illustrate throwing an application specific exception
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;
}
//life cycle methods
...
}
Code Example 3: The Endpoint ImplementationNow that we have seen the service code, let's also briefly look at
the client for this application. The client would use the WSDL file in Code Example 1 and generate a Java
service interface as in Code Example 4,
and this Java interface of
the service would be used as in the client code in Code Example 5 to
send the purchase order to the service. Note that the purchase order
data in this client application is gathered as input from a web
application which holds the data in a client-defined PurchaseOrder
type as shown in Code Example 6, and
this purchase order Java object is converted to a SOAPElement,
which is then sent to
the service.
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 {
//this flag is to generate a wrapper element BusinessDocumentRequest
//as
defined in the WSDL
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);
}
}
}
Code Example 5: Client Code for
Sending a Purchase Order XML Document to the
anyType ServiceThe helper PurchaseOrder
class generated by the client application is shown in Code Example 6. In the client application,
a web page form is submitted and then the PurchaseOrder
is populated with data. Then this class is used in Code Example 5 to get a
representation
of the purchase order XML document to be submitted to the
service. Notice that
the
PurchaseOrder class has a method toXMLSOAPElement()
,
which converts the Java purchase order.
The key thing to notice is that the purchase order XML is wrapped
inside of a parent element BusinessDocumentRequest
which
is defined in the WSDL for this service.
So, when using anyTpe to define a service, clients must modify the XML
document and wrap it in the parent element defined in the WSDL. This
puts a bit of a burden on the clients that want to use service
interface, which uses anyType to represent the documents being
exchanged
with the service.
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 {
//construct the DOM tree
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));
}
//create a 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>
Code Example 7: Snippet From ejb-jar.xml Deployment
Descriptor<service-endpoint>
in ejb-jar.xml. The endpoint also needs a web services deployment
descriptor file, webservices.xml, like this: <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>
Code Example 8: Snippet From webservice.xml
Deployment Descriptor