[ Team LiB ] |
Creating a Web Service with a Stateless Session Bean Back EndThe process of creating a Web Service from a Stateless Session Bean is pretty straightforward. Implement the bean and create its JAR file. Listing 30.7 contains the code for the DoctorInfoBean. Running the EJBGen tool against it will create the EJB support classes and the EJB JAR file. Listing 30.7 Stateless Session Bean Using EJBGenpackage com.wls8unleashed.webservices; // This is an EJBGen-annotated class import java.rmi.RemoteException; import java.util.*; import javax.ejb.*; import javax.naming.*; import javax.rmi.PortableRemoteObject; /** * * @ejbgen:session * ejb-name = DoctorInfoEJB * default-transaction = Required * * @ejbgen:jndi-name * remote = com.wls8unleashed.webservices.DoctorInfoHome * * @ejbgen:ejb-client-jar * file-name = DoctorInfo_client.jar */ public class DoctorInfoBean implements SessionBean { private SessionContext ctx; /** * @ejbgen:remote-method */ public String getGreeting(String name) { return "Hello, " + name + " the local time is " + new java.util.Date(); } public void setSessionContext(SessionContext c) { ctx = c; } public void ejbCreate() {} public void ejbActivate() {} public void ejbPassivate() {} public void ejbRemove() {} } Place the JAR file in a staging directory and create an Ant script that contains the servicegen task, as shown in Listing 30.8. Here you can see that the EJB JAR file is listed. Listing 30.8 Ant Build Script for Creating a Web Service with a Stateless Session Bean<project name="buildWebservice" default="ear"> <target name="ear"> <servicegen destEar="DoctorInfoWS.ear" contextURI="MedicalServices" > <classpath> <pathelement path="${java.class.path}" /> <pathelement path="." /> </classpath> <service ejbJar="DoctorInfo.jar" targetNamespace="http://www.getgamma.com/webservices/ejb" serviceName="DoctorInfoWS" serviceURI="/DoctorInfoWS" generateTypes="True" expandMethods="True" style="rpc" > <client packageName="com.wls8unleashed.webservices.ejb" /> </service> </servicegen> </target> </project> When you run the script file, the DoctorInfoWS.ear will be created. Deploy this file and the embedded DoctorInfo EJB will be deployed as well. The Web Service home page is located at http://host:port/MedicalServices/DoctorInfoWS. Working with Nonsimple Data TypesIn the TestWS Web Service, getGreeting accepts a String as input and returns a String as output. String is a commonly used data type and is considered a built-in data type. However, Web Services deployed in the real world have more complex data type requirements. WebLogic Server defines three types of Web Service operation parameters:
Creating an Operation with a Supported Data TypeLet's create a Web Service that returns six numbers suitable for playing lotto, except that the same number can show up more than once. Our Web Service returns these numbers as a vector, as shown in Listing 30.9. Listing 30.9 Web Service Returning a Vectorimport java.util.Date; import java.util.Vector; public class LottoWebService { public LottoWebService () { } public Vector getLottoNumbers() { Vector vec = new Vector(); for(int i=0; i<6; i++) { Integer lottoNumber = new Integer((int)(Math.random()*60)+1); vec.add(lottoNumber); } return vec; } } If we run the build.xml that contains the Ant servicegen task, we will generate a new testWebService.ear file. Just as before, there will be a TestWS_client.jar in the web-services.war within the EAR file. There will now be two extra classes: VectorHolder and VectorCodec. These files will be used to convert between the Java data type Vector and XML. We can now create a static Java client that calls the getLottoNumbers operation as shown in Listing 30.10. The JAX-RPC runtime handles all the code required to convert between the Vector data type and XML. In this case, it has converted the Vector to an array of Objects. Listing 30.10 Web Service Client Calling getLottoNumberspublic void callWS(String wsdlURI) { try { TestWSPort testWS = null; if (wsdlURI == null) { testWS = new TestWS_Impl().getTestWSPort(); } else { testWS = new TestWS_Impl(wsdlURI).getTestWSPort(); } System.out.print("Lotto numbers are: "); Object[] nums = testWS.getLottoNumbers(); for(int i=0; i<nums.length; i++) { Integer lottoNumber = (Integer)nums[i]; System.out.print(lottoNumber.toString()+" "); } System.out.println(" Good Luck!"); } catch (Exception e) { e.printStackTrace(); } } Working with User-Defined Data TypesCreating a Web Service with a user-defined data type requires the following information:
In some cases, this information can be automatically generated with the autotype Ant task. For example, suppose that we want to return a variable of type DoctorInfo from a Web Service operation, as shown in Listing 30.11. This class must implement Serializable and must contain a no-argument constructor. Listing 30.11 A User-Defined Java Class to Be Returned from a Web Service Operationpackage com.wls8unleashed.webservices.autotype; import java.io.Serializable; public class DoctorInfo implements Serializable { public int id; public String firstName; public String lastName; public float officeVisitCharge; public DoctorInfo() { } public DoctorInfo(int id, String firstName, String lastName, float officeVisitCharge) { this.id = id; this.firstName = firstName; this.lastName = lastName; this.officeVisitCharge = officeVisitCharge; } } To generate the required information, create an Ant build script that calls the autotype Ant task. An example of this is shown in Listing 30.12. Listing 30.12 Ant Build Script for Invoking the autotype Ant Task<project name="createAutotype" default="createautotype"> <target name="createautotype"> <autotype javatypes="com.wls8unleashed.webservices.autotype.DoctorInfo" targetNamespace="http://www.getgamma.com/autotyper" packageName="com.wls8unleashed.webservices.autotype" destDir="d:\tempautotype" > <classpath> <pathelement path="${java.class.path}" /> <pathelement path="." /> </classpath> </autotype> </target> </project> This script instructs autotype to create the data typing components for the DoctorInfo class in the com.wls8unleashed.webservices.autotype package. It will place these components in the d:\tempautotype directory. The following components will be generated:
For a list of supported data types and other information about autotype, please visit http://e-docs.bea.com/wls/docs81/webserv/assemble.html#1060696. Creating a Web Service with a User-Defined Data TypeWe're now going to create a Web Service based on the Java class file in Listing 30.13. In previous releases of WebLogic Server, we used the servicegen Ant task to create the entire Web Service, including the EAR file, its internal WAR file, and the Web Service deployment descriptor, web-services.xml. Now that we have a user-defined data type, we have to perform some of this by hand. Listing 30.13 Java Class Used as Web Servicepackage com.wls8unleashed.webservices.autotype; import java.util.Hashtable; public class DoctorWebService { Hashtable doctorHash = null; public DoctorWebService() { doctorHash = new Hashtable(); DoctorInfo di = new DoctorInfo(1, "Troy", "Chin", 89.25f); doctorHash.put(new Integer(1), di); di = new DoctorInfo(2, "Rina", "Caprario", 95.72f); doctorHash.put(new Integer(2), di); } public DoctorInfo getDoctorInfo(int doctorID) { Object key = new Integer(doctorID); DoctorInfo di = (DoctorInfo)doctorHash.get(key); return di; } } We need to generate a web-services.xml deployment descriptor for our Web Service. WebLogic comes with an Ant task called source2wsdd that can create a web-services.xml file from a Java class. Because we're using a Java class back end for our Web Service, we can use source2wsdd as shown in Listing 30.14. Listing 30.14 Script File to Invoke source2wsdd<project name="createWSDD" default="WSDD"> <target name="WSDD"> <source2wsdd javaSource="DoctorWebService.java" typesInfo="d:\tempautotype\types.xml" ddFile="web-services.xml" serviceURI="/DoctorAutoTypeService"> <classpath> <pathelement path="${java.class.path}" /> <pathelement path="." /> </classpath> </source2wsdd> </target> </project> Listing 30.14 uses the XML schema information for DoctorInfo that's contained in types.xml, which was generated by autotype. When this script is executed, it will create a web-services.xml file that contains our XML schema information. More information about source2wsdd can be found at http://e-docs.bea.com/wls/docs81/webserv/assemble.html#1056639. Assembling the Web ServiceAt this point, you have all the elements of the Web Service:
You can assemble these by hand into a deployable EAR file, or you can use the wspackage Ant task. A build script that uses wspackage is shown in Listing 30.15. Listing 30.15 Script File to Invoke wspackage<project name="createWSDD" default="WSDD"> <target name="WSDD"> <wspackage output="DoctorWebService.ear" contextURI="DoctorWebService" codecDir="d:\tempautotype" webAppClasses="com.wls8unleashed.webservices.autotype.DoctorWebService" ddFile="web-services.xml"> <classpath> <pathelement path="${java.class.path}" /> <pathelement path="." /> </classpath> </wspackage> </target> </project> In Listing 30.15, we specify the location of web-services.xml, the Java backend class for the Web Service, where the codecs (serialization classes) are stored, and the contextURI of the Web Service. After this script has been executed, you'll have a DoctorWebService.ear file that can then be deployed. After the EAR file has been deployed, the Web Service home page will be located at http://host:port/DoctorWebService/DoctorAutoTypeService. TIP We've used Ant tasks to automate generation of the web-services.xml file, XML schema and data mapping, and serialization classes. If you need to perform these tasks manually, please visit the following URL for more information: http://e-docs.bea.com/wls/docs81/webserv/customdata.html. |
[ Team LiB ] |