Skip Headers
Oracle® Application Server Web Services Developer's Guide
10g Release 3 (10.1.3)
B14434-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

6 Assembling a Web Service with Java Classes

This chapter describes how to assemble stateless and stateful Web services based on Java classes. The Web service assembly is performed bottom up by WebServicesAssembler.

A stateless Web service does not carry any local state across calls. In contrast, a stateful Web service may carry state across calls, and the results of method invocations depend on the scope. The stateful Web services supported by Oracle Application Server Web Services is HTTP-based. It works only for SOAP/HTTP endpoints and not for SOAP/JMS endpoints.

Stateless Web services interoperate with .NET or any vendor's Web services. Stateful OracleAS Web Services based on Java classes contain Oracle-proprietary extensions and may not operate with other services unless the service provider makes available scopes with the same semantics.

This chapter has the following sections:

Exposing Java Classes as a Stateless Web Service

You can use WebServicesAssembler to assemble Web services from Java classes that conform to the JAX-RPC 1.1 specification. Exposing Java classes as a Web service is convenient if you want a lightweight system and do not need the transactional capabilities that an EJB container offers.

WebServicesAssembler assembles the service bottom up. It starts with the Java classes you want to expose as a Web service and generates a deployable EAR file containing the WSDL, the mapping files, the implementation files, and the deployment descriptors.

JAX-RPC requires you to provide a Java class that contains the methods you want to expose as a service and its interface. For more information on the requirements on the class and interface, see "Writing Java Class-Based Web Services".

A Web service based on Java classes can be invoked by a client written in Java, .NET, or any other programming language. The client can be based on static stub or Dynamic Invocation Interface (DII).

Prerequisites

Before you begin, provide the following files and information.

How to Assemble a Stateless Web Service

The following steps describe how to use WebServicesAssembler to expose a stateless Web service from a Java class:

  1. Provide the compiled Java class that you want to expose as a Web service and its compiled interface.

    This example uses the HelloInterface interface and the HelloImpl class. You can find code listings of these files in "Defining a Java Interface" and "Defining a Java Class".

  2. Generate the service artifacts by running the WebServicesAssembler with the assemble command. This example assumes that the interface and implementation classes are compiled to the ./build/classes/service directory.

    java -jar wsa.jar -assemble
        -appName hello
        -serviceName HelloService
        -interfaceName oracle.demo.hello.HelloInterface
        -className oracle.demo.hello.HelloImpl
        -input ./build/classes/service
        -output build
        -ear dist/hello.ear
        -uri HelloService
        -targetNamespace http://hello.demo.oracle
    
    

    The output of this command is an EAR file that contains the contents of a WAR file that can be deployed to an OC4J instance. The dist directory contains the J2EE Web services-compliant application EAR file, hello.ear. For more information on the required and optional arguments to assemble, see "assemble".

  3. Deploy the service and bind the application.

    Deploy EAR files in the standard manner into a running instance of OC4J. For more information on deploying EAR files, see the Oracle Containers for J2EE Deployment Guide. The following is a sample deployment command:

    java -jar <OC4J_HOME>/j2ee/home/admin_client.jar deployer:oc4j:localhost:port <user> <password> 
                -deploy 
                -file dist/hello.ear 
                -deploymentName hello 
                -bindWebApp default-web-site
    
    

    The following list describes the variables used in this code example.

    • <OC4J_Home>—The directory containing the OC4J installation.

    • <user>—The user name for the OC4J instance. The user name is assigned at installation time

    • <password>—The password for the OC4J instance. The password is assigned at installation time

    • default-web-site—The Web site to which the application will be bound. This is usually default-web-site. To configure Web sites, see the server.xml file in <OC4J_HOME>/j2ee/home/config.

  4. (Optional) Check that deployment succeeded. OracleAS Web Services provides a Web Service Home Page for each deployed Web service. See "Using the Web Services Home Page" for information on accessing and using the Web service home page.

  5. Generate the client-side code:

    • For the J2SE environment, generate stubs (client proxies) for a J2SE Web service client by running the WebServicesAssembler tool with the genProxy command. For more information on generating and assembling client-side code for the J2SE environment, see Chapter 14, "Assembling a J2SE Web Service Client".

    • For the J2EE environment, generate a Service Endpoint Interface and a mapping file for a J2EE Web service client by running the WebServicesAssembler tool with the genInterface command. For more information on generating and assembling client-side code, see Chapter 13, "Assembling a J2EE Web Service Client".

    For example, the following command generates stubs that can be used for a J2SE client:

    java -jar wsa.jar -genProxy 
                      -output build/src/client/ 
                      -wsdl http://localhost:8888/hello/HelloService?WSDL 
                      -packageName oracle.demo.hello
    
    

    This command generates the client proxies and stores them in the directory build/src/client. The client application uses the stub to invoke operations on a remote service. For more information on the required and optional arguments to genProxy, see "genProxy".

  6. Write the client application.

  7. Compile and run the client.

    List the appropriate JARs on the classpath before compiling the client. Table A-2, "Classpath Components for a Client Using a Client-Side Proxy" lists all of the JAR files that can possibly be used on the client classpath. As an alternative to listing individual JARs, you can include the client-side JAR, wsclient_extended.jar on the client classpath. This JAR file contains all the classes necessary to compile and run a Web service client. The classes are from the individual JAR files listed in Table A-2. See "Setting the Web Service Proxy Client Classpath" for more information on wsclient_extended.jar and the client classpath.

