Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 44 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
44
Dung lượng
437,45 KB
Nội dung
The problem from our second attempt to find WSDL documents revolves around the concept of classifications. Because both registry objects for our first query were not classified as the UDDI “wsdlspec” type, they do not have WSDL documents. Unfor- tunately, this is a common programming mistake. If the programmer had assumed that these were both Web services registered with a WSDL URL, the program would have mixed results—the program may work for one query, but not for another. In the case of the false WSDL document output on line 17, if the program had tried to dynamically call the Web service using JAX-RPC, the program would have failed. The answer to our dilemma lies in our call from the Classification object to the RegistryObject in Figure 47.2. If you call getClassifications() from the returned RegistryObject, and if the classification of that object is the “wsdlspec” classification, then you can call getClassifiedObject() to then get the WSDL- classified object, and then retrieve the external link. Listing 47.6 does just that in lines 123 to 150. 064: public void makeCall(String query) throws Exception 065: { 066: if ( m_querymgr == null ) 067: { 068: throw new Exception(“No query manager!!!!! Exiting Æ makeCall()”); 069: } 070: else 071: { 072: 073: Collection findQualifiers = new ArrayList(); 074: findQualifiers.add(FindQualifier.SORT_BY_NAME_DESC); 075: Collection namePatterns = new ArrayList(); 076: namePatterns.add(“%” + query + “%”); 077: 078: BulkResponse response = 079: m_querymgr.findOrganizations(findQualifiers, 080: namePatterns, 081: null, null, null, null); 082: 083: Iterator orgIterator = response.getCollection().iterator(); 084: 085: System.out.println(“Made an organizational query for ‘“ + 086: query + “‘ ”); 087: 088: int orgcnt = 0; 089: while ( orgIterator.hasNext() ) 090: { 091: String orgname = null; 092: String orgdesc = null; Listing 47.6 The solution to our dilemma 412 Item 47 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 093: String svcname = null; 094: 095: //Let’s get every organization that matches the query! 096: Organization org = (Organization) orgIterator.next(); 097: 098: orgname = convertToString(org.getName()); 099: orgdesc = convertToString(org.getDescription()); 100: 101: //Now get the services provided by the organization 102: Iterator svcIter = org.getServices().iterator(); 103: while ( svcIter.hasNext() ) 104: { 105: Service svc = (Service)svcIter.next(); 106: svcname = convertToString(svc.getName()); 107: 108: //Let’s get the service binding object from service 109: Iterator bindit = svc.getServiceBindings().iterator(); 110: while ( bindit.hasNext() ) 111: { 112: ServiceBinding sb = (ServiceBinding)bindit.next(); 113: 114: Iterator speclinkit = 115: sb.getSpecificationLinks().iterator(); 116: while ( speclinkit.hasNext() ) 117: { 118: SpecificationLink slink = 119: (SpecificationLink)speclinkit.next(); 120: 121: RegistryObject ro = slink.getSpecificationObject(); 122: 123: //Now, let’s see the classification object 124: Iterator classit = ro.getClassifications().iterator(); 125: while ( classit.hasNext() ) 126: { 127: Classification classif = 128: (Classification)classit.next(); 129: if ( classif.getValue().equalsIgnoreCase(“wsdlspec”) ) 130: { 131: orgcnt++; 132: System.out.println(orgcnt + 133: “) Organization Name: “ + orgname); 134: System.out.println( 135: “ Organization Desc: “ + orgdesc); 136: System.out.println( 137: “ Service Name: “ + svcname); 138: 139: RegistryObject ro2 = classif.getClassifiedObject(); Listing 47.6 (continued) Where’s the WSDL? Pitfalls of Using JAXR with UDDI 413 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 140: 141: Iterator extlinkit = 142: ro2.getExternalLinks().iterator(); 143: while ( extlinkit.hasNext() ) 144: { 145: ExternalLink extlink = 146: (ExternalLink)extlinkit.next(); 147: 148: System.out.println(“ WSDL: “ + 149: extlink.getExternalURI()); 150: } 151: 152: } 153: } 154: } 155: } 156: } 157: } 158: } 159: } Listing 47.6 (continued) The result of our example is shown in Listing 47.7. In our output, our program only prints the listing of Web services that have WSDL documents. 01: Made an organizational query for ‘trumantruck’ 02: SECOND QUERY 03: Made an organizational query for ‘sched’ 04: 1) Organization Name: LFC Scheduling 05: Organization Desc: 06: Service Name: Classroom Scheduling 07: WSDL: Æ http://www.contest.eraserver.net/Scheduling/Scheduler.asmx?wsdl 08: 2) Organization Name: Interactive Scheduler 09: Organization Desc: 10: Service Name: Interactive Schedule 11: WSDL: Æ http://www.contest.eraserver.net/InteractiveScheduler/ Æ InteractiveScheduler.wsdl Listing 47.7 The output of our solution 414 Item 47 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com It is important to note that we could get to the service much easier. If we knew the name of the service, for example, and we wanted to go directly to the RegistryOb- ject that has the “wsdlspec” classification, we could do a concept query. The Reg- istryObject, shown in Figure 47.2, on page 408, is always a Concept object when using UDDI registries (even though the getSpecificationObject() from the SpecificationLink interface returns the RegistryObject interface to be more flexible for other registries). To demonstrate this, we will show another example of the makeCall() method in Listing 47.8. We will call the findConcepts() method on the BusinessQueryMan- ager object. To constrain the search, we will use the same namePatterns query pat- tern that we used in the previous examples, but we will add a classification constraint on lines 83 to 100. In doing so, the objects that are returned will be Concept objects that have WSDL documents and that match the query pattern passed in as a parameter. 064: public void makeCall(String query) throws Exception 065: { 066: if ( m_querymgr == null ) 067: { 068: throw new Exception(“No query manager!!!!! Exiting Æ makeCall()”); 069: } 070: else 071: { 072: 073: Collection findQualifiers = new ArrayList(); 074: findQualifiers.add(FindQualifier.SORT_BY_NAME_DESC); 075: Collection namePatterns = new ArrayList(); 076: namePatterns.add(“%” + query + “%”); 077: 078: /* 079: * Find the classification scheme defined by 080: * the UDDI spec 081: */ 082: 083: String schemeName = “uddi-org:types”; 084: ClassificationScheme uddiOrgTypes = 085: m_querymgr.findClassificationSchemeByName(null, 086: schemeName); 087: /* 088: * Create a classification, specifying the scheme 089: * and the taxonomy name and value defined for 090: * WSDL documents by the UDDI spec 091: */ 092: BusinessLifeCycleManager blm = 093: m_regserv.getBusinessLifeCycleManager(); Listing 47.8 Good example of querying by concept (continued) Where’s the WSDL? Pitfalls of Using JAXR with UDDI 415 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 094: 095: Classification wsdlSpecClass = 096: blm.createClassification(uddiOrgTypes, 097: “wsdlSpec”, “wsdlSpec”); 098: 099: Collection classifications = new ArrayList(); 100: classifications.add(wsdlSpecClass); 101: 102: // Find concepts 103: BulkResponse response = 104: m_querymgr.findConcepts(null, namePatterns, 105: classifications, null, null); 106: 107: System.out.println(“Made an wsdlSpec concept query for \n’” + 108: “services matching ‘“ +query + “‘“); 109: 110: // Display information about the concepts found 111: int itnum = 0; 112: Iterator iter = response.getCollection().iterator(); 113: if ( !iter.hasNext()) 114: { 115: System.out.println(“ No matching items!”); 116: } 117: while ( iter.hasNext() ) 118: { 119: itnum++; 120: Concept concept = (Concept) iter.next(); 121: System.out.println(itnum + “) Name: “ + 122: convertToString(concept.getName())); 123: System.out.println(“ Description: “ + 124: convertToString(concept.getDescription())); 125: 126: Iterator linkit = concept.getExternalLinks().iterator(); 127: if ( linkit.hasNext() ) 128: { 129: ExternalLink link = 130: (ExternalLink) linkit.next(); 131: System.out.println(“ WSDL: ‘“ + 132: link.getExternalURI() + “‘“); 133: } 134: 135: } 136: } 137: } Listing 47.8 (continued) The result of our program is shown in Listing 47.9. On our concept query for ser- vices with the string ‘sched’ in them with WSDL documents, we had four results. 416 Item 47 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 01: Made an wsdlSpec concept query for 02: ‘services matching ‘truman’ 03: No matching items! 04: SECOND QUERY 05: Made an wsdlSpec concept query for 06: ‘services matching ‘sched’ 07: 1) Name: Continental-com:Schedule-v1 08: Description: Flight schedule 09: WSDL: Æ ‘http://webservices.continental.com/schedule/schedule.asmx?WSDL’ 10: 2) Name: Interactive Scheduler 11: Description: A Web Service that provides a method to schedule Æ meetings into someone else’s calendar. 12: WSDL: Æ ‘http://www.contest.eraserver.net/InteractiveScheduler/ Æ InteractiveScheduler.wsdl’ 13: 3) Name: Lake Forest College-com:SchedulingInterface-v1 14: Description: Scheduling Web Service for Institutions- Æ Scheduling Classes to appropriate rooms 15: WSDL: Æ ‘http://www.contest.eraserver.net/Scheduling/Scheduler.asmx?wsdl’ 16: 4) Name: Metric-com:Aeroflot Flights Schedule 17: Description: Web service deliver on-line flights schedule Æ information 18: WSDL: ‘http://webservices.aeroflot.ru/flightSearch.wsdl’ Listing 47.9 Output of querying by concept In this pitfall, we demonstrated problems that developers encounter when using the JAXR API with UDDI registries. We showed two examples of potential pitfalls while traversing the data structures of the registry and provided solutions for these prob- lems. Because of the difficulty that some programmers have with JAXR and UDDI, reading the JAXR specification is highly recommended. Item 48: Performance Pitfalls in JAX-RPC Application Clients The Java API for XML-based Remote Procedure Calls (JAX-RPC) allows us to continue to think like Java developers when we develop, deploy, and communicate with RPC- based Web services. Although JAX-RPC relies on underlying protocols (HTTP and SOAP), the API hides this complexity from the application developer. Using basic pro- gramming techniques that enterprise developers are accustomed to, you can create a Web service easily. Building a client that communicates with the Web service is also Performance Pitfalls in JAX-RPC Application Clients 417 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com easy—proxy stubs for the Web service can be compiled prior to runtime, they can be dynamically generated at runtime, or the Dynamic Invocation Interface (DII) can be used to discover a Web service’s API on-the-fly. In this pitfall item, we use different techniques in building clients for a simple Web service. We run a timing experiment on each of the techniques and give recommenda- tions for building clients using JAX-RPC. As a result of reading this pitfall item, you will understand the performance implications of using each technique—and hopefully use this to your advantage in your projects. Example Web Service For this pitfall item, we used Sun’s Java Web Services Developer Pack (WSDP) and cre- ated a simple Web service called “SimpleTest.” The Web service has one method called doStuff(), and the interface used to develop this Web service is shown in Listing 48.1. 001: package org.javapitfalls.item48; 002: 003: import java.rmi.Remote; 004: import java.rmi.RemoteException; 005: 006: public interface SimpleTestIF extends Remote 007: { 008: public String doStuff(String s) throws RemoteException; 009: } Listing 48.1 Interface to our simple Web service. The Web Service Description Language (WSDL) that was automatically generated from the tools available with the developer’s pack is shown in Listing 48.2. Because this was automatically generated and deployed with the developer tools that gener- ated this from our Java interface, our implementation class, and deployment descrip- tors, we weren’t forced to write it by hand. As JAX-RPC defines Web services as collections of remote interfaces and methods, WSDL defines Web services as a collec- tion of ports and operations. The WSDL provided in Listing 48.2 is for your reference, as we develop our Web service clients later in the pitfall examples. 001: <?xml version=”1.0” encoding=”UTF-8” ?> 002: <definitions xmlns=”http://schemas.xmlsoap.org/wsdl/” 003: xmlns:tns=”http://org.javapitfalls.item48/wsdl/SimpleTest” Listing 48.2 WSDL for a simple Web service 418 Item 48 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 005: xmlns:xsd=”http://www.w3.org/2001/XMLSchema” 004: xmlns:soap=”http://schemas.xmlsoap.org/wsdl/soap/” 006: name=”SimpleTest” 007: targetNamespace=”http://org.javapitfalls.item48/wsdl/SimpleTest”> 008: <types /> 009: <message name=”SimpleTestIF_doStuff”> 010: <part name=”String_1” type=”xsd:string” /> 011: </message> 012: <message name=”SimpleTestIF_doStuffResponse”> 013: <part name=”result” type=”xsd:string” /> 014: </message> 015: <portType name=”SimpleTestIF”> 016: <operation name=”doStuff” parameterOrder=”String_1”> 017: <input message=”tns:SimpleTestIF_doStuff” /> 018: <output message=”tns:SimpleTestIF_doStuffResponse” /> 019: </operation> 020: </portType> 021: <binding name=”SimpleTestIFBinding” type=”tns:SimpleTestIF”> 022: <operation name=”doStuff”> 023: <input> 024: <soap:body 025: encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/” 026: use=”encoded” 027: namespace=”http://org.javapitfalls.item48/wsdl/SimpleTest” 028: /> 029: </input> 030: <output> 031: <soap:body 032: encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/” 033: use=”encoded” 034: namespace=”http://org.javapitfalls.item48/wsdl/SimpleTest” 035: /> 036: </output> 037: <soap:operation soapAction=”” /> 038: </operation> 039: <soap:binding transport=”http://schemas.xmlsoap.org/soap/http” 040: style=”rpc” /> 041: </binding> 042: <service name=”SimpleTest”> 043: <port name=”SimpleTestIFPort” binding=”tns:SimpleTestIFBinding”> 044: <soap:address xmlns:wsdl=”http://schemas.xmlsoap.org/wsdl/” 045: location=”http://localhost:8080/simpletest-jaxrpc/simpletest” /> 046: </port> 047: </service> 048: </definitions> Listing 48.2 (continued) Performance Pitfalls in JAX-RPC Application Clients 419 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Next, we will get to the meat of this pitfall: writing different clients that will call the doStuff() method on the “SimpleTest” Web service. In the next sections, we show different approaches to building JAX-RPC clients. A Simple Client That Uses Precompiled Stub Classes The first, and easiest, way to call an RPC-style Web service is by using precompiled stubs. To create these stubs, the Java Web Services Developer Pack contains a tool called “wscompile.” As a result, a client can communicate with the Web service inter- face using the java.xml.rpc.Stub interface. The wscompile tool is run against a configuration file listing details about the Web services (the URL of the WSDL, the package name, etc). When the wscompile tool runs successfully, it processes the WSDL for our Web service and generates proxy stubs so that our client can invoke methods on our SimpleTestIF interface at runtime. Listing 48.3 shows a client that uses precompiled stubs. Lines 37 to 40 show the sta- tic createProxy() method that returns the stub that is cast to the SimpleTestIF interface in line 16. As a result, you do not have to know anything about SOAP or WSDL. Instead, you write code like you’re using RMI. Note that in lines 27 and 28, we are printing out the invocation setup time. This will be used later in this pitfall item to compare pre-invocation times with our other techniques. 001: package org.javapitfalls.item48; 002: 003: import javax.xml.rpc.*; 004: import javax.xml.namespace.*; 005: 006: public class NoDynamicStuffClient 007: { 008: public static void main(String[] args) 009: { 010: try 011: { 012: long initial, afterproxy, preInvokeTime, invokeTime; 013: 014: initial = System.currentTimeMillis(); 015: 016: SimpleTestIF simpletest = (SimpleTestIF)createProxy(); 017: 018: afterproxy = System.currentTimeMillis(); 019: preInvokeTime = afterproxy - initial; 020: 021: //Now, invoke our method 022: 023: String response = 024: simpletest.doStuff(“Hi there from NoDynamicStuffClient!”); 025: //Print out stats 026: Listing 48.3 A simple client using precompiled stubs 420 Item 48 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 027: System.out.println(“Invocation setup took “ 028: + preInvokeTime + “ milliseconds.”); 029: 030: } 031: catch ( Exception ex ) 032: { 033: ex.printStackTrace(); 034: } 035: } 036: 037: private static Stub createProxy() 038: { 039: return(Stub)(new SimpleTest_Impl().getSimpleTestIFPort()); 040: } 041:} Listing 48.3 (continued) A Client That Uses Dynamic Proxies for Access JAX-RPC includes the concept of using dynamic proxies—a second way for clients to access Web services. A dynamic proxy class is a class that implements a list of interfaces specified at runtime, and using this technique, does not require pregeneration of the proxy class. Listing 48.4 shows an example of building such a proxy. In line 30, we create a new instance of ServiceFactory. We then specify the service in lines 32 and 33 by passing the URL for our WSDL in the example, as well as the javax.xml.name- space.QName, which represents the value of a qualified name as specified in the XML Schema specification. By calling the getPort() method on our javax.xml.rpc .Service class on lines 35 to 37, we have generated a proxy class that is cast to our orig- inal interface class from Listing 48.1. 001: package org.javapitfalls.item48; 002: 003: import java.net.URL; 004: import javax.xml.rpc.Service; 005: import javax.xml.rpc.JAXRPCException; 006: import javax.xml.namespace.QName; 007: import javax.xml.rpc.ServiceFactory; 008: 009: public class DynamicProxyClient 010: { 011: Listing 48.4 A simple client using dynamic proxies (continued) Performance Pitfalls in JAX-RPC Application Clients 421 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com [...]... 222 GoodDomLookup .java example, 69–71 GoodFileRename .java example, 155–156 GoodLayeredPane .java example, 150 GoodNavigationUtils .java example, 116 GoodRightMouseButton .java example, 85–86 GoodSetSize .java example, 124–125 GoodStringTokenizer .java example, 142–144 GoodURLPost .java example, 135–136 GoodVoter.Servlet .java example, 296–297 GoodWindowsExec .java example, 9–11 GoodWinRedirect .java example, 13–15... Unregistered Version B BadDomLookup .java example, 67 BadExecJavac .java example, 5–6 BadLayeredPane .java example, 147–148 BadLoggerExample, 45–49 BadNavigationUtils .java example, 114–115 BadRightMouseButton .java example, 81–83 BadSetSize .java example, 123 BadStringTokenizer .java example, 141 BadURLPost .java example, 131–132 BadVoterServlet .java example, 292–293 BadWinRedirect .java example, 12 BasicService... http://www.simpopdf.com XMLOutputter, 80 XSLTFilter, 252 XulRunner, 146 See also interfaces class loading, 111–112 ClassNotFoundExceptions, 112 CLASSPATHS, 108 –111 ClipboardService interface, 233 cloneNode() method, 58–59 clustering, 335 code See listings commandAction() method, 177 CommandListener class, 175 commands dir exec() method, 8 GoodWindowsExec .java, 11 java classname, 108 java -r jarname, 108 SQL,... Listing 50. 3 StateTellerBean .java The StateTellerBeanHome interface, shown in Listing 50. 4, extends the EJBHome class so that remote clients can access the application Our application does not use this, but it is provided so that other applications can use it if they want to 01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: package org.javapitfalls.item50; import java. rmi.RemoteException; import javax.ejb.CreateException;... DatabaseAccessControl, 40 databases, creation, destruction and population, 96–98 data corruption, time line of, 275 DatagramChannel class, 18 date formats, 264 dbQueryBean .java example, 105 dbQueryCase .java example, 105 107 DDConnectionBroker class, 281, 286 DefaultContext element, 383 delete() method, 152, 155, 157 depends tag, 89 deploying Java applications, 109 – 110 Design by Contract utility, 59–60 The Design... clients Simpo PDF Merge When Transactions Go Awry, or Consistent State in Stateful Session EJBs 441 01: package org.javapitfalls.item50; 02: 03: import javax.ejb.EJBObject; and Split Unregistered Version - http://www.simpopdf.com 04: import java. rmi.RemoteException; 05: 06: public interface StateTellerBean extends EJBObject { 07: 08: public double getBalance() throws RemoteException; 09: 10: public double... setFrom(Memento source) { 12: imaInt=source.imaInt; 13: imaDouble=source.imaDouble; 14: } 15: Listing 50. 2 MementoExample .java (continued) 440 Simpo PDF Item 50 16: } 17: 18: public MementoExample() { Merge and Split Unregistered Version - http://www.simpopdf.com 19: currentState = new Memento(1,20.0); 20: priorState = new Memento(0,0.0); 21: priorState.setFrom(currentState); 22: } 23: 24: public void changeState(int... (String state), and the tax on the purchase amount is returned We load the properties file in our session bean’s calculateTax() method, and we calculate the sales tax and return it as a double In lines 18 to 31, we load the properties file using the java. io.FileInputStream class and calculate the tax: 001: 002: 003: 004: 005: 006: 007: 008: 009: 010: 011: 012: 013: 014: 015: 016: package org.javapitfalls.item49;... import import java. rmi.RemoteException; javax.ejb.SessionBean; javax.ejb.SessionContext; java. util.Properties; java. io.*; javax.ejb.EJBException; public class BadTaxCalculatorBean implements SessionBean { public double calculateTax(double cost, String state) { Properties p = new Properties(); double tax = 0; Listing 49.1 Bean reading properties file for values (continued) 429 430 Simpo PDF Item 49 017:... (Floyd Marinescu), 340, 364 EJBObject class, 440 embedded code constructs, 266 embedded comment syntax, 266 employeeFormBean .java example, 101 102 employeeFormBeanTestCase .java example, 102 103 enabling assertions, 64–65 Endorsed Standards Override Mechanism (ESOM), 59 Enterprise JavaBeans (EJBs) overview, 291 primary keys for, generating application server-specific approach, 363 client control approach, . classifications = new ArrayList(); 100 : classifications.add(wsdlSpecClass); 101 : 102 : // Find concepts 103 : BulkResponse response = 104 : m_querymgr.findConcepts(null, namePatterns, 105 : classifications,. convertToString(org.getDescription()); 100 : 101 : //Now get the services provided by the organization 102 : Iterator svcIter = org.getServices().iterator(); 103 : while ( svcIter.hasNext() ) 104 : { 105 : Service svc. parameter on line 52, and we invoke the method on line 63. 001: package org.javapitfalls.item48; 002: 003: import java. net.*; 004: import javax.xml.rpc.*; 005: import javax.xml.namespace.*; 006: 007: