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

Part Number B28975-02
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

10 Using Web Service Providers

This chapter describes how to use the Oracle Application Server Web Services Provider API. 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 enables 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 using 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 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

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 the methods and properties in the ProviderConfig class.

addService and removeService Methods

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.

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

public void addService(String pathInfo, InputStream wsdlStream, String wsdlBaseURI, QName wsdlPort, QName serviceName, Object policy) throws ProviderException;

public void addService(String pathInfo, Definition wsdl, 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 features. The Provider can make processing decisions for incoming requests based on the URI available from the Provider's MessageContext.

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. While the pathInfo parameter cannot be null, it can be set to an empty string.

Three forms of the addService method are available; they differ only in how you provide the WSDL location for the service.

  • Providing the WSDL as a URL—This form of the addService method enables you to provide the WSDL as a URL (URL wsdlURL).

  • Reading the WSDL From an Input Stream—This form of the method enables the WSDL to be read from an input stream (InputStream wsdlStream). This method also provides a parameter where you can specify a URI for the WSDL file (String wsdlBaseURI). The value of this parameter is used to resolve relative imports in the Provider WSDL input stream.

  • Providing the WSDL as a Definition Object—This form of the method enables you to provide the WSDL as a javax.wsdl.Definition object. Use this signature if you are constructing endpoints dynamically and already have a Definition object instantiated. For example, you may have created the Definition object in memory and it does not represent a WSDL in the file system.

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 the Policy Element

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

PROPAGATE_DYNAMIC_ENDPOINTS Property

To support clustered environments, the ProviderConfig class provides the boolean constant PROPAGATE_DYNAMIC_ENDPOINTS. This constant represents the following property:

oracle.webservices.provider.propagateDynamicEndpoints

This property enables a Provider to make a dynamic endpoint accessible from all instances of an application across a configuration group or cluster. For more information on how to use this property, see "How to Make Dynamic Endpoints Accessible in a Clustered Environment".

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.

ProviderServlet Class

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.

How to Make a Web Service Provider-Aware

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

How to Edit 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="..." inputName="..." outputName="...">
                     <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>. The <provider-port> subelement is required; all others are optional.

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

Element Name Description

<property>

Specifies globally-defined properties; that is, properties that are available to all of the defined Provider ports. This element recognizes a name attribute.

<provider-description-name>

A name for the Provider description.

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

<wsdl-file>

Specifies the location of an associated WSDL for the Provider.

<wsdl-service-name>

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.


The <provider-port> element associates a WSDL port with a Web service interface and implementation. Table 10-2 describes the subelements of <provider-port>. The <provider-name>, <implementation-class>, and <servlet-links> subelements are required; all others are optional.

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

Element Name Description

<expose-testpage>

Indicates whether the test page should be exposed. Default is true.

<expose-wsdl>

Indicates whether the WSDL should be exposed. Default is true.

<implementation-class>

(required) Specifies the name of the class implementing the oracle.webservices.provider.Provider interface.

<max-request-size>

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.

<policy>

Defines the Web service management policies for the Provider. Table 10-3 describes the subelements of <policy>.

<property>

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.

<provider-name>

(required) The name of the Provider. The <provider-name> within the <provider-port> must be unique within the deployment descriptor.

<servlet-link>

(required) Associates a provider-port value with a servlet endpoint defined in the /WEB-INF/web.xml file.

<wsdl-port>

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.


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 describes the management policies applied to an individual operation. Table 10-4 describes the <operation> subelement.

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


Table 10-4 describes the <operation> element, where you can define management policies for specific Provider operations.

Table 10-4 Subelement of the <operations> Element

Element Name Description

<operation>

Specifies client-side quality of service configuration for a particular operation provided by the referenced Web service. The configuration appears within this element's <runtime> subelement.

This <operation> element has these attributes:

  • input—contains the input name of the operation from the WSDL.

  • name—(required) associates the contained quality of service configuration to a specific operation. The value of the attribute must match the operation name from the WSDL.

  • output—contains the output name of the operation from the WSDL.


See Also:

The following resources provide more information on Web service management policies:

How to Edit 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-5.

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-5 describes the elements which you must add to web.xml to make it Provider-aware.

Table 10-5 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

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 detailed information on each step.

  1. Write your Provider application so that it implements 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.

    "How to Make a Web Service Provider-Aware" provides 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.

    "How to Package Provider Web Application Provider Classes" provides more information on packaging a service which includes Provider classes.

How to Register a Dynamic Provider-Managed Endpoint

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

The generation, packaging, and deployment of a dynamic Provider-managed endpoint follows the same steps outlined in "How to Register a Static Provider-Managed Endpoint". To register the endpoint, you must perform the following additional step:

  • Register the service by invoking the addService method on the providerConfig reference. The implementation also has the option of passing the policy configuration by using the method's policy parameter.

Example 10-7 illustrates how a Provider can dynamically add an endpoint. In this example, 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. The policy parameter of the addService method uses the XMLUtil.elementFromString(ADD_SERVICE_POLICY) to pass the management features to the service. 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 ));
... 
}

How to Make Dynamic Endpoints Accessible in a Clustered Environment

To support clustered environments, the ProviderConfig class provides the boolean constant PROPAGATE_DYNAMIC_ENDPOINTS. This constant represents the following property:

oracle.webservices.provider.propagateDynamicEndpoints

This property enables you to make a dynamic endpoint accessible from all instances of an application across a configuration group or cluster.

If the property is set to true, then any addService invocation made after the dynamic endpoint is initialized at one OC4J instance causes the endpoint to be accessible to all instances of the application across the cluster or configuration group.

PROPAGATE_DYNAMIC_ENDPOINTS is an optional property that can be set as a <property> subelement of <provider-port> in the oracle-webservices.xml deployment descriptor. Example 10-8 illustrates how the property is used.

Example 10-8 PROPAGATE_DYNAMIC_ENDPOINTS Property

<oracle-webservices>
 <provider-description>
  ...
   <provider-port>
        ...
        <property name="oracle.webservices.provider.propagateDynamicEndpoints">true</property>
       ...
   </provider-port>
 </provider-description>
</oracle-webservices>

How to Package 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-9 illustrates the contents of an EAR file for a Provider Web application.

Example 10-9 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.

See Also:

Oracle Containers for J2EE Deployment Guide for more information on deploying Provider Web applications.

Testing Provider Web Application Deployment

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

See Also:

"Testing Web Service Deployment" in the Oracle Application Server Web Services Developer's Guide for more information on 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.

See Also:

The following chapters provide more information on assembling Web service clients:

Troubleshooting

See "Using Web Service Providers".

Additional Information

For more information on: