A Dynamic e-Business Application Using Web Services , Page 3
A successful login process fetches the customer profiles, product details, and his previous order details using synchronous RPC to initialize the customer data models. TradingWebServicesMgr is the component that interacts with the manufacturer Web services on behalf of the customer client. The client makes use of a local proxy object and invokes a method on them. This proxy could be a stub in the case of static binding or a dynamic proxy, a class created by the client at runtime. In this application, the manufacturer Web service description document (TradingWebServices.wsdl) that is generated during deployment is available to the customer either directly or through a link in the public registry. Refer to the Resources section for more information on WSDL. The customer application uses this WSDL document to generate a dynamic proxy at run time and invokes calls on this object. The runtime makes use of serializers and de-serializers to transfer Java objects between the client and server. The code snippet from TradingWebServicesMgr.java below shows steps for creating serializers for the Product class and registering with the service.
// set up serializers and de-serializers CombinedSerializer productSerializer = new Product_SOAPSerializer(productQname, ENCODE_TYPE, NULLABLE, SOAPConstants.URI_ENCODING); productSerializer = new ReferenceableSerializerImpl( SERIALIZE_AS_REF, productSerializer); SerializerFactory productSerializerFactory = new SingletonSerializerFactory(productSerializer); DeserializerFactory productDeSerializerFactory = new SingletonDeserializerFactory(productSerializer); . . . . . . . . . . TypeMappingRegistry registry = service.getTypeMappingRegistry(); TypeMapping typeMapping = registry.getTypeMapping( SOAPConstants.URI_ENCODING); typeMapping.register(Product.class, productQname, productSerializerFactory, productDeSerializerFactory);
The Product_SOAPSerializer class above is created when the xrpc compiler generates Web services ties on the server using information in config.xml. The extract below shows the creation of a dynamic proxy handle with the help of the Web service class and the WSDL document.
ServiceFactory serviceFactory = ServiceFactory.newInstance(); Service service = serviceFactory.createService(etradeWsdlUrl, new QName(wsdlNSUri, serviceName)); . . . . . . . . . . //get the proxy handle tradeIF = (TradingWebServicesIF) service.getPort(new QName(wsdlNSUri, servicePort), Class.forName(serviceClass));
The JAX-RPC runtime establishes a synchronous communication channel between the client proxy and the tie object on the server. Ties are components running at the server complementing the proxy stubs on the client. JAX-RPC uses XML-based remote procedure calls to invoke services on remote systems. The calls and responses are transmitted as SOAP messages over HTTP. The JAX-RPC API hides all the complexity from the developer while writing the client code. Figure 5 shows the communication between a client and server using a dynamic proxy with JAX-RPC.
Figure 5: A synchronous interaction using Java API for XML-RPC
The asynchronous delivery process is implemented using JMS Queue and Topic. The customer performs a lookup for the JMS connection factories and destinations on the LDAP server using the JNDI lookup mechanism. All customer orders in the form of a Purchase Order XML document embedded within a SOAP message is funneled through the JMS Queue and delivered to the manufacturer application. The client code for this is developed using the JAXM API. Shown below is the Purchase Order XML document sent within a SOAP message.
<?xml version="1.0" encoding="UTF-8"?>
<PurchaseOrder custId="JOHNS" poRef="JOHNS1048316652804" poDate="20030322" poValue="25235">
<street>P.O Box 00001</street>
<street>P.O Box 00001</street>
<productName>Presario-2512EA Laptop PC</productName>
<desc>Intel-P4, 2.5GHz, 256MB RAM, 40GB HDD, 15" XGA</desc>
<productName>Presario-2125EA Laptop PC</productName>
<desc>Intel-M Celeron, 2.0GHz, 256MB RAM, 30GB HDD, 15" XGA</desc>
The customer implements a MessageListener interface to receive asynchronous responses from the manufacturer via the JMS Topic destination. The JMS messages are converted to SOAP messages and the embedded data extracted from it. The code snippet from the onMessage() handler below shows how data is extracted from an incoming JMS message.
. . . . . . . . . . TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer = tf.newTransformer(); // convert JMS to SOAP message. SOAPMessage soapMessage = MessageTransformer.SOAPMessageFromJMSMessage( message, MessageFactory.newInstance() ); soapMessage.writeTo(System.out); // Get SOAP part. SOAPPart soapPart = soapMessage.getSOAPPart(); // Get SOAP envelope. SOAPEnvelope soapEnvelope = soapPart.getEnvelope(); // Get the empty SOAP Envelope as a generic Source and put it // into a DOMResult javax.xml.transform.Source spSrc = soapPart.getContent(); javax.xml.transform.dom.DOMResult domResultEnv = new javax.xml.transform.dom.DOMResult(); transformer.transform(spSrc, domResultEnv); // Get the document org.w3c.dom.Node envelopeRoot = domResultEnv.getNode(); . . . . . . . . . .
The internal customer data models are updated upon receipt of appropriate messages from the manufacturer that in turn update the onscreen data. Figure 6 is a screen snapshot of the customer application showing the Order Details tab page. This page is automatically updated when the Manufacturer receives a PO and sends an ACK back or approves the pending order.
Figure 6: Screen snapshot of customer application showing the Order Details tab page
The customer is assembled as a .jar standalone application.