[ Team LiB ] Previous Section Next Section

Creating a Web Service with a Stateless Session Bean Back End

The 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 EJBGen
package 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 Types

In 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:

  • Built-in data types are automatically converted between Java and XML by WebLogic Server. This includes the following Java data types: int, short, long, float, double, byte, boolean, char, java.lang.Integer, java.lang.Short, java.lang.Long, java.lang.Float, java.lang.Double, java.lang.Byte, java.lang.Boolean, java.lang.Character, java.lang.String, java.math.BigInteger, java.math.BigDecimal, java.lang.String, java.util.Calendar, java.util.Date, and byte[].

  • Supported data types that are not built in require special components (such as a serializer class) to be used as Web Service parameters. However, the servicegen and autotype Ant tasks can generate these components automatically. This includes the following Java data types: an array of any built-in Java data type, JavaBean whose properties are any built-in Java data type, java.util.List, java.util.ArrayList, java.util.LinkedList, java.util.Vector, and java.lang.Object (in some cases).

  • Not supported and not built-in data types require special components to be used as Web Service parameters. These components must be generated manually.

Creating an Operation with a Supported Data Type

Let'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 Vector
import 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 getLottoNumbers
public 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 Types

Creating a Web Service with a user-defined data type requires the following information:

  • A Java class to represent the user-defined data type

  • An XML schema to describe the Java class

  • A serialization class to convert between the Java class and XML

  • The data mapping information for the Java class

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 Operation
package 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:

  • A XML schema and mapping file called types.xml that describes the DoctorInfo class and how to map from the Java class to XML

  • The files DoctorInfoHolder.java and DoctorInfoCodec.java, which are used as serialization classes

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 Type

We'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 Service
package 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 Service

At this point, you have all the elements of the Web Service:

  • Deployment descriptorweb-service.xml, which was created with source2wsdd

  • User-defined data type components— XML schema (now in web-services.xml) and codec classes created with autotype

  • Java backend component— Some Java component that implements the business logic for 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 ] Previous Section Next Section