bea.com | products | dev2dev | support | askBEA

Download Docs | Site Map | Glossary
Search

Programming WebLogic Web Services

Creating a WebLogic Web Service: A Simple Example

The following sections describe a simple example of creating a WebLogic Web service:

- Description of the Example

- Example of Creating a WebLogic Web Service: Main Steps

- Writing the Java Code for the EJB

- Writing the Java Code for the Non-Built-In Data Type

- Creating EJB Deployment Descriptors

- Assembling the EJB

- Creating the build.xml Ant Build File

Description of the Example

This example describes the start-to-finish process of implementing, assembling, and deploying the WebLogic Web service provided as a product example in the directory WL_HOME\samples\server\src\examples\webservices\complex\statelessSession, where WL_HOME refers to the main WebLogic Platform directory.

The example shows how to create a WebLogic Web service based on a stateless session EJB. The example uses the Trader EJB, one of the EJB 2.0 examples located in the WL_HOME\samples\server\src\examples\ejb20\basic\statelessSession directory.

The Trader EJB defines two methods, buy() and sell(), that take as input a String stock symbol and an int number of shares to buy or sell. Both methods return a non-built-in data type called TradeResult.

When the Trader EJB is converted into a Web service, the two methods become public operations defined in the WSDL of the Web service. The Client.java application uses a JAX-RPC style client API to create SOAP messages that invoke the operations.

Example of Creating a WebLogic Web Service: Main Steps

To create the sample Trader WebLogic Web service, follow these steps:

1. Set up your environment.

   On Windows NT, execute the setExamplesEnv.cmd command, located in the directory WL_HOME\samples\server\config\examples, where WL_HOME is the main directory of your WebLogic Platform.

   On UNIX, execute the setEnv.sh command, located in the directory WL_HOME/samples/server/config/examples, where WL_HOME is the main directory of your WebLogic Platform.

2. Write the Java interfaces and classes for the Trader stateless session EJB.

   See Writing the Java Code for the EJB.

3. Write the Java code for the TradeResult non-built-in data type.

   See Writing the Java Code for the Non-Built-In Data Type.

4. Compile the Java code into class files.

5. Create the EJB deployment descriptors.

   See Creating EJB Deployment Descriptors.

6. Assemble the EJB class files and deployment descriptors into a trader.jar archive file.

   See Assembling the EJB.

7. Create the build.xml Ant build file. This file will execute the servicegen Ant task used to assemble the WebLogic Web service.

   See Creating the build.xml Ant Build File.

8. Create a staging directory.

9. Copy the EJB trader.jar file and the build.xml file into the staging directory.

10. Execute the Java Ant utility to assemble the Trader Web service into a trader.ear archive file:

    >     $ ant

11. Auto-deploy the Trader Web service to WebLogic Server for testing purposes by copying the trader.ear archive file to the domain/applications directory, where domain refers to the location of your domain.

12. View the Home Page of the Trader Web serivce by invoking the following URL in your browser:

    >     http://localhost:port/webservice/TraderService

    where

    - localhost refers to the machine on which WebLogic Server is running

    - port refers to port on which WebLogic Server is listening

    From the Web Service Home Page you can view the generated WSDL and test the Web service to make sure it's working correctly.

To invoke the Trader Web service from a Java client application, see the Client.java file in the WL_HOME\samples\server\src\examples\webservices\complex\statelessSession directory.

For instructions for building and running the client application, invoke the WL_HOME\samples\server\src\examples\webservices\complex\statelessSession\package-summary.html Web page in your browser.

Writing the Java Code for the EJB

The sample Trader stateless session EJB contains two public methods: buy() and sell(). The Trader EJB defines two methods, buy() and sell(), that take as input a String stock symbol and an int number of shares to buy or sell. Both methods return a non-built-in data type called TraderResult.

The following Java code is the public interface of the Trader EJB:

>     package examples.webservices.complex.statelessSession;

>     import java.rmi.RemoteException;
>     import javax.ejb.EJBObject;

