1 / 90

J2EE 1.4 APIs For Web Services

J2EE 1.4 APIs For Web Services. Michael D. Thomas mdthomas@ibiblio.org. Agenda. Quick Tour Of J2EE APIs Service Oriented Architecture SOAP & WSDL: The 10 minute guide JAX-RPC SAAJ JAXP JAXR. A Simple Example. Company has web app that looks up invoices The customers like it

salena
Download Presentation

J2EE 1.4 APIs For Web Services

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. J2EE 1.4 APIs For Web Services Michael D. Thomas mdthomas@ibiblio.org

  2. Agenda • Quick Tour Of J2EE APIs • Service Oriented Architecture • SOAP & WSDL: The 10 minute guide • JAX-RPC • SAAJ • JAXP • JAXR

  3. A Simple Example • Company has web app that looks up invoices • The customers like it • Customer wants to pass the data automatically to another application • Typical situation for a web service • Will do it with: • Straight XML (JAXP) • SAAJ: Wrapper around SOAP and HTTP • JAX-RPC: Uses SOAP and WSDL, but you never have to see it

  4. Invoice Screen

  5. Invoice App Structure

  6. Invoice JSP <html> <head> <title>Invoice</title> </head> <body bgcolor="white"> <%@ page language="java" import="org.ibiblio.mdthomas.ws.autopartssupplier.*" %> <jsp:useBean id="invoiceHelper" scope="request" class="org.ibiblio.mdthomas.ws.autopartssupplier.InvoiceHelper"/> <jsp:setProperty name=”invoiceHelper” property=”*”/> <% InvoiceBean invoice = invoiceHelper.getInvoiceById(); CustomerBean customer = invoice.getCustomer(); InvoiceItemBean items[] = invoice.getInvoiceItems(); %> Continued . . . .

  7. Invoice JSP <% for (int i=0; i<items.length;i++) { %> <tr> <td><%= items[i].getName() %></td> <td><%= items[i].getProductId() %></td> <td><%= items[i].getQuantity() %></td> <td align="right"> <%= items[i].getPerItemPrice() %> </td> <td align="right"> <%= items[i].getTotalLineItemPrice() %> </td> </tr> <% } %> Continued . . . .

  8. Invoice Helper package org.ibiblio.mdthomas.ws.autopartssupplier; import java.rmi.Remote; import java.rmi.RemoteException; public class InvoiceHelper { long id; InvoiceBusinessDelegate invoiceBusinessDelegate; public InvoiceHelper () { invoiceBusinessDelegate = BusinessDelegateFactory.getInvoiceBusinessDelegate();} public void setInvoiceId (long id) { this.id = id; } public long getInvoiceId() { return id;} public InvoiceBean getInvoiceById() { return invoiceBusinessDelegate.getInvoiceById(this.id);} public InvoiceBean getInvoiceById(long id) { return invoiceBusinessDelegate.getInvoiceById(id);} }

  9. InvoiceBean (incomplete) package org.ibiblio.mdthomas.ws.autopartssupplier; public class InvoiceBean implements Serializable { private CustomerBean customer; private InvoiceItemBean invoiceItems[]; private long invoiceId; private float total; private float shippingCharge; private float subTotal; public InvoiceBean() {} public float getTotal() { return total;} public void setTotal(float total) { this.total = total;} public void setCustomer(CustomerBean customer) { this.customer = customer;} public CustomerBean getCustomer() { return customer; } public InvoiceItemBean[] getInvoiceItems() { return invoiceItems;} public void setInvoiceItems(InvoiceItemBean items[]) { this.invoiceItems = items;} }

  10. New XML Architecture

  11. XML Invoice

  12. XML Invoice JSP <?xml version="1.0"?> <ordering:invoice xmlns:ordering="http://www.tinasautoparts.com/xmlns/orders"> <%@ page language="java" import="org.ibiblio.mdthomas.ws.autopartssupplier.*" %> <jsp:useBean id="invoiceHelper" scope="request" class="org.ibiblio.mdthomas.ws.autopartssupplier.InvoiceHelper" /> <jsp:setProperty name="invoiceHelper" property="*"/> <% InvoiceBean invoice = invoiceHelper.getInvoiceById(); CustomerBean customer = invoice.getCustomer(); InvoiceItemBean items[] = invoice.getInvoiceItems(); %> <ordering:invoiceId> <%= invoice.getInvoiceId() %> </ordering:invoiceId> Continued . . .

  13. “Web Services” Requestor public static void main(String[] args) throws Exception { long invoiceId = 0; if (args.length>0) { invoiceId = Long.parseLong(args[0]);} // Create the URL and encode the invoiceId param String base = "http://localhost:8080/jsp-examples/ch03/invoiceAsXml.jsp?"; String invoiceParam = "invoiceId="+invoiceId+"&"; URL invoiceURL = new URL(base+invoiceParam); // Connect to the URL URLConnection conn = invoiceURL.openConnection(); conn.connect(); // Get the result and create the XML InputStream invoiceStream = conn.getInputStream(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(invoiceStream); // Handle the XML handleXML(doc); }

  14. “Web Services” Requestor private static void handleXML(Document doc) { float invoiceTotal = 0f; int totalQuantities = 0; float shippingCharge =0f; Element docRoot = doc.getDocumentElement(); NodeList children = docRoot.getChildNodes(); for (int i=0;i<children.getLength();i++) { Node node = children.item(i); System.out.println("node name: "+node.getNodeName()); short nodeType = node.getNodeType(); if (node.getNodeName().equals("ordering:customer")) { Element customerElement = (Element)node; NodeList nodeList = customerElement.getElementsByTagName("ordering:customerName"); Element customerNameElem = (Element)nodeList.item(0); Node customerNameText = customerNameElem.getFirstChild(); String customerName = customerNameText.getNodeValue(); System.out.println("Customer name: "+customerName); } Continued . . .

  15. Basic XML Web Services Issues • Satisfies the business requirement • Not standards based – doesn’t use SOAP or WSDL • Had to handle HTTP directly

  16. SAAJ & SOAP Approach • Uses SOAP standard • Similar to previous example, but requestor handles SOAP details • SOAP: data (Body) and meta-data (Header) • Contained in a SOAP envelope • Can attach data outside of the SOAP envelope • SAAJ: handles HTTP requests, wraps JAXP in SOAP specific nature (like JDOM)

  17. SOAP Request POST /invoice-jaxrpc/invoice HTTP/1.1 Content-Type: text/xml; charset="utf-8" Content-Length: 246 SOAPAction: "" Cache-Control: no-cache Pragma: no-cache User-Agent: Java/1.4.2 Host: localhost:9090 Accept: text/html, text/xml, image/gif, image/jpeg, *; q=.2, */*; q=.2 Connection: keep-alive <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <getInvoiceById xmlns="http://www.ibiblio.org/mdthomas/invoice/types"> <long_1 xmlns="">9845</long_1> </getInvoiceById> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

  18. SOAP Request POST /invoice-jaxrpc/invoice HTTP/1.1 Content-Type: text/xml; charset="utf-8" Content-Length: 246 SOAPAction: "" Cache-Control: no-cache Pragma: no-cache User-Agent: Java/1.4.2 Host: localhost:9090 Accept: text/html, text/xml, image/gif, image/jpeg, *; q=.2, */*; q=.2 Connection: keep-alive <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <getInvoiceById xmlns="http://www.ibiblio.org/mdthomas/invoice/types"> <long_1 xmlns="">9845</long_1> </getInvoiceById> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

  19. SOAP Request POST /invoice-jaxrpc/invoice HTTP/1.1 Content-Type: text/xml; charset="utf-8" Content-Length: 246 SOAPAction: "" Cache-Control: no-cache Pragma: no-cache User-Agent: Java/1.4.2 Host: localhost:9090 Accept: text/html, text/xml, image/gif, image/jpeg, *; q=.2, */*; q=.2 Connection: keep-alive <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <getInvoiceById xmlns="http://www.ibiblio.org/mdthomas/invoice/types"> <long_1 xmlns="">9845</long_1> </getInvoiceById> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

  20. SOAP Response (incomplete) HTTP/1.1 200 OK X-Powered-By: Servlet/2.4 SOAPAction: "" Content-Type: text/xml; charset="utf-8" Transfer-Encoding: chunked Date: Sun, 23 Nov 2003 16:00:17 GMT Server: Sun-Java-System/JWSDP-1.3 <?xml version="1.0" encoding="UTF-8"?> <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns0="http://www.ibiblio.org/mdthomas/invoice/types"> <env:Body> <ns0:getInvoiceByIdResponse> <result> <customer> data </customer> <invoiceId>9845</invoiceId> <invoiceItem> data </invoiceItem> continued…

  21. SAAJ Provider public class InvoiceSAAJProvider extends HttpServlet { MessageFactory messageFactory; public void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/xml"); response.setBufferSize(8192); OutputStream out = response.getOutputStream(); try { // initialize the messageFactory messageFactory = MessageFactory.newInstance(); // Get the requested invoice long invoiceId = getInvoiceId(request); InvoiceHelper invoiceHelper = new InvoiceHelper(); InvoiceBean invoice = invoiceHelper.getInvoiceById(invoiceId); // Create the SOAP output message SOAPMessage outputMessage = createOutputSOAPMessage(invoice); // Write the output SOAP message to the response output stream outputMessage.writeTo(out); } catch (Exception ex) { ex.printStackTrace(); } out.close(); }

  22. SAAJ Provider private long getInvoiceId(HttpServletRequest request) throws SOAPException, IOException { // create the input SOAP message from the request's inputStream MimeHeaders mimeHeaders = getMimeHeaders(request); InputStream inputStream = request.getInputStream(); SOAPMessage inputMessage = messageFactory.createMessage(mimeHeaders,inputStream); // get the SOAP body SOAPPart inputPart = inputMessage.getSOAPPart(); SOAPEnvelope inputEnvelope = inputPart.getEnvelope(); SOAPBody inputBody = inputMessage.getSOAPBody(); // get the invoice id as a String Name getInvName = inputEnvelope.createName("getInvoiceById", null, "http://www.ibiblio.org/mdthomas/invoice/types"); Iterator it = inputBody.getChildElements(getInvName); SOAPElement getInvoiceElem = (SOAPElement)it.next(); Name idName = inputEnvelope.createName("long_1")); it = getInvoiceElem.getChildElements(idName); SOAPElement invoiceIdElem = (SOAPElement)it.next(); // convert to a long and return String invoiceIdStr = invoiceIdElem.getValue(); long invoiceId = Long.parseLong(invoiceIdStr); return invoiceId; }

  23. Creating output private SOAPMessage createOutputSOAPMessage(InvoiceBean invoice) throws SOAPException { // Create a message SOAPMessage outputMessage = messageFactory.createMessage(); SOAPPart outputSoapPart = outputMessage.getSOAPPart(); SOAPEnvelope outputEnvelope = outputSoapPart.getEnvelope(); outputEnvelope.addNamespaceDeclaration("ns0", "http://www.ibiblio.org/mdthomas/invoice/types"); // Get the SOAP header from the message and remove it SOAPHeader header = outputMessage.getSOAPHeader(); header.detachNode(); // Get the SOAP body from the message SOAPBody body = outputMessage.getSOAPBody(); // Add the top level elements Name responseName = outputEnvelope.createName( "getInvoiceByIdResponse", "ns0", null); SOAPElement invoiceElem = body.addBodyElement(responseName); SOAPElement resultElem = invoiceElem.addChildElement("result"); // add the invoice id SOAPElement invoiceIdElem = resultElem.addChildElement("invoiceId"); long invoiceId = invoice.getInvoiceId(); invoiceIdElem.addTextNode(String.valueOf(invoiceId)); // add customer CustomerBean customer = invoice.getCustomer(); SOAPElement customerElem = resultElem.addChildElement("customer"); SOAPElement customerNameElem = customerElem.addChildElement("name");

  24. Creating output (incomplete) //add invoice items InvoiceItemBean items[] = invoice.getInvoiceItems(); for (int i=0;i<items.length;i++) { SOAPElement invoiceItemElem = resultElem.addChildElement("invoiceItems"); SOAPElement nameElem = invoiceItemElem.addChildElement("name"); String name = items[i].getName(); nameElem.addTextNode(name); SOAPElement perItemPriceElem = invoiceItemElem.addChildElement("perItemPrice"); float perItemPrice = items[i].getPerItemPrice(); perItemPriceElem.addTextNode(String.valueOf(perItemPrice)); SOAPElement totalLineItemPriceElem = invoiceItemElem.addChildElement( "totalLineItemPrice"); float totalLineItemPrice = items[i].getTotalLineItemPrice(); totalLineItemPriceElem.addTextNode( String.valueOf(totalLineItemPrice)); SOAPElement quantityElem = invoiceItemElem.addChildElement("quantity"); int qty = items[i].getQuantity(); quantityElem.addTextNode(String.valueOf(qty)); }

  25. Creating output (incomplete) // save and return outputMessage.saveChanges(); return outputMessage; }

  26. SAAJ Requestor public static SOAPMessage createSOAPRequest(long invoiceId) throws SOAPException { // Create message factory MessageFactory messageFactory = MessageFactory.newInstance(); // Create a message SOAPMessage message = messageFactory.createMessage(); SOAPPart soapPart = message.getSOAPPart(); SOAPEnvelope envelope = soapPart.getEnvelope();

  27. SAAJ Requestor // Get the SOAP header from the message and remove it SOAPHeader header = message.getSOAPHeader(); header.detachNode(); // Get the SOAP body from the message SOAPBody soapBody = message.getSOAPBody(); // create the outer invoice element Name getInvoiceName = envelope.createName("getInvoiceById", null, "http://ibiblio.org/invoice/types"); SOAPBodyElement getInvoiceElem = soapBody.addBodyElement(getInvoiceName);

  28. SAAJ Requestor // create the invoice parameter Name invoiceIdName = envelope.createName("long_1",null,""); SOAPElement invoiceIdElem = getInvoiceElem.addChildElement(invoiceIdName); invoiceIdElem.addNamespaceDeclaration("",""); invoiceIdElem.addTextNode(String.valueOf(invoiceId)); message.saveChanges(); return message; }

  29. SAAJ Code Problems • Compliant with SOAP… • Still haven’t done anything with WSDL • Lots and lots of XML creation and parsing • Absolutely no error checking – not even simple type checking • Have to handle all interoperability problems

  30. JAX-RPC

  31. JAX-RPC Service Endpoint Interface package org.ibiblio.mdthomas.ws.autopartssupplier; import java.rmi.Remote; import java.rmi.RemoteException; public interface InvoiceWebService extends Remote { public InvoiceBean getInvoiceById(long id) throws RemoteException; }

  32. JAX-RPC Servant public class InvoiceHelper implements InvoiceWebService { // existingcode }

  33. Run the tools • SEI-to-WSDL tool and WSDL-to-SEI tool are required by JAX-RPC specification • Wscompile and wsdeploy with the Java Web Services Development Pack from Sun • Java2WSDL with Apache Axis

  34. Web Service “home page”

  35. Web Service WSDL

  36. JAX-RPC Requestor public static void main(String[] args) { try { // Get the web service port InvoiceWebService_Service wsDef = new InvoiceWebService_Service_Impl(); InvoiceWebService_PortType stub = wsDef.getInvoiceWebServicePort(); // Create the input parameter GetInvoiceById idWrapper = new GetInvoiceById(1000); // Make the remote call to the web service GetInvoiceByIdResponse invoiceWrapper = stub.getInvoiceById(idWrapper); // Unwrap the result InvoiceBean invoice = invoiceWrapper.getResult(); // Print some data CustomerBean customer = invoice.getCustomer(); System.out.println("Customer: "+customer.getName()); InvoiceItemBean items[] = invoice.getInvoiceItems(); for (int i=0;i<items.length;i++) { System.out.println("item name: "+items[i].getName()); } } catch (Exception ex) { ex.printStackTrace(); } }

  37. JAX-RPC Requestor public static void main(String[] args) { try { // Get the web service port InvoiceWebService_Service wsDef = new InvoiceWebService_Service_Impl(); InvoiceWebService_PortType stub = wsDef.getInvoiceWebServicePort(); // Create the input parameter GetInvoiceById idWrapper = new GetInvoiceById(1000); // Make the remote call to the web service GetInvoiceByIdResponse invoiceWrapper = stub.getInvoiceById(idWrapper); // Unwrap the result InvoiceBean invoice = invoiceWrapper.getResult(); // Print some data CustomerBean customer = invoice.getCustomer(); System.out.println("Customer: "+customer.getName()); InvoiceItemBean items[] = invoice.getInvoiceItems(); for (int i=0;i<items.length;i++) { System.out.println("item name: "+items[i].getName()); } } catch (Exception ex) { ex.printStackTrace(); } }

  38. .NET C# Requestor • Generate C# requestor based on WSDL: >wsdl.exe /language:CS /protocol:SOAP \ http://localhost:8080/invoice/jaxrpc/invoice?WSDL • Entry point: public getInvoiceByIdResponse getInvoiceById( [System.Xml.Serialization.XmlElementAttribute("getInvoiceById", Namespace="http://www.ibiblio.org/mdthomas/invoice/types")] getInvoiceById getInvoiceById1) { object[] results = this.Invoke("getInvoiceById", new object[] {getInvoiceById1}); return ((getInvoiceByIdResponse)(results[0])); }

  39. .NET C# Requestor class JAXClient { [STAThread] static void Main(string[] args) { // Create the stub InvoiceWebService service = new InvoiceWebService(); // Set the endpoint if (args.Length == 1) service.Url = args[0]; else service.Url = "http://localhost:8080/invoice-jaxrpc/invoice"; // create and send the request getInvoiceById idWrapper = new getInvoiceById(); idWrapper.long_1 = 1000; getInvoiceByIdResponse responseWrapper = service.getInvoiceById(idWrapper); // Receive and process the result InvoiceBean invoice = responseWrapper.result; Console.WriteLine("Invoice id: "+invoice.invoiceId); CustomerBean customer = invoice.customer; Console.WriteLine("Customer: "+customer.name); for (int i=0;i<invoice.invoiceItems.Length;i++) { Console.WriteLine("item name: "+invoice.invoiceItems[i].name); } } }

  40. Web Services Architecture • Web Services as a presentation layer technology • Service Oriented Architecture (SOA) & Web Services • Message Exchange Patterns (MEPs) • RPC centric vs. Document centric approaches • Relevant SOAP & WSDL details

  41. Web Services And Presentation Layer

  42. Web Services And Presentation Layer

  43. Fallacies Of Distributed Computing (Peter Deutch) • The network is reliable • Latency is zero • Bandwidth is infinite • The network is secure • Topology doesn’t change • There is one administrator • Transport cost is zero • The network is homogeneous

  44. Waldo On Distributed Computing “…work in distributed object-oriented systems that is based on a model that ignores or denies [the differences between local and remote objects] is doomed to failure, and could easily lead to an industry-wide rejection of the notion of distributed object-based systems." -- Jim Waldo et al, “A Note on Distributed Computing,” 1994

  45. Local objects are different than remote objects • Local objects are different than remote objects because: • Different address spaces (by reference vs. by copy) • Latency • Partial failure • Concurrency

  46. Service Oriented Architecture (SOA) • Services have network interfaces • Service providers and consumers are loosely coupled • Interfaces are coarse grained • Location is transparent • Services can be looked up in a registry • Consumer can bind to a provider at runtime

  47. SOA applied to EJBs • EJBs do distributed computing • J2EE patterns that promote SOA tenets: • Session Façade pattern with Value Objects for “bind” and “execute” • Service Locator pattern for “find”

  48. SOA Applied to EJBs

  49. SOA Applied To Web Services

  50. Message Exchange Patterns • Message Exchange Patterns (MEPs): how messages are exchanged • There are really two: • Request-response • One way • WSDL defines two others, notification and solicit response, which aren’t supported by J2EE and aren’t widely used • Code to MEPs, not to the underlying protocol

More Related