Skip Headers
Oracle® Application Server Web Services Developer's Guide
10g (10.1.3.5.0)

Part Number E13982-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

7 Assembling a Web Service with Java Classes

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

A stateless Web service does not carry any local state across calls. Stateless Web services interoperate with .NET or any vendor's Web services. The service can use either HTTP or JMS as the transport mechanism.

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

Requirements for Writing Java Classes for 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:

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.

Note:

OracleAS Web Services may be able to expose a Java class directly as a Web service even if you do not provide a service interface and if your class does not meet some of the conditions for a compliant class. To expose a Java class as a Web service in this case, you must use J2SE 5.0 Annotations such as @WebService. For more information, see Chapter 11, "Assembling Web Services with Annotations".

Also note that a Web service assembled under these conditions will not be conformant or portable as defined by the JAX-RPC specification.

See Also:

"How to Write Java Implementations for Stateless Web Services" for information on writing Java classes for stateless Web services and "How to Write Java Implementations for Stateful Web Services" for information on writing Java classes for stateful Web services.

Java Classes and Stateless Web Services

This section has the following subsections:

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 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.

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

See Also:

"Requirements for Writing Java Classes for Web Services" for more information on the requirements on the class and interface.

How to Assemble A Stateless Web Service with Java Classes

This section contains the following subsections:

Prerequisites

Before you begin, provide the following files and information.

  • Supply a compiled Java class and interface that contains the methods that you want to expose as a service. The class and its interface must conform to the JAX-RPC standards for a Web service.

    See "How to Write Java Implementations for Stateless Web Services" if you are exposing Java classes as a stateless Web service. See "Exposing Java Classes as a Stateful Web Service" if you are exposing Java classes as a stateful Web service.

  • Decide whether you want WebServicesAssembler to only generate the service files or if you want it to package the files into a deployable archive. The ear argument packages the files into an archive. If you do not specify ear, then the files are stored in the directory specified by the output argument.

    See "ear", "output", and "war" for more information on these arguments.

  • If your Java classes need to work with any additional message processing components, for example to provide reliability and security features, you can specify message handlers.

    See Chapter 17, "Processing SOAP Headers" and "How to Configure Handlers in an Ant Task" for more information on these topics.

  • If the methods in the Java class use nonstandard data types, you must specify a custom serializer to process them.

    If you are working with non-supported data types, see "Mapping Java Types to XML and WSDL Types" in the Oracle Application Server Advanced Web Services Developer's Guide and Table 5-1, "Java Types Supported by RPC-Encoded Proprietary Message Format".

    For information on custom serialization, see "Custom Serialization of Java Value Types" in the Oracle Application Server Advanced Web Services Developer's Guide.

    For a list of supported data types, see the JAX-RPC 1.1 specification available from the following Web site:

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

Steps for Assembling a Stateless Web Service with Java Classes

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 "Steps for Assembling a Stateless Web Service with Java Classes".

  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.

    Command line:

    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
        -classpath ./build/classes/service
    

    Ant task:

    <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/service"/>
                </oracle:classpath>
    </oracle:assemble>
    

    In this command and Ant task:

    • assemble—Generates a Web service from Java files bottom up. The command creates all of the files required to create a deployable archive. See "assemble".

    • appName—Specifies the name of an application. Usually, this name is used as a base value for other arguments like context and uri. See "appName".

    • serviceName—Specifies the service name. See "serviceName".

    • interfaceName—Specifies the name of a Java class (including the package name) that contains the service endpoint interface (SEI). See "interfaceName".

    • className—Specifies the name of the class (including the package name) that is the implementation class for the Web service. See "className".

    • input—Specifies the directory or JAR containing the classes that should be copied to WEB-INF/classes. This argument will be added to the classpath used by the WebServicesAssembler. See "input".

    • output—Specifies the directory where generated files will be stored. If the directory does not exist, it will be created. See "output".

    • ear—Specifies the name and location of the generated EAR. See "ear".

    • uri—Specifies the URI to use for the Web service. See "uri".

    • targetNamespace—Specifies the target namespace to be used in the generated WSDL. The value can be either a conforming HTTP URL, a non-conforming HTTP URL, or even a URI. See "targetNamespace".

    • classpath—Specifies the classpath that contains any user-created classes given to WebServicesAssembler. One reason to specify this argument is if you have already created some value type classes or exceptions and you do not want WebServicesAssembler to overwrite them. See "classpath".

    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 Test Page for each deployed Web service. See "How to Use the Web Services Test Page" for information on accessing and using the Web Service Test 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 15, "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 14, "Assembling a J2EE Web Service Client".

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

    Command line:

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

    Ant task:

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

    In this command line and Ant task:

    • genProxy—Creates a static proxy stub that can be used by a J2SE Web service client. See "genProxy".

    • output—Specifies the directory where generated files will be stored. If the directory does not exist, it will be created. See "output".

    • wsdl—Specifies the absolute file path, relative file path, or URL to a WSDL document. See "wsdl".

    • packageName—Specifies the package name that will be used for generated classes if no package name is declared in the JAX-RPC mapping file. See "packageName".

    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 Classpath for a Web Service Proxy" for more information on wsclient_extended.jar and the client classpath.