>     /**
>      * The methods in this interface are the public face of TraderBean.
>      * The signatures of the methods are identical to those of the EJBean, except
>      * that these methods throw a java.rmi.RemoteException.
>      * Note that the EJBean does not implement this interface. The corresponding
>      * code-generated EJBObject, TraderBeanE, implements this interface and
>      * delegates to the bean.
>      *
>      * @author Copyright (c) 1999-2002 by BEA Systems, Inc. All Rights Reserved.
>      */

>     public interface Trader extends EJBObject {
>       /**
>        * Buys shares of a stock.
>        *
>        * @param stockSymbol       String Stock symbol
>        * @param shares            int Number of shares to buy
>        * @return                  TradeResult Trade Result
>        * @exception               RemoteException if there is
>        *                          a communications or systems failure
>        */
>       public  TradeResult buy (String stockSymbol, int shares)
>         throws RemoteException;
>       /**
>        * Sells shares of a stock.
>        *
>        * @param stockSymbol       String Stock symbol
>        * @param shares            int Number of shares to sell
>        * @return                  TradeResult Trade Result
>        * @exception               RemoteException if there is
>        *                          a communications or systems failure
>        */
>       public TradeResult sell (String stockSymbol, int shares)
>         throws RemoteException;
>     }

The following Java code is the actual stateless session EJB class:

>     package examples.webservices.complex.statelessSession;

>     import javax.ejb.CreateException;
>     import javax.ejb.SessionBean;
>     import javax.ejb.SessionContext;
>     import javax.naming.InitialContext;
>     import javax.naming.NamingException;

>     /**
>      * TraderBean is a stateless Session Bean. This bean illustrates:
>      * <ul>
>      * <li> No persistence of state between calls to the Session Bean
>      * <li> Looking up values from the Environment
>      * </ul>
>      *
>      * @author Copyright (c) 1999-2002 by BEA Systems, Inc. All Rights Reserved.
>      */
>     public class TraderBean implements SessionBean {

>       private static final boolean VERBOSE = true;
>       private SessionContext ctx;
>       private int tradeLimit;

>       // You might also consider using WebLogic's log service
>       private void log(String s) {
>         if (VERBOSE) System.out.println(s);
>       }

>       /**
>        * This method is required by the EJB Specification,
>        * but is not used by this example.
>        *
>        */
>       public void ejbActivate() {
>         log("ejbActivate called");
>       }

>       /**
>        * This method is required by the EJB Specification,
>        * but is not used by this example.
>        *
>        */
>       public void ejbRemove() {
>         log("ejbRemove called");
>       }

>       /**
>        * This method is required by the EJB Specification,
>        * but is not used by this example.
>        *
>        */
>       public void ejbPassivate() {
>         log("ejbPassivate called");
>       }

>       /**
>        * Sets the session context.
>        *
>        * @param ctx               SessionContext Context for session
>        */
>       public void setSessionContext(SessionContext ctx) {
>         log("setSessionContext called");
>         this.ctx = ctx;
>       }

>       /**
>        * This method corresponds to the create method in the home interface
>        * "TraderHome.java".
>        * The parameter sets of the two methods are identical. When the client calls
>        * <code>TraderHome.create()</code>, the container allocates an instance of
>        * the EJBean and calls <code>ejbCreate()</code>.
>        *
>        * @exception               javax.ejb.CreateException if there is
>        *                          a communications or systems failure
>        * @see                     examples.ejb11.basic.statelessSession.Trader
>        */
>       public void ejbCreate () throws CreateException {
>         log("ejbCreate called");
>         try {
>           InitialContext ic = new InitialContext();
>           Integer tl = (Integer) ic.lookup("java:/comp/env/tradeLimit");
>           tradeLimit = tl.intValue();
>         } catch (NamingException ne) {
>           throw new CreateException("Failed to find environment value "+ne);
>         }
>       }

>       /**
>        * Buys shares of a stock for a named customer.
>        *
>        * @param customerName      String Customer name
>        * @param stockSymbol       String Stock symbol
>        * @param shares            int Number of shares to buy
>        * @return                  TradeResult Trade Result
>        *                          if there is an error while buying the shares
>        */
>       public TradeResult buy(String stockSymbol, int shares) {
>         if (shares > tradeLimit) {
>           log("Attempt to buy "+shares+" is greater than limit of "+tradeLimit);
>           shares = tradeLimit;
>         }
>         log("Buying "+shares+" shares of "+stockSymbol);
>         return new TradeResult(shares, stockSymbol);
>       }

>       /**
>        * Sells shares of a stock for a named customer.
>        *
>        * @param customerName      String Customer name
>        * @param stockSymbol       String Stock symbol
>        * @param shares            int Number of shares to buy
>        * @return                  TradeResult Trade Result
>        *                          if there is an error while selling the shares
>        */
>       public TradeResult sell(String stockSymbol, int shares) {
>         if (shares > tradeLimit) {
>           log("Attempt to sell "+shares+" is greater than limit of "+tradeLimit);
>           shares = tradeLimit;
>         }
>         log("Selling "+shares+" shares of "+stockSymbol);
>         return new TradeResult(shares, stockSymbol);
>       }
>     }

The following Java code is the Home interface of the Trader EJB:

>     package examples.webservices.complex.statelessSession;

>     import java.rmi.RemoteException;
>     import javax.ejb.CreateException;
>     import javax.ejb.EJBHome;

>     /**
>      * This interface is the home interface for the TraderBean.java,
>      * which in WebLogic is implemented by the code-generated container
>      * class TraderBeanC. A home interface may support one or more create
>      * methods, which must correspond to methods named "ejbCreate" in the EJBean.
>      *
>      * @author Copyright (c) 1998-2002 by BEA Systems, Inc. All Rights Reserved.
>      */
>     public interface TraderHome extends EJBHome {
>       /**
>        * This method corresponds to the ejbCreate method in the bean
>        * "TraderBean.java".
>        * The parameter sets of the two methods are identical. When the client calls
>        * <code>TraderHome.create()</code>, the container
>        * allocates an instance of the EJBean and calls <code>ejbCreate()</code>.
>        *
>        * @return                  Trader
>        * @exception               RemoteException if there is
>        *                          a communications or systems failure
>        * @exception               CreateException
>        *                          if there is a problem creating the bean
>        * @see                     examples.ejb11.basic.statelessSession.TraderBean
>        */
>       Trader create() throws CreateException, RemoteException;
>     }

Writing the Java Code for the Non-Built-In Data Type

The two methods of the EJB return a non-built-in data type called TraderResult. The following Java code describes this type:

>     package examples.webservices.complex.statelessSession;

>     import java.io.Serializable;

>     /**
>      * This class reflects the results of a buy/sell transaction.
>      *
>      * @author Copyright (c) 1999-2002 by BEA Systems, Inc. All Rights Reserved.
>      */
>     public final class TradeResult implements Serializable {

>       // Number of shares really bought or sold.
>       private int    numberTraded;

>       private String stockSymbol;

>       public TradeResult() {}

>       public TradeResult(int nt, String ss) {
>         numberTraded = nt;
>         stockSymbol  = ss;
>       }

>       public int getNumberTraded() { return numberTraded; }

>       public void setNumberTraded(int numberTraded) {
>             this.numberTraded = numberTraded;
>       }

>       public String getStockSymbol() { return stockSymbol; }

>       public void setStockSymbol(String stockSymbol) {
>             this.stockSymbol = stockSymbol;
>       }
>     }

Creating EJB Deployment Descriptors

See Editing XML Files for information on using the BEA XML Editor to create and edit the ejb-jar.xml and weblogic-ejb-jar.xml files.

The following example shows the ejb-jar.xml deployment descriptor that describes the Trader EJB:

>     <?xml version="1.0"?>

>     <!DOCTYPE ejb-jar PUBLIC
>     '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN'
>     'http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd'>

>     <ejb-jar>
>       <enterprise-beans>
>         <session>
>           <ejb-name>TraderService</ejb-name>
>           <home>examples.webservices.complex.statelessSession.TraderHome</home>
>           <remote>examples.webservices.complex.statelessSession.Trader</remote>
>           <ejb-class>examples.webservices.complex.statelessSession.TraderBean</ejb-class>
>           <session-type>Stateless</session-type>
>           <transaction-type>Container</transaction-type>
>           <env-entry>
>             <env-entry-name>WEBL</env-entry-name>
>             <env-entry-type>java.lang.Double </env-entry-type>
>             <env-entry-value>10.0</env-entry-value>
>           </env-entry>
>           <env-entry>
>             <env-entry-name>INTL</env-entry-name>
>             <env-entry-type>java.lang.Double </env-entry-type>
>             <env-entry-value>15.0</env-entry-value>
>           </env-entry>
>           <env-entry>
>             <env-entry-name>tradeLimit</env-entry-name>
>             <env-entry-type>java.lang.Integer </env-entry-type>
>             <env-entry-value>500</env-entry-value>
>           </env-entry>
>         </session>
>       </enterprise-beans>
>       <assembly-descriptor>
>         <container-transaction>
>           <method>
>             <ejb-name>TraderService</ejb-name>
>             <method-name>*</method-name>
>           </method>
>           <trans-attribute>Required</trans-attribute>
>         </container-transaction>
>       </assembly-descriptor>
>     </ejb-jar>

The following example shows the weblogic-ejb-jar.xml deployment descriptor that describes the Trader EJB:

>     <?xml version="1.0"?>

>     <!DOCTYPE weblogic-ejb-jar PUBLIC
>     '-//BEA Systems, Inc.//DTD WebLogic 7.0.0 EJB//EN'
>     'http://www.bea.com/servers/wls700/dtd/weblogic700-ejb-jar.dtd'>

>     <weblogic-ejb-jar>
>       <weblogic-enterprise-bean>
>         <ejb-name>TraderService</ejb-name>
>         <jndi-name>webservices-complex-statelessession</jndi-name>
>       </weblogic-enterprise-bean>
>     </weblogic-ejb-jar>

Assembling the EJB

To assemble the EJB class files and deployment descriptors into a trader.jar archive file, follow these steps:

1. Create a temporary staging directory.

2. Copy the compiled Java EJB class files into the staging directory.

3. Create a META-INF subdirectory in the staging directory.

4. Copy the ejb-jar.xml and weblogic-ejb-jar.xml deployment descriptors into the META-INF subdirectory.

5. Create the pre_trader.jar archive file using the jar utility:

   >     jar cvf pre_trader.jar -C staging_dir .

6. Run the weblogic.ejbc utility to generate and compile EJB 2.0 and 1.1 container classes and create the final trader.jar file:

   >     java weblogic.ejbc pre_trader.jar trader.jar

Creating the build.xml Ant Build File

The Ant build file, build.xml, contains a call to the servicegen Ant task that introspects the trader.jar EJB file, generates all data type components (such as the serialization class), creates the web-services.xml deployment descriptor file, and packages it all up into a deployable trader.ear file.

The following build.xml file contains instructions that will build the EAR file into a temporary build_dir directory :

>     <project name="webServicesExample" default="build">
>       <target name="build" >
>         <delete dir="build_dir" />
>         <mkdir dir="build_dir" />
>         <copy todir="build_dir" file="trader.jar"/>
>         <servicegen
>           destEar="build_dir/trader.ear"
>           warName="trader.war"
>           contextURI="webservice">
>           <service
>              ejbJar="build_dir/trader.jar"
>              targetNamespace="http://www.bea.com/examples/Trader"
>              serviceName="TraderService"
>              serviceURI="/TraderService"
>              generateTypes="True"
>              expandMethods="True" >
>           </service>
>         </servicegen>
>       </target>
>     </project>