Ant Tasks for Generating a Stateless Web Service

The current release provides Ant tasks for Web services development. The following code samples show how the WebServicesAssembler commands in the preceding examples can be rewritten as Ant tasks.

For more information on Ant tasks for WebServicesAssembler commands, see Chapter 17, "Using WebServicesAssembler".

For the assemble command, here is an example Ant task. In this example, build/classes/client is the directory where client classes (stubs) will be generated.

<oracle:assemble appName="hello"
        serviceName="HelloService"
        input="./build/classes/service"
        output="build"
        ear="dist/hello.ear"
        targetNamespace="http://hello.demo.oracle"
        >
            <oracle:porttype
                interfaceName="oracle.demo.hello.HelloInterface"
                className="oracle.demo.hello.HelloImpl">
                <oracle:port uri="HelloService" />
            </oracle:porttype>
            <oracle:classpath>
                <pathelement location="build/classes/client"/>
            </oracle:classpath>
</oracle:assemble>

For the genProxy command, here is a sample Ant task. The client proxies will be stored in the directory build/src/client.

<oracle:genProxy  wsdl="http://localhost:8888/hello/HelloService?WSDL"
           output="build/src/client"
           packageName="oracle.demo.hello"
/>

Writing Java Class-Based Web Services

To use JAX-RPC to create a Web service with Java files, you must provide a public interface that defines the remote methods that you want to expose as a service. The interface definition must also extend java.rmi.Remote, and its methods must throw a java.rmi.RemoteException object. The interface must also reside in a package.

You can also use the public interface to list the signatures for the public methods, or public methods with supported data types, that you want to make available to the Web service. That is, you can employ the interface to filter the methods that you want to expose.

The implementation of the interface must satisfy other requirements:

For a description of all of the requirements on the interface, see the Enterprise Web Services 1.1 specification at the following Web address: http://www.jcp.org/aboutJava/communityprocess/final/jsr109/index.html

When a Web service client makes a service request, OC4J runs the corresponding method in that class. There are very few restrictions on what actions the Web service can perform. At a minimum, the Web services generate some data that is sent to the client or perform an action specified by a Web service request.

The following sections illustrate how to write stateless Web services based on Java classes. For information on writing stateful Web services based on Java classes, see "Exposing Java Classes as a Stateful Web Service".

Writing Stateless Web Services

OracleAS Web Services supports stateless implementations for Java classes running as Web services. For a stateless Java implementation, OracleAS Web Services creates multiple instances of the Java class in a pool; any one of the instances can be used to service a request. After servicing the request, the object is returned to the pool for use by a subsequent request.

Developing a stateless Java Web service consists of the following steps:

Defining a Java Interface

Example 6-1 displays the HelloInterface.java interface for the stateless Web service. To comply with the JAX-RPC 1.1 specification, the interface must reside in a package. It must also extend java.rmi.Remote, and its methods must throw a java.rmi.RemoteException object.

Example 6-1 Defining an Interface for a Stateless Web Service

package oracle.demo.hello; 
 
import java.rmi.RemoteException;
import java.rmi.Remote;
 
public interface HelloInterface extends Remote {
    public String sayHello(String name) throws RemoteException;
}

Defining a Java Class

Create a Java class by implementing the methods in the interface that you want to expose as a Web service. A Java class for a Web service usually defines one or more public methods. To comply with the JAX-RPC 1.1 specification, the implementation class must reside in a package. It must also import java.rmi.Remote and java.rmi.RemoteException.

Example 6-2 displays the public class, HelloImpl. This class defines a public method, sayHello, that returns the string "Hello name!" where name is an input value.

Example 6-2 Defining a Public Class for a Stateless Web Service

package oracle.demo.hello;

import java.rmi.RemoteException;
import java.rmi.Remote;

public class HelloImpl {
     public HelloImpl() {
   }
   public String sayHello(String name) {
     return ("Hello " + name + "!");
   }
} 

Notice that Java class Web service implementations must include a public constructor that takes no arguments.

When an error occurs while running a method on the Java class, it throws a RemoteException. In response to the exception, OracleAS Web Services returns a Web service (SOAP) fault. Use standard J2EE and OC4J administration facilities to view errors for a Web service that uses Java classes for its implementation.

When you create a Java class containing methods that implement a Web service, the methods, parameters, and return values must use supported types or nonstandard types supported by OracleAS Web Services. For a list of the supported data types, see the JAX-RPC 1.1 specification available from the following Web site:

http://java.sun.com/webservices/jaxrpc/index.jsp

"Mapping Java Types to XML and WSDL Types" in the Oracle Application Server Advanced Web Services Developer's Guide and Table 4-1 provides lists of supported data types and supported nonstandard types.

If methods, parameters, and return values use unsupported types, then you must handle them in either of the following ways.

  • Use the interface class to limit the exposed methods to only those using JAX-RPC supported types and the supported non-standard types.

  • Use the custom serializer to map unsupported types. For more information on working with unsupported types, see "Custom Serialization of Java Value Types" in the Oracle Application Server Advanced Web Services Developer's Guide.

Exposing Java Classes as a Stateful Web Service

OC4J supports stateful Web services based on Java classes. The Java object that implements the service persists for the duration of the HTTP session. To maintain state, these services contain Oracle-proprietary extensions. Because of these extensions, you should not consider stateful OracleAS Web Services to be interoperable unless the service provider makes available scopes with the same semantics.

The stateful Web services supported by OracleAS Web Services is HTTP-based. It works only for SOAP/HTTP endpoints and does not work for SOAP/JMS endpoints.

Prerequisites

The prerequisites for generating a stateful Web service from Java classes are identical to those described for a stateless Web service. For a description of the information and files you must provide, see "Prerequisites".

How to Assemble a Stateful Web Service

The following instructions describe how to use WebServicesAssembler to create a stateful Web service from a Java class. The Java object that implements the service persists for the duration of the HTTP session.

  1. Provide the Java class that you want to expose as a Web service and its interface.

  2. Generate the service artifacts by running the WebServicesAssembler with the assemble command. For example:

    java -jar wsa.jar -assemble
        -appName counter
        -serviceName counterService
        -interfaceName oracle.demo.count.CounterInterface
        -className oracle.demo.count.CounterImpl
        -input build/classes/service
        -output build
        -ear dist/counter.ear
        -recoverable true
        -timeout 30
        -uri counterService
    
    

    Note the timeout argument on the command line. In addition to indicating the number of seconds an HTTP session should last before it times out, it also implicitly sets the session argument to true. When session is true, the service instance is stored in an HTTP session. The recoverable argument indicates that this stateful application is distributable. For more information on the required and optional arguments to assemble, see "assemble".

    This command generates all the files required to create a deployable archive. The output build directory contains separate directories for the EAR file and the Java classes. The dist directory contains the J2EE Web services-compliant application EAR file, counter.ear.

  3. Deploy the service and bind the application.

    Deploy the EAR file in the standard manner into a running instance of OC4J. For more information on deploying EAR files, see the Oracle Containers for J2EE Deployment Guide. The following is a sample deployment command.

    java -jar <OC4J_HOME>/j2ee/home/admin_client.jar deployer:oc4j:localhost:port <user> <password>
               -deploy 
               -file dist/counter.ear 
               -deploymentName counter 
               -bindWebApp default-web-site
    
    

    The following list describes the parameters used in this code example.

    • <OC4J_HOME>—The directory containing the OC4J installation.

    • <user>—the user name for the OC4J instance. The user name is assigned at installation time.

    • <password>—the password for the OC4J instance. The password is assigned at installation time.

    • default-web-site— the Web site to which the application will be bound. This is usually default-web-site. To configure Web sites, see the server.xml file in <OC4J_HOME>/j2ee/home/config.

  4. (Optional) Check that deployment succeeded. OracleAS Web Services provides a Web Service Home Page for each deployed Web service. See "Using the Web Services Home Page" for information on accessing and using the Web service home page.

  5. Generate the client code:

    • For the J2SE environment, generate stubs (client proxies) for a J2SE Web service client by running the WebServicesAssembler tool with the genProxy command. For more information on generating and assembling client-side code for the J2SE environment, see Chapter 14, "Assembling a J2SE Web Service Client".

    • For the J2EE environment, generate a Service Endpoint Interface and a mapping file for a J2EE Web service client by running the WebServicesAssembler tool with the genInterface command. For more information on generating and assembling client-side code, see Chapter 13, "Assembling a J2EE Web Service Client".

    For example, the following command generates client proxies (stubs) that can be used for a J2SE client:

    java -jar wsa.jar -genProxy 
                      -output build/src/client/ 
                      -wsdl http://localhost:8888/counter/counterService?WSDL 
                      -packageName oracle.demo.count
    
    

    This command generates the client proxies and stores them in the directory build/src/client. The client application uses the stub to invoke operations on a remote service. For more information on the required and optional arguments to genProxy, see "genProxy".


    Note:

    On systems such as Unix or Linux, the URL might need to be quoted (" ") on the command line.

  6. Write the client application.

    Ensure that the client participates in the session by setting the SESSION_MAINTAIN_PROPERTY runtime property (javax.xml.rpc.session.maintain) to true either on the stub, the DII call, or the endpoint client instance.

    Instead of setting this property directly, OracleAS Web Services provides a helpful wrapper class with a setMaintainSession(boolean) method. Set this method to true to maintain sessions. The wrapper takes care of setting the property inside of the client. For example, in the client code, enter:

    CounterServicePortClient c = new CounterServicePortClient(); 
    //sets Maintain Session to true, as the endpoint is stateful.c.setMaintainSession(true); 
    
    
  7. Compile and run the client.

    List the appropriate JARs on the classpath before compiling the client. Table A-2, "Classpath Components for a Client Using a Client-Side Proxy" lists all of the JAR files that can possibly be used on the client classpath. As an alternative to listing individual JARs, you can include the client-side JAR, wsclient_extended.jar on the client classpath. This JAR file contains all the classes necessary to compile and run a Web service client. The classes are from the individual JAR files listed in Table A-2. See "Setting the Web Service Proxy Client Classpath" for more information on wsclient_extended.jar and the client classpath.

Ant Tasks for Generating a Stateful Web Service

The current release provides Ant tasks for Web service development. The following code samples show how the WebServicesAssembler commands in the preceding examples can be rewritten as Ant tasks.

For the assemble command, here is an example Ant task. In this example, ${wsdemo.common.class.path} represents the classpath.

<oracle:assemble appName="counter"
            serviceName="counterService"
            input="build/classes/service"
            output="build"
            ear="dist/service.ear"
            recoverable="true"
            timeout="30        "
        >
        <oracle:porttype
            interfaceName="oracle.demo.count.CounterInterface"
            className="oracle.demo.count.CounterImpl">
            <oracle:port uri="counterService" />
        </oracle:porttype>
        <oracle:classpath>
            <pathelement path="${wsdemo.common.class.path}"/>
            <pathelement location="build/classes/client"/>
        </oracle:classpath>
    </oracle:assemble>

For the genProxy command, here is an example Ant task.

<oracle:genProxy wsdl="http://stadp54.us.oracle.com:8888/counter/counter?WSDL"
    output="build/src/client"
    packageName="oracle.demo.count"/>

Writing Stateful Web Services

Java implementations for a stateful Web service must meet the same requirements as implementations for a stateless service. "Writing Java Class-Based Web Services", describes these requirements.

In addition, OC4J supports the call, session, and endpoint scope for a stateful Java implementation:

  • call—The class instance is created for each call. The instance is garbage collected after each call. The value of the callScope argument determines whether the class instance is created for each call.

  • session—The class instance is stored in an HTTP session. This applies only for HTTP transport. Session timeout can be tuned by the timeout argument. The value of the session argument determines whether the class instance is stored in an HTTP session.

  • endpoint—The service endpoint implementation class instance is a singleton instance for each endpoint. This is the default scope.

Developing a stateful Java Web service consists of the following steps:

Defining a Java Interface

Example 6-3 displays the CountInterface.java interface for the stateful Web service. This example also shows that the service class does not have to implement the Service Endpoint Interface directly. To comply with the JAX-RPC 1.1 specification, the interface must reside in a package. It must also extend java.rmi.Remote and its methods must throw a java.rmi.RemoteException object.

Example 6-3 Defining an Interface for a Stateful Web Service

package oracle.demo.count; 
 
import java.rmi.RemoteException;
import java.rmi.Remote;

public interface CounterInterface extends Remote {
    // gets the current counter value
    public int getCurrentCounter() throws RemoteException;
}

Defining a Java Class

Create a Java class by implementing the methods in the interface that you want to expose as a Web service. A Java class for a Web service usually defines one or more public methods. To comply with the JAX-RPC 1.1 specification, the implementation class must reside in a package. It must also import java.rmi.Remote and java.rmi.RemoteException.

Example 6-4 displays the public class, CounterImpl. The class initializes the count and defines the public method, getCurrentCounter.

Example 6-4 Defining a Public Class for a Stateful Web Service

package oracle.demo.count; 

import java.rmi.RemoteException;
import java.rmi.Remote;

public class CounterImpl implements java.io.Serializable {
    private int counter = 0; 

    public CounterImpl() {
    }

  public int getCurrentCounter() {
      System.out.println("Current counter value is: " + (++counter));
      return (counter);
   }
}  

Packaging and Deploying Web Services

The packaging of Web services that expose Java classes is described in "Packaging for a Web Service Based on Java Classes".

For a detailed description of Web module deployment, see the Oracle Containers for J2EE Deployment Guide.

Tool Support for Exposing Java Classes as Web Services

With Oracle JDeveloper, you can create, modify, and deploy J2EE-compliant Java class files as Web services. When you create Java classes in JDeveloper, you use the modeling tools and wizards. The wizards can perform the following tasks.

For more information on using JDeveloper to create Java classes and expose them as Web services, see the JDeveloper on-line help.

Limitations

See "Assembling Web Services from Java Classes".

Additional Information

For more information on: