Skip Headers
Oracle® Application Server Advanced Web Services Developer's Guide
10g Release 3 (10.1.3)
B25603-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
 

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

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.

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

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:

Additional Information

For more information on: