Enterprise beans can be used for both developing and accessing Web service applications. Enterprises can apply enterprise beans technology to access a Web service from an enterprise bean implementation class. This is necessary when an enterprise application needs to send information to or receive information from an external application, such as an application in another enterprise. Because the external application might not be written as an enterprise bean or as a Java application and might require communication across the Internet, it is advantageous to use Web services technology to access the external application. Typically, an application client developer obtains a WSDL document describing the Web service and configures a service reference in an enterprise bean's environment. The EJB 2.1 architecture specifies how a bean developer can have the bean reference a Web service through a declaration in the bean's deployment descriptor. The deployer can then link the bean to a Web service installation. This implies that the Web service to be accessed is known at development time. However, the network endpoint (the host name and TCP/IP port number) may be provided by the deployer when deployment occurs. This mechanism is similar to the ejb-ref mechanism by which an enterprise bean can declare a reference to other enterprise beans. For referencing Web services, the enterprise bean declares a service-ref element in its deployment descriptor. The service-ref element indicates the JNDI name in the java:comp/env namespace at which the lookup of the Web service endpoint is performed along with the expected Java type of the service interface for the Web service. This service interface has methods to return the proxy, or stub, object for each port type in the Web service. The proxy object implements the Java service endpoint interface to which the port type has been mapped. The Java service endpoint interface contains the methods for each operation in the port type. The EJB component can invoke these methods on the proxy object to send a request to the Web service. The service-ref element also contains the location of the WSDL file from which the service interface was created and the location of the JAX-RPC mapping file. This mapping, which is itself an XML document, provides details of how the Java service interface was generated from the WSDL. Its format is the same as the mapping file provided by a stateful session bean that implements a Web service endpoint. Finally, the service-ref element in an enterprise bean's deployment descriptor may also include a list of JAX-RPC Handler classes that are to be used during invocations on specific ports in the Web service. These handlers are invoked by the container before it sends the SOAP request message to the Web service and after it receives the SOAP response message from the Web service. Let's look at an example that puts these techniques into practice. 9.4.1 Accessing a Web Service ExampleThis example illustrates the possibilities for further extending the integration of Star Enterprise's benefits enrollment system with its insurance providers' plan administration applications. Providence Health, a provider of health insurance plans, has installed in its enterprise a Web service that its clients use to access information about plan contents and costs. Star Enterprise decides to use this existing Web service and to "pull" information from Providence Health's Web service when an employee requests information about Providence Health's health plans. Recall from the example in Chapter 8 that Star Enterprise uses a PlanEJB entity bean to store insurance plan information. This entity bean, which uses container-managed persistence, was developed by Wombat Inc. In that example, the PlanEJB bean stored its persistent state in BenefitsDatabase. We now develop an entity bean that delegates its business methods to Providence Health's Web service. This entity bean, ProvidencePlanEJB, is developed with bean-managed persistence. ProvidencePlanEJB extends PlanEJB and "wraps" the Web service from Providence Health. But first let us look at the Providence Health Web service itself. 9.4.2 Providence Health Web ServiceProvidence Health provides a description of its Web service to Star Enterprise, using a WSDL document (Code Example 9.4): Code Example 9.4 WSDL Description of the Providence Health Web Service[View full width] <?xml version="1.0" encoding="UTF-8"?> <definitions name="Providence" targetNamespace="providence" xmlns:tns="providence" Star Enterprise's IT department uses this WSDL description as a starting point from which it maps the ProvidenceWebSvc port type to a Java service endpoint interface by using a tool that implements the JAX-RPC standard. The tool also generates a service class, ProvidenceWebService, from which a client can obtain a proxy, or stub, for the ProvidenceWebSvcPort port. In our example, the Web service has only one port. In general, the service class provides proxies for all ports declared in the Web service. Code Example 9.5 shows the code for the ProvidenceWebSvcPort interface: Code Example 9.5 The ProvidenceWebSvcPort Service Endpoint Interfacepublic interface ProvidenceWebSvcPort extends java.rmi.Remote { public double getCost(String planId, int coverage, int age, boolean isSmoker) throws java.rmi.RemoteException; public com.star.plan.providence.DoctorInfo[] getDoctorInfo( String planId, com.star.plan.providence.DoctorInfo doctorQuery) throws java.rmi.RemoteException; public com.star.plan.providence.PlanInfo[] getPlanInfo( String planId, String planType, com.star.plan.providence.DoctorInfo doctorQuery) throws java.rmi.RemoteException; } The preceding service endpoint interface is a typical JAX-RPC service endpoint interface. Note that it contains business methods that use Java primitive types and the value types PlanInfo and DoctorInfo. The getDoctorInfo and getPlanInfo methods return an array of PlanInfo or DoctorInfo objects corresponding to the criteria specified by the respective method parameters. For example, the doctorQuery parameter provides a partial set of fields against which the Web service matches doctor records to choose the records to be returned. Comparing the WSDL document and the Java interfaces, it is obvious that the Java interface is simpler to understand and hides the complexity of the WSDL document. 9.4.3 ProvidencePlanEJB Entity BeanThe ProvidencePlanEJB entity bean integrates the Providence Health Web service with the Benefits Enrollment application developed by Wombat and deployed in Star Enterprise. The bean's home and component interfaces are PlanHome and Plan, which were described in Chapter 8. Because ProvidencePlanEJB uses PlanEJB's PlanHome and Plan interfaces, all clients of PlanEJB can use ProvidencePlanEJB with no code changes or recompilation. The bean implementation class for ProvidencePlanEJB, ProvidencePlanBean, uses bean-managed persistence. Instead of storing its state in BenefitsDatabase, ProvidencePlanEJB delegates all its operations to the Providence Health Web service. Thus, ProvidencePlanEJB does not itself load or store any persistent state. See Code Example A.15 on page 431 for the complete code listing for the ProvidencePlanBean class. Code Example 9.6 shows the code for the setEntityContext method in ProvidencePlanBean for obtaining a reference to a service endpoint interface. The method obtains a reference to the ProvidenceWebSvcPort service endpoint interface, as well as the DoctorHome object: Code Example 9.6 Obtaining a Web Service Referencepublic void setEntityContext(EntityContext ctx) { super.setEntityContext(ctx); try { InitialContext ic = new InitialContext(); ProvidenceWebService service = ( ProvidenceWebService)ic.lookup( "java:comp/env/service/ProvidenceWebService"); providence = service.getProvidenceWebSvcPort(); doctorHome = (DoctorHome)ic.lookup( "java:comp/env/ejb/ProvidenceDoctorEJB"); } catch ( Exception ex ) { throw new EJBException(ex); } } The service endpoint reference is declared in ProvidencePlanEJB's deployment descriptor, using a service-ref element. The deployer links this reference to an instance of ProvidenceWebService. Code Example 9.7 shows the getDoctorsBySpecialty business method in the ProvidencePlanBean class. This method delegates to the getDoctorInfo operation in ProvidenceWebSvcPort: Code Example 9.7 The getDoctorsBySpecialty Business Methodpublic Collection getDoctorsBySpecialty(String specialty) throws FinderException, RemoteException { DoctorInfo doctorQuery = new DoctorInfo(); doctorQuery.setSpecialty(specialty); DoctorInfo[] doctors = providence.getDoctorInfo( getPlanId(), doctorQuery); return convertToCollection(doctors); } 9.4.4 ProvidenceDoctorEJB Entity BeanThe ProvidenceDoctorEJB entity bean integrates the Providence Health Web service with the DoctorEJB interfaces in the Benefits Enrollment application deployed in Star Enterprise. The DoctorEJB bean's home and component interfaces are DoctorHome and Doctor, which are described in Section 8.2.6, DoctorEJB Entity Bean, on page 279. Because ProvidenceDoctorEJB uses DoctorEJB's DoctorHome and Doctor interfaces, all clients of DoctorEJB can use ProvidenceDoctorEJB with no code changes or recompilation. The implementation class for ProvidenceDoctorEJB, ProvidenceDoctorBean, uses bean-managed persistence and delegates all its operations to the Providence Health Web service. See Code Example A.16 on page 439 for the complete code listing for the ProvidenceDoctorBean class. 9.4.5 PackagingStar Enterprise packages the beans ProvidencePlanEJB and ProvidenceDoctorEJB consisting of the bean classes and the home and component interfaces the supporting ProvidenceWebService interface and referenced interfaces and classes, the WSDL file for Providence Health's Web service, the XML Java mapping file, and the EJB deployment descriptor (ejb-jar.xml) into an ejb-jar file called providence.jar. Note that Star Enterprise does not package in providence.jar the stub or proxy classes nor the classes for the serialization and deserialization of the XML schema elements that are described in the Providence Health Web service's WSDL description. Instead, the application server generates these classes at deployment. This JAR file is then packaged along with the other JAR files in the Benefits Enrollment application and deployed in Star Enterprise's application server. |