How to Write Java Implementations for 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.

You can assemble Java classes for stateless Web services only for SOAP/HTTP endpoints and not for SOAP/JMS endpoints.

To develop a stateless Java Web service, define the Java interface and its implementation. This is described in the following sections:

Note:

OracleAS Web Services may be able to expose a Java class directly as a Web service even if you do not provide a service interface and if your class does not meet some of the conditions for a compliant class. To expose a Java class as a Web service in this case, you must use J2SE 5.0 Annotations such as @WebService. For more information, see Chapter 11, "Assembling Web Services with Annotations".

Also note that a Web service assembled under these conditions will not be conformant or portable as per the JAX-RPC specification.

How to Define a Java Interface

Example 7-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 7-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;
}

How to Define 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 7-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 7-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

See Also:

"Mapping Java Types to XML and WSDL Types" in the Oracle Application Server Advanced Web Services Developer's Guide and Table 5-1 for 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.

    See Also:

    "Custom Serialization of Java Value Types" in the Oracle Application Server Advanced Web Services Developer's Guide for more information on working with unsupported types.

Java Classes and Stateful Web Services

This section has the following subsections:

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 session-based.

How to Assemble a Stateful Web Service

This section contains the following subsections:

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".

Steps for Assembling 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 more information on the required and optional arguments to assemble, see "assemble".

    For example:

    Command line:

    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
    

    Ant task:

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

    In this command and Ant task:

    • assemble—Generates a Web service from Java files bottom up. The command creates all of the files required to create a deployable archive. See "assemble".

    • appName—Specifies the name of an application. Usually, this name is used as a base value for other arguments like context and uri. See "appName".

    • serviceName—Specifies the service name. See "serviceName".

    • interfaceName—Specifies the name of a Java class (including the package name) that contains the service endpoint interface (SEI). See "interfaceName".

    • className—Specifies the name of the class (including the package name) that is the implementation class for the Web service. See "className".

    • input—Specifies the directory or JAR containing the classes that should be copied to WEB-INF/classes. This argument will be added to the classpath used by the WebServicesAssembler. See "input".

    • output—Specifies the directory where generated files will be stored. If the directory does not exist, it will be created. See "output".

    • ear—Specifies the name and location of the generated EAR. See "ear" .

    • recoverable—Indicates whether applications with session state are recoverable. This argument can be used only when the service is exposed as a stateful Web service with session scope. See "recoverable".

    • timeout—Specifies the number of seconds a session should last before it times out. See "timeout".

    • uri—Specifies the URI to use for the Web service. See "uri".

    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.

    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 needs to be distributable. Recoverable means that you want the service to be able to recover in a distributed environment if the node that you are interacting with goes down. This means that the Web service state must be also be distributable.

  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 Test Page for each deployed Web service. See "How to Use the Web Services Test Page" for information on accessing and using the Web Service Test Page.

  5. Generate the client code:

    • For the J2SE environment, generate stubs (client proxies) 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 15, "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 14, "Assembling a J2EE Web Service Client".

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

    Command line:

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

    Ant task:

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

    In this command and Ant task:

    • genProxy—Creates a static proxy stub that can be used by a J2SE Web service client. See "genProxy".

    • output—Specifies the directory where generated files will be stored. If the directory does not exist, it will be created. See "output".

    • wsdl—Specifies the absolute file path, relative file path, or URL to a WSDL document. See "wsdl".

    • packageName—Specifies the package name that will be used for generated classes if no package name is declared in the JAX-RPC mapping file. See "packageName".

    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 javax.xml.rpc.Call.SESSION_MAINTAIN_PROPERTY runtime property 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 Classpath for a Web Service Proxy" for more information on wsclient_extended.jar and the client classpath.

How to Write Java Implementations for Stateful Web Services

Java implementations for a stateful Web service must meet the same requirements as implementations for a stateless service.

See Also:

"Requirements for Writing Java Classes for Web Services", for a description of the requirements for a Java implementation.

WebServicesAssembler enables you to define call, session, and endpoint scopes for a stateful Java implementation:

  • call scope—When the WebServicesAssembler callScope argument is set to true, a new class instance is created for each call. The instance is garbage collected after each call. The default value of callScope is false.

  • session scope—When the WebServicesAssembler session argument is set to true, 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 default value for session is false. However, if the timeout argument is set with WebServicesAssembler, then session will automatically be set to true.

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

Developing a stateful Java Web service consists steps described in the following sections:

How to Define a Java Interface

Example 7-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 7-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;
}

How to Define 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 7-4 displays the public class, CounterImpl. The class initializes the count and defines the public method, getCurrentCounter.

Example 7-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".

See Also:

Oracle Containers for J2EE Deployment Guide for a detailed description of Web module deployment.

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 Oracle JDeveloper, you use modeling tools and wizards. The wizards can perform the following tasks.

See Also:

Oracle JDeveloper on-line help for more information on using Oracle JDeveloper to create Java classes and expose them as Web services.

Limitations

See "Assembling Web Services from Java Classes".

Additional Information

For more information on: