Skip Headers

Oracle® Application Server Advanced Web Services Developer's Guide 10g Release 3 (10.1.3) B25603-01 |
| Home | Solution Area | Contents | Index

Previous | Next |

# 10 Using Web Service Providers

This chapter describes how to use the Provider API in Oracle Application Server Web Services. The Provider API lets you define custom processing logic for a Web services endpoint that is not tied to any particular service endpoint implementation strategy, such as JAX-RPC. The Provider model can be used to provide common functionality to a number of endpoints. Rather than incorporating the same functions into many Web services, the Provider model enables you to add the logic into the runtime directly.

## What is a Provider?

A Provider lets you bypass the JAX-RPC tie-based framework and allows you the flexibility of choosing your own mechanism for traversing and interpreting the message payload. Since it runs in the OC4J container, a Provider can take advantage of the container's services such as schema validation, security, and reliability.

When to Use a Provider

You can choose to employ a Provider as your endpoint implementation if you find that your performance is lacking when leveraging a standard JAX-RPC endpoint implementation. Because a Provider does not use the JAX-RPC framework, marshalling and unmarshalling of data is not performed. Therefore, based on your message traversal and interpretation mechanism, there may be less parsing and serialization effort before the message is processed.

Also, because a Provider enables you to process the SOAP message directly, you can perform much more sophisticated processing such as content-based routing. For example, inbound messages could be routed to a number of intermediate destinations (perhaps for some intermediate level of processing) before routing to a final destination.

## Understanding the Provider API

The interfaces and classes in the `oracle.webservices.provider` package allow you to implement and use your own Provider to process SOAP messages.

- Provider Interface—your application must implement this interface to create your Provider.

- ProviderConfig Class—configuration class that is passed to the Provider during its initialization. This represents the information related to the Provider configuration. The Provider also uses this class to interact with the container.

- MessageContext Class—context class that is passed to the Provider's `processMessage` method when an invocation is to be serviced by the Provider. The Provider instance can use this class to obtain transport protocol-related information.

- HTTPConstants Class—provides a set of well-defined properties for the HTTP protocol that the container will set on the `MessageContext`.

### Provider Interface

Your Provider class must implement the `oracle.webservices.provider.Provider` interface. The following sections provide more information on the methods in the `Provider` interface that must be implemented.

- init Method

- processMessage Method

- destroy Method

init Method

    public void init(ProviderConfig config) throws ProviderException;

The `init` method is called when the Provider is loaded and initialized. The method can be called only once during the lifecycle of the Provider. In response to the `init` method, the container passes an instance of `ProviderConfig` to the Provider. This instance provides configuration information related to the Provider. The `ProviderConfig` instance provides mechanisms to set and get properties and the `ServletContext`. The `init` and `destroy` methods provide the lifecycle mechanisms for the Provider much like the `ServiceLifecycle` interface provides the lifecycle mechanisms for JAX-RPC service endpoint implementation (SEI) classes.

The Provider uses the `ProviderConfig` instance to set or retrieve properties. If a property is set on the context, it will overwrite the corresponding static property set in the deployment descriptors. For example, the Provider can set the boolean `VALIDATION_SOAP_SCHEMA` property to `true` to let the container perform schema validation. Schema validation can be performed only if the WSDL is available; it cannot be performed in pass-through mode. In passthrough mode, the provider itself is not exposed as an endpoint. The default value of the `VALIDATION_SOAP_SCHEMA` property is `false`. Schema validation is based on the `QName` value of the child element of the SOAP Body.

If the appropriate load-on-startup directive is provided (for example, by using the `web.xml` file in the Provider application WAR file), then the `init` method will be called on application startup.

processMessage Method

    public SOAPMessage processMessage(SOAPMessage request, MessageContext messageContext) throws ProviderException;

The `processMessage` method is the Provider's main access method: it is invoked every time a SOAP request is dispatched to the Provider instance. The `processMessage` method is where you provide the processing logic for the SOAP message. For the SOAP protocol, this method takes a `SOAPMessage` instance as an argument. From this `SOAPMessage` instance, the Provider can obtain access to other parts of the message payload, such as the SOAP body, headers, and attachments.

The `processMessage` method also takes a `MessageContext` object. The message context defines the properties that are valid for the particular message.

This method returns a `SOAPMessage` instance. If the instance is not null, then the Provider intends to return a response to the sender, assuming the underlying transport supports it. If the underlying transport is a one-way protocol, such as JMS, then an attempt to send a response will cause an error to be thrown in the server logs. The return must be null for pure one-way calls and must not be null for request-response calls.

destroy Method

    public void destroy() throws ProviderException;

The container invokes the `destroy` method to notify the Provider instance of its intent to remove the Provider from its working set. After the method is called, the Provider instance is destroyed and garbage collected.

### ProviderConfig Class

This class contains the configuration-related information for the Provider instance. The information includes details that are also listed in the proprietary deployment descriptors.

The properties of the `ProviderConfig` are used to communicate with the container. For example, a policy object reference can be set as a `ProviderConfig` property inside `processMessage` (assuming the Provider implementation maintains a reference to the `ProviderConfig` instance as an attribute initialized during the `init` method invocation) or the `init` method of the Provider instance. The container can read this policy object and apply the appropriate management functions to the Provider instance.

The following section provides more information on methods on the `ProviderConfig` class.

addService and removeService Methods

    public void addService(String pathInfo, URL wsdlURL, QName wsdlPort, QName serviceName, Object policy) throws ProviderException;

    public void removeService(String pathInfo);

The `addService` and `removeService` methods of the ProviderConfig class can be invoked in the Provider's `init` and `processMessage` methods to dynamically add and remove manageable service endpoints, each with a unique URI. Internally, the container maintains a repository of WSDLs and a map of the WSDLs with the URIs of the incoming requests. In addition, these dynamic endpoints can be managed by using the Application Server Control tool, allowing you to apply security, reliability, auditing, and logging. The Provider can make processing decisions for incoming requests based on the URI available from the Provider's `MessageContext`.

These methods allow the Provider instance to dynamically provide or remove services to or from the container. The container can perform a variety of tasks on the services, such as test-page presentation, request message schema validation, and Web service management processing. The service registration process also allows the container to perform Web service management processing for the registered services.

The `addService` and `removeService` methods both take a `pathInfo` parameter. This parameter contains the extra path information associated with the URL sent by the client when it invokes the endpoint. The extra path information follows the servlet path format, however, it precedes the query string and starts with a forward slash (`/`) character. The `pathInfo` parameter can also be set to an empty string.

The `addService` method can also take a `policy` parameter that defines the management features for the dynamic endpoint. The `policy` parameter must be an `org.w3c.dom.Element` that is compliant with the structure listed in Example 10-1. The definition of this element is listed as a type in the `oracle-webservices-10_0.xsd` schema.

Example 10-1 Definition of Provider-Policy-Type

    <xsd:complexType name="provider-policy-type">
       <xsd:all>
          <xsd:element name="runtime" type="serverPortRuntimeType" minOccurs="0"/>
          <xsd:element name="operations" type="serverOperationsType" minOccurs="0"/>
       </xsd:all>
    </xsd:complexType>

Example 10-2 illustrates a structure defined by this type, as it would appear in an `oracle-webservices.xml` deployment descriptor.

Example 10-2 XML Structure of Policy Element

    <policy>
       <runtime enabled="logging,auditing,security,reliability">
          <logging>…</logging>
          <security>…</security>
          <reliability>…</reliability>
       </runtime>
       <operations>
          <operation name="…">
             <runtime>
                <logging>…</logging>
                <auditing>…<auditing>
                <reliability>…</reliability>
             </runtime>
          </operation>
       </operations>
    </policy>

### MessageContext Class

This class contains the definitions of the transport-agnostic message properties. These properties are updated on each call to `processMessage`. A standard set of constants is defined for the HTTP transport. Properties of the same name are available from the `MessageContext` class. The `MessageContext` class also contains the definitions of constants defined for non-HTTP transports.

### HTTPConstants Class

This class provides a set of well-defined properties for the HTTP protocol that the container will set on the `MessageContext`. The Provider instance should ensure that these properties are not overwritten.

### Provider Servlet

The `ProviderServlet` (`oracle.j2ee.ws.server.provider.ProviderServlet`) handles the routing of requests to the Provider instance. Once deployed, a `ProviderServlet` listens to a URL for incoming SOAP over HTTP requests. When the servlet receives a SOAP message, `ProviderServlet` dispatches it to the `processMessage` method of the Provider instance.

If you are hosting the Provider in the servlet container, then specify this servlet in the `<servlet-class>` subelement of `<servlet>` in your Provider application's `web.xml` deployment descriptor. The servlet URL is specified in the `<url-pattern>` element.

Example 10-3 illustrates a fragment of a `web.xml` file. In the file, `ProviderServlet` is specified in the `<servlet-class>` element and the URL to which it listens, `/LoggerService`, is specified in the `<url-pattern>` element. This URL pattern is relative to the Web application's context root.

The `<servlet-name>` element provides the link between this entry and the Provider-specific information in `oracle-webservices.xml` illustrated in Example 10-5.

Example 10-3 web.xml Fragment, with ProviderServlet and the URL to Which it Listens

    ...
    <servlet>
         <servlet-name>LoggerProviderPort</servlet-name>
         <display-name>LoggerProviderPort</display-name>
         <description>JAX-RPC endpoint  Provider Port</description>
         <servlet-class>oracle.j2ee.ws.server.provider.ProviderServlet</servlet-class>
         <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
         <servlet-name>LoggerProviderPort</servlet-name>
         <url-pattern>/LoggerService</url-pattern>
    </servlet-mapping>
    ...

Extending ProviderServlet

You can extend `ProviderServlet` to tailor its functionality to a particular use case. Example 10-4 illustrates how you can extend the servlet's `doGet` method to allow for the retrieval of specific resources based on the HTTP query string. Note that in this case, if the query string is not processed by the extended servlet, the request should be passed to the parent servlet's `doGet` method. Note the call to `super` if the incoming GET request is not processed.

Example 10-4 Extension of a ProviderServlet Method with a Call to super

    public class ExtendedProviderServlet extends ProviderServlet{

        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {

            String queryString = request.getQueryString();

            if ((queryString != null) &&
                    (queryString.equalsIgnoreCase("someotherquery"))) {
                response.setContentType("text/html; charset=UTF-8");
                response.setStatus(HttpServletResponse.SC_OK);
                OutputStream outputStream = response.getOutputStream();
                OutputStreamWriter writer = new OutputStreamWriter(outputStream);
                writer.write( "<HTML><BODY>TEST RESPONSE</BODY></HTML>" );
                writer.close();
            } else {
                super.doGet(request, response);
    ...
    }

You can also extend `ProviderServlet` to use your own test-page generation mechanism instead of using the default test page provided by the servlet.

## Making a Web Service Provider-Aware

For the Web service to recognize a Provider, you must add information about your Provider to the `oracle-webservices.xml` and `web.xml` deployment descriptors. The JDeveloper and Application Server Control tools do not provide support for adding this information; you must edit the files by hand.

- Editing the oracle-webservices.xml Deployment Descriptor

- Editing the web.xml Deployment Descriptor

### Editing the oracle-webservices.xml Deployment Descriptor

To make the Web service Provider-aware, add the `<provider-description>` clause to the `oracle-webservices.xml` deployment descriptor. Example 10-5 illustrates a fragment of an `oracle-webservices.xml` deployment descriptor with this clause. "Provider Elements in oracle-webservices.xml" describes the elements that can appear in the `<provider-description>` clause.

Example 10-5 oracle-webservices.xml Fragment, with a <provider-description> Clause

    <oracle-webservices>
     <provider-description>
      <provider-description-name> some name</provider-description-name>
      <wsdl-file>/file location</wsdl-file>
      <wsdl-service-name xmlns:ns_="urn:oracle-ws">ns_:PhotoService</ wsdl-service-name >
      <provider-port>
                 <provider-name>LoggerProviderPort</provider-name>
                 <wsdl-port xmlns:ns_="urn:oracle-ws">ns_:PhotoIFPort</wsdl-port>
                 <implementation-class>oracle.myprovider.JmsRetriever</ implementation-class >
                <servlet-link>LoggerProviderPort</servlet-link>
                <property name="connection-factory-name">jms/ws/mdb/theQueueConnectionFactory</property>
                <property name="queue-name">jms/ws/mdb/theQueue</property>
                 <policy>
                   <runtime enabled="logging,auditing,security,reliability">
                      <logging>…</logging>
                      <security>…</security>
                      <reliability>…</reliability>
                   </runtime>
                   <operations>
                      <operation name="…">
                         <runtime>
                            <logging>…</logging>
                            <auditing>…<auditing>
                            <reliability>…</reliability>
                         </runtime>
                     </operation>
                   </operations>
                </policy>
      </provider-port>
     </provider-description>
    </oracle-webservices>

#### Provider Elements in oracle-webservices.xml

The top-level Provider element is `<provider-description>`. This element identifies a collection of Provider ports. Table 10-1 describes the subelements of `<provider-description>`.

Table 10-1 Subelements of the <provider-description> Element

Element Name | Description
--- | ---
<provider-description-name> | (optional) A name for the Provider description.
<wsdl-file> | (optional) Specifies the location of an associated WSDL for the Provider.
<wsdl-service-name> | (optional) Associates the WSDL's service name with the name of a Provider. This element should be provided if a WSDL has more than one service. This element is not required if the WSDL has only one service.
<property> | (optional) Specifies globally-defined properties; that is, properties that are available to all of the defined Provider ports. This element recognizes a `name` attribute.
<provider-port> | (required) Associates a WSDL port with a Web service interface and implementation. It defines the name of the port as a component. It also associates the port with a servlet endpoint. If a `wsdl-file` is not present, the `provider-port` defines a pass-through gateway. For information on the subelements of `<provider-port>`, see Table 10-2.

The `<provider-port>` element associates a WSDL port with a Web service interface and implementation. Table 10-2 describes the subelements of `<provider-port>`.

Table 10-2 Subelements of the <provider-port> Element

Element Name | Description
--- | ---
<provider-name> | (required) The name of the Provider. The `<provider-name>` within the `<provider-port>` must be unique within the deployment descriptor.
<wsdl-port> | (optional) Associates the Provider with a particular port of the WSDL defined by the `wsdl-file` element. This element is not required if no WSDL file is defined.
<expose-wsdl> | (optional) Indicates whether the WSDL should be exposed. Default is `true`.
<expose-testpage> | (optional) Indicates whether the test page should be exposed. Default is `true`.
<implementation-class> | (required) Specifies the name of the class implementing the `oracle.webservices.provider.Provider` interface.
<servlet-link> | (required) Associates a `provider-port` value with a servlet endpoint defined in the `/WEB-INF/web.xml` file.
<max-request-size> | (optional) When a positive value is specified, the service will limit the size of requests to that value (in bytes). Any request that exceeds the maximum length will generate an error. Default is `-1`, which indicates no limit.
<property> | (optional) A locally defined property. If a property with a particular name is defined both locally and globally, then the property defined locally overrides the one defined globally.
<policy> | Defines the Web service management policies for the Provider. Table 10-3 describes the subelements of `<policy>`.

The `<policy>` element defines the Web service management policies for the Provider. Example 10-2 illustrates the structure of the element as it would appear in an `oracle-webservices.xml` deployment descriptor. Table 10-3 describes the subelements of the `<policy>` element.

Table 10-3 Subelements of the <policy> Element

Element Name | Description
--- | ---
<operations> | Contains a sequence of elements, one for each operation. The `<operation>` subelement indicates an individual operation. Each of these subelements contain client-side quality of service configuration for a single operation provided by the referenced Web service.
<runtime> | Contains server-side quality of service runtime information (security, reliability, auditing, and logging) applicable to all the operations provided by the referenced Web service. Each child element contains configuration for a specific feature.

For more information on Web service management policies, see the following resources.

- security—Oracle Application Server Web Services Security Guide

- reliability—Chapter 5, "Ensuring Web Service Reliability"

- auditing and logging—Chapter 6, "Auditing and Logging Messages"

### Editing the web.xml Deployment Descriptor

To make the Web service Provider-aware, add the `<servlet-class>` element to the `<servlet>` clause and the `<url-pattern>` element to the `<servlet-mapping>` clause. Example 10-6 illustrates a `web.xml` deployment descriptor with these elements. They are described in Table 10-4.

Example 10-6 Provider Elements in the web.xml Deployment Descriptor

    <web-app><display-name/>
    <description/>
    <servlet>
         <servlet-name>LoggerProviderPort</servlet-name>
         <display-name>LoggerProviderPort</display-name>
         <description>JAX-RPC endpoint  Provider Port</description>
         <servlet-class>oracle.j2ee.ws.server.provider.ProviderServlet</servlet-class>
         <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
         <servlet-name>LoggerProviderPort</servlet-name>
         <url-pattern>/LoggerService</url-pattern>
    </servlet-mapping>
    </web-app>

#### Provider Elements in web.xml

Table 10-4 describes the elements which you must add to `web.xml` to make it Provider-aware.

Table 10-4 Provider Elements in web.xml

Element Name | Description
--- | ---
<servlet-class> | Specifies the name of the Provider servlet. The value can be either `oracle.j2ee.ws.server.provider.ProviderServlet` or a subclass as described in "Extending ProviderServlet".
<url-pattern> | Specifies the URL pattern to use for the Web service. The Provider servlet will listen to URLs whose prefix is specified by this element. The URL pattern should be relative to the Provider servlet context for the Web module. For dynamic pass through mode, the `<url-pattern>` should be "`/*`".

## Registering a Provider-Managed Endpoint

The following sections describe how to register a Provider-managed endpoint for your Web service.

- How to Register a Static Provider-Managed Endpoint

- How to Register a Dynamic Provider-Managed Endpoint

### How to Register a Static Provider-Managed Endpoint

The following steps provide a general outline of how to register a static Provider-managed endpoint for your Web service. Follow the links for more detained information on each step.

1. Your Provider application must implement the `Provider` interface. The `Provider` methods `init`, `processMessage` and `destroy` must be implemented. See "Provider Interface" for more information on this interface and its methods.

2. Edit the `oracle-webservices.xml` and `web.xml` deployment descriptors. See "Making a Web Service Provider-Aware" for more information on editing these descriptors.

3. (optional) Provide a management configuration. The configuration is specified as a `policy` clause in the `oracle-webservices.xml` deployment descriptor. Example 10-2 provides an example of the `policy` clause structure in the deployment descriptor.

4. Package the service. See "Packaging Provider Web Application Provider Classes" for more information on packaging a service which includes Provider classes.

### How to Register a Dynamic Provider-Managed Endpoint

You can register additional Provider-managed endpoints using the `ProviderConfig.addService` method to configure Web service management features for those endpoints. For example, a Business Process Execution Language (BPEL) process manager might choose to register its processes using this mechanism.

Note that the generation, packaging, and deployment of the Provider implementation follows the same procedure outlined for a static Provider-managed endpoint. To register dynamic Provider-managed endpoints, you must perform the following additional step.

- Register the service by invoking the `addService` method on the `providerConfig` reference. The implementation can optionally pass the policy configuration by using the method's policy parameter.

Example 10-7 illustrates how a Provider can dynamically add an endpoint. The `ADD_SERVICE_POLICY` property declares the Web service management features for the dynamically-added endpoint (in this case, security auditing and reliability). The `addService` invocation is made on the `providerConfig` reference (`config`) passed to the `init` method of the Provider. In this case, the `policy` parameter of the `addService` method passes `XMLUtil.elementFromString(ADD_SERVICE_POLICY)`. Note the WSDL is packaged as part of the WAR file and retrieved as a resource using the `servletContext`.

Example 10-7 Dynamically Registering a Provider-Managed Endpoint

    ...
     private static final String ADD_SERVICE_POLICY = "<policy>\n" +
                "                <runtime enabled=\"security,auditing,reliability\">\n" +
                "                   <security>\n" +
                "                        <inbound>\n" +
                "                           <verify-username-token password-type=\"PLAINTEXT\" require-nonce=\"false\" " +
                "                           require-created=\"false\"/>\n" +
                "                        </inbound>\n" +
                "                   </security>\n" +
                "                </runtime>\n" +
                "            </policy>";
    ...
      public void init(ProviderConfig config) throws ProviderException {
    ...
    URL wsdlURL1 = ((ServletContext)config.getContainerContext()).getResource("/WEB-INF/wsdl/HelloService.wsdl");
    ...
            config.addService("/loanservice",wsdlURL1,new QName("http://hello.demo.oracle/","HttpSoap11"),null,
                    XMLUtil.elementFromString( ADD_SERVICE_POLICY ));
    ...
    }

## Packaging Provider Web Application Provider Classes

Provider Web applications are packaged like any standard Web application. If the Provider application has a WSDL file, store it in the `/WEB-INF/wsdl` directory in the WAR file. Store the Provider classes in the `/classes` directory which is a child of `/WEB-INF`. Example 10-8 illustrates the contents of an EAR file for a Provider Web application.

Example 10-8 Package Structure for a Web Service with a Provider Application

    provider.ear
        |__/META-INF/application.xml
        |__ provider-web.war
               |__/WEB-INF
                      |__web.xml
                      |__oracle-webservices.xml
                      |__/wsdl/<wsdl_name>.wsdl (optional)
                      |__/lib
                      |__/classes
                             |__ /provider instance classes

## Deploying Provider Web Applications

A Provider Web application is deployed (using standard deployment mechanisms) in a J2EE servlet container. The container must have the Provider system classes and the supporting classes available in its runtime.

For more information on deploying Provider Web applications, see the Oracle Containers for J2EE Deployment Guide.

## Testing Provider Web Application Deployment

The endpoints of a Provider Web application can be exposed by using a statically configured endpoint or added dynamically. If the endpoint provides an associated WSDL file, then you can invoke the Web Service Home Page to see whether deployment was successful. If the endpoint does not provide a WSDL file, a Test Page will not be available.

"Testing Web Service Deployment" in the Oracle Application Server Web Services Developer's Guide describes the Web Service Home page.

## Managing Provider Endpoints

If a static or a dynamically-added Provider endpoint provides an associated WSDL file, then it can be configured through the Web Services interface in Application Server Control. For more information see the topic "Web Service Home Page" in the Application Server Control on-line help.

## Assembling Clients for Provider Web Service Applications

A Provider Web Service application can be accessed by standard J2SE or J2EE static stub or DII clients. For more information on generating clients, see the following chapters:

- assembling a J2EE Web Service client, see "Assembling a J2EE Web Service Client" in the Oracle Application Server Web Services Developer's Guide.

- assembling a J2SE Web service client, see "Assembling a J2SE Web Service Client" in the Oracle Application Server Web Services Developer's Guide.

- "Testing Web Service Deployment" in the Oracle Application Server Web Services Developer's Guide describes the

- using WebServicesAssembler commands to assemble Web service artifacts, see "Using WebServicesAssembler" in the Oracle Application Server Web Services Developer's Guide.

## Additional Information

For more information on:

- assembling a J2EE Web Service client, see "Assembling a J2EE Web Service Client" in the Oracle Application Server Web Services Developer's Guide.

- assembling a J2SE Web service client, see "Assembling a J2SE Web Service Client" in the Oracle Application Server Web Services Developer's Guide.

- testing whether the Provider Web service application deployed successfully, see "Testing Web Service Deployment" in the Oracle Application Server Web Services Developer's Guide.

- using WebServicesAssembler commands to assemble Web service artifacts, see "Using WebServicesAssembler" in the Oracle Application Server Web Services Developer's Guide.