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
 

9 Using Web Services Invocation Framework

This chapter describes Oracle Application Server Web Services support for the Web Services Invocation Framework (WSIF). WSIF provides a standard API for working with representations of different Web service messaging protocols as an alternative to working directly with a JAX-RPC SOAP client API. The WSIF API allows the client to use native protocols to communicate with the service.

The WSIF API allows a Web service to communicate with Web service components, such as Java classes, EJBs, or database resources, through a single interface. In addition to JAX-RPC which understands only SOAP, WSIF clients can directly use other protocols, such as RMI, IIOP, or JDBC.

To support different messaging protocols, you can add different WSIF bindings to the WSDL. This is in contrast to the SOAP protocol, where you add a SOAP binding. WSIF and SOAP bindings can co-exist in the same WSDL. This enables you to define both native and SOAP bindings for a particular service. For example, you can expose an EJB with a WSIF port and a SOAP port. Clients can access the same Web service even though they may be using different protocols. The protocol that is used to communicate with the service is determined by selecting a particular binding in the client: either a SOAP or a WSIF binding.

This chapter contains the following sections.

WSIF is sponsored by the Apache Software Group. For more information on WSIF, see the following Web site.

http://ws.apache.org/wsif/

Understanding WSIF Architecture

In the WSIF architecture, communications between the client and Web services are enabled through the WSDL. The WSDL becomes the normalized description of the software interface.

Figure 9-1 illustrates the WSIF architecture for OracleAS Web Services. The following steps describe the data flow through the architecture.

  1. Program the WSIF client according to the content of the abstract service description portion of the WSDL. This portion of the WSDL includes port types, operations, and message exchanges.

  2. At runtime, the WSIF client selects a concrete binding in the WSDL that determines which provider the WSIF runtime will use. Providers are protocol-specific pieces of code that provide implementation of the different WSIF bindings in the WSDL.

  3. The WSIF client makes calls into the WSIF API to invoke the Web service. This API is based on the abstract service description portion of the WSDL. By invoking the service based on its abstract description, you can work with a service regardless of how it was implemented, its protocol, or where it resides.

  4. The WSIF runtime in the kernal determines which provider to use, based on the binding selected in Step 2.

  5. The provider interacts with the Web service.

Services can be invoked dynamically and without the need for generating stubs.

Figure 9-1 WSIF Architecture for OracleAS Web Services

Description of Figure 9-1 follows
Description of "Figure 9-1 WSIF Architecture for OracleAS Web Services"

WSIF supports providers for clients of Web services that expose JAX-RPC (SOAP), Java classes, EJBs, and database resources. You can also define your own providers. Defining your own providers is beyond the scope of this manual. For information on this topic, see the Apache Software Group Web page for WSIF.

http://ws.apache.org/wsif/

The following sections describe the WebServicesAssembler commands and Ant tasks that insert WSIF information into the WSDL.

Configuring a WSIF Endpoint for Java Classes

To insert WSIF Java extensions into the WSDL, OracleAS Web Services provides two arguments that can be used with the assemble or genWsdl WebServicesAssembler commands.

As you assemble a Web service based on a Java class with the assemble or genWsdl commands, the wsifJavaBinding and wsifJavaPort arguments allow you to request a WSIF binding. For more information on creating a Web service based on a Java class, see "Assembling a Web Service with Java Classes" in the Oracle Application Server Web Services Developer's Guide.

The wsifJavaBinding or wsifJavaPort arguments add the appropriate WSDL extensions in the form of a WSIF binding that allow a WSIF client to access Java class exposed as a Web service. "WSIF Java Extensions to the WSDL" lists the schema definitions that can be added to the WSDL to support WSIF Java bindings.

To configure the WSIF Java bindings for a single port, you can use either the wsifJavaBinding or wsifJavaPort argument. The wsifJavaPort argument also enables you to specify multiple ports of different types within an Ant task.

While the wsifJavaBinding argument can be used either on the command line or in an Ant task, the wsifJavaPort can be used only in an Ant task.

The following sections describe how to configure a WSIF endpoint for single and multiple Java ports.

Configuring a WSIF Endpoint for a Single Java Port

A WSIF endpoint for a single Java port can be configured with wsifJavaBinding or wsifJavaPort.

Configuring a Single Java Port with wsifJavaBinding

The wsifJavaBinding argument can be used by either assemble or genWsdl command to specify the WSIF Java binding for a single port.

The wsifJavaBinding argument requires you to specify the className argument. The argument passes this value to the java:address element in the WSDL's <port> element.

Example 9-1 illustrates an WebServicesAssembler command line for genWsdl that calls wsifJavaBinding. Example 9-2 illustrates the corresponding Ant task. The argument causes the java:address element in the WSDL's <port> element to be populated with classname="oracle.demo.hello.HelloImpl". The variable ${wsdemo.common.class.path} represents the classpath.

Example 9-1 Command Line, Using wsifJavaBinding to Configure a Single Java Port

java -jar wsa.jar -genWsdl 
                  -output wsdl 
                  -style rpc 
                  -use literal 
                  -wsifJavaBinding true 
                  -interfaceName oracle.demo.hello.HelloInterface 
                  -className oracle.demo.hello.HelloImpl 
                  -classpath ${wsdemo.common.class.path}:build/classes 

Example 9-2 Ant Task, Using wsifJavaBinding to Configure a Single Java Port

<oracle:genWsdl
    output="wsdl"
    style="rpc"
    use="literal"
    wsifJavaBinding="true"
    >
    <oracle:porttype
         interfaceName="oracle.demo.hello.HelloInterface"
         className="oracle.demo.hello.HelloImpl" 
    </oracle:porttype>
    <oracle:classpath>
         <oracle:pathelement path="${wsdemo.common.class.path}"/>
         <oracle:pathelement location="build/classes"/>
    </oracle:classpath>
</oracle:genWsdl>

Configuring a Single Java Port with wsifJavaPort

The wsifJavaPort argument can be used only in an Ant task. Although you typically use wsifJavaPort to specify WSIF Java bindings for multiple ports, you can also use it to specify a single port. The argument also has attributes that allow you to specify a WSIF port name, a Java class name for each port, and a custom class loader and its classpath. These attributes are passed to the java:address element in the WSDL's <port> element.

Table 9-1 describes the attributes that can be used by the wsifJavaPort argument. All of the attributes are optional.

Table 9-1 Attributes for the wsifJavaPort Argument

Attribute Description

classLoader

Specifies the name of the Java class loader. If you do not provide a value for this attribute, the value for the system class loader will be used.

className

Specifies the name of the implementation class. If you do not provide a value for this attribute, WebServicesAssembler will use the class name for the parent Ant task if it was specified.

classPath

Specifies the class path for the Java class loader. If you do not provide a value for this attribute, the system class path will be used.

name

Specifies the name of the WSIF port in the Web service. This name will be used to identify the WSIF port in the WSDL's port element.


The Ant task for genWsdl in Example 9-3 inserts WSIF Java binding code into the WSDL's binding, binding operation, and port clauses. The HelloImpl class used as the className attribute to the wsifJavaPort argument, contains a sayHello method that takes a greeting parameter of type String. The variable ${additional.class.path} represents the classpath.

Example 9-3 Using wsifJavaPort to Configure a Single Java Port

<oracle:genWsdl
       output="wsdl"
       style="rpc"
       use="literal"
       >
       <oracle:porttype
          interfaceName="oracle.demo.hello.HelloInterface">
           <oracle:wsifJavaPort name="HelloServiceJavaPort" 
                     className="oracle.demo.hello.HelloImpl"  />
       </oracle:porttype>
       <oracle:classpath>
           <oracle:pathelement path="${additional.class.path}" />
           <oracle:pathelement location="build/classes" />
       </oracle:classpath>
</oracle:genWsdl>

Example 9-4 illustrates the WSIF Java binding code that the Ant task in the previous example inserts into the WSDL's binding, binding operation, and port clauses.

Example 9-4 WSDL Extensions for WSIF Java Bindings

...
<java:binding/>
     <format:typeMapping encoding="Java" style="Java">
           <format:typeMap typeName="xsd:string" formatType="java.lang.String"/>
     </format:typeMapping>
     ...
<java:operation
      methodName="sayHello"
      parameterOrder="greeting"
      methodType="instance"
      returnType="result" />
      ...
<port name="HelloServiceJavaPort" binding="tns:JavaBinding"> 
    <java:address className="oracle.demo.hello.HelloImpl" />
</port>
...

Configuring a WSIF Endpoint for Multiple Java Ports

You can use the wsifJavaPort argument with the assemble and genWsdl commands to define WSIF bindings for multiple Java ports. Example 9-5 illustrates an Ant task that creates a WSIF port named HelloServiceJavaPort and a SOAP port named HelloServiceSoapPort. The SOAP port is created by adding the <oracle:port name="... "/> subtask. Note that className is declared in the parent Ant task. The variable ${additional.class.path} represents the classpath. Table 9-1 describes the attributes that can be used by wsifJavaPort.

Example 9-5 Using wsifJavaPort to Configure a WSIF Java Port and a SOAP Java Port

<oracle:genWsdl
       output="wsdl"
       style="rpc"
       use="literal"
       >
       <oracle:porttype
         interfaceName="oracle.demo.hello.HelloInterface"
         className="oracle.demo.hello.HelloImpl">
           <oracle:wsifJavaPort name="HelloServiceJavaPort" /> 
           <oracle:port name="HelloServiceSoapPort" /> 
       </oracle:porttype>
       <oracle:classpath>
           <oracle:pathelement path="${additional.class.path}" />
           <oracle:pathelement location="build/classes" />
       </oracle:classpath>
</oracle:genWsdl>

WSIF Java Extensions to the WSDL

To comply with the WSIF Framework definition, OracleAS Web Services inserts binding information into the WSDL that allows a Java class to be represented as a Web service. Example 9-4 illustrates how additional bindings, binding operations, and port clauses are added to the WSDL to describe a WSIF service. Example 9-6 illustrates the corresponding XML schema definitions for these extensions.

Example 9-6 Schema Definitions to Support WSIF Java Bindings

...
<!-- Java binding --> 
<binding ... > 
    <java:binding/> 
    <format:typeMapping style="uri" encoding="..."/>? 
        <format:typeMap typeName="qname"|elementName="qname" 
              formatType="nmtoken"/>* 
    </format:typeMapping> 
    ...
    <operation>* 
        <java:operation 
            methodName="nmtoken" 
            parameterOrder="nmtoken"? 
            returnPart="nmtoken"?
            methodType="instance|static|constructor"? />? 
        <input name="nmtoken"? />? 
        <output name="nmtoken"? />? 
        <fault name="nmtoken"? />? 
    </operation> 
</binding> 
 ....
<service ... > 
    <port name="nmtoken" >* 
         <java:address 
             className="nmtoken" 
             classPath="nmtoken"? 
             classLoader="nmtoken"? /> 
    </port> 
</service>
...

Configuring a WSIF Endpoint for EJBs

To insert WSIF EJB extensions into the WSDL, the WebServicesAssembler tool provides two arguments that can be used with the ejbAssemble or genWsdl commands.

As you assemble a Web service based on an EJB with the ejbAssemble command, the wsifEjbBinding or wsifEjbPort arguments allow you to request a WSIF binding. For more information on creating a Web service based on an EJB, see "Assembling a Web Service with EJBs" in the Oracle Application Server Web Services Developer's Guide.

These arguments add the appropriate WSDL extensions that allow a WSIF client to access an EJB exposed as a Web service. The section "WSIF EJB Extensions to the WSDL" lists the schema definitions that can be added to the WSDL to support WSIF EJB bindings.

To configure the WSIF EJB binding for a single port, you can use either the wsifEjbBinding or wsifEjbPort argument. To configure WSIF EJB bindings for multiple ports, you must use the wsifEjbPort argument.

While the wsifEjbBinding argument can be used either on the command line or in an Ant task, the wsifEjbPort can be used only in an Ant task.

The following sections describe how to configure WSIF endpoints for single and multiple EJB ports.

Configuring a WSIF Endpoint for a Single EJB Port

A WSIF endpoint for a single EJB port can be configured with the wsifEjbBinding or wsifEjbPort argument.

Configuring a Single EJB Port with wsifEjbBinding

The wsifEjbBinding argument can be used by either the ejbAssemble or genWsdl command to specify the WSIF EJB binding for a single port.

The wsifEjbBinding argument requires you to specify the name and jndiName arguments. The wsifEjbBinding argument passes these values to the ejb:address element in the WSDL's <port> element. The jndiProviderURL and initialContextFactory arguments provide the JNDI provider URL and JNDI initial context values. If you do not provide these arguments, then these values are obtained from the jndi.properties file. For more information on this argument, see "wsifEjbBinding" in the Oracle Application Server Web Services Developer's Guide.

Example 9-7 illustrates a WebServicesAssembler command line for genWsdl that calls wsifEjbBinding. Example 9-8 illustrates the corresponding Ant task. The argument causes the ejb:address element in the WSDL's <port> element to be populated with className="oracle.demo.hello.HelloImpl" and jndiName="HelloService2EJB". The variable ${additional.class.path} represents the classpath.

Example 9-7 Command Line, Using wsifEjbBinding to Configure a Single EJB Port

java -jar wsa.jar -genWsdl 
                  -output wsdl 
                  -style rpc 
                  -use literal 
                  -wsifEjbBinding true 
                  -jndiName HelloService2EJB 
                  -interfaceName oracle.demo.ejb.HelloServiceInf 
                  -jndiProviderUrl deployer:oc4j:localhost:23791/HelloService
                  -initialContextFactory oracle.j2ee.rmi.RMIInitialContextFactory
                  -className oracle.demo.hello.HelloImpl 
                  -classpath ${additional.class.path}:build/classes 

Example 9-8 Ant Task, Using wsifEjbBinding to Configure a Single EJB Port

<oracle:genWsdl
      output="wsdl"
      style="rpc"
      use="literal"
      wsifEjbBinding="true"
      jndiName="HelloService2EJB"
      jndiProviderUrl="deployer:oc4j:localhost:23791/HelloService"
      initialContextFactory="oracle.j2ee.rmi.RMIInitialContextFactory"
      >
       <oracle:porttype
            interfaceName="oracle.demo.ejb.HelloServiceInf"
            className="oracle.demo.hello.HelloImpl">
       </oracle:porttype>
       <oracle:classpath>
            <pathelement path="${additional.class.path}"/>
            <pathelement location="build.ejb.dir"/>
       </oracle:classpath>
</oracle:genWsdl>

Configuring a Single EJB Port with wsifEjbPort

The wsifEjbPort argument can be used only in an Ant task. Although you typically use wsifEjbPort to specify WSIF EJB bindings for multiple ports, you can also use it to specify a single port. The argument has attributes that allow you to specify a WSIF port name, a class name, a JNDI name, a JNDI initial context, and a JNDI provider URL for each port. These attributes are passed to the ejb:address element in the WSDL. Table 9-2 describes the attributes that can be used by the wsifEjbPort argument. Except for jndiName, all of the attributes are optional.

Table 9-2 Attributes for the wsifEjbPort argument.

Attribute Description

className

Specifies the class name of the EJB's home interface. If you do not provide a value for this attribute, WebServicesAssembler will use the class name for the parent Ant task if it was specified.

initialContextFactory

Specifies the name of the factory that will provide the initial context. If you not provide a value for this attribute, the value in the jndi.properties file will be used.

jndiName

(required) Specifies the JNDI name for the EJB.

jndiProviderURL

Specifies the URL for the JNDI Provider. If you do not provide a value for this attribute, the value in the jndi.properties file will be used.

name

Specifies the name of the WSIF Port in the Web service. This name will be used to identify the WSIF port in the WSDL's port element.


The Ant task for genWsdl in Example 9-9 inserts WSIF EJB binding code into the WSDL's binding, binding operation, and port clauses. The HelloHome class used as the className attribute to the wsifEJBPort argument, contains a sayHello method that takes a greeting parameter of type String. The variable ${additional.class.path} represents the classpath.

Example 9-9 Using wsifEjbPort to Configure a Single EJB Port

<oracle:genWsdl
    output="wsdl"
    style="rpc"
    use="literal"  
    serviceName="${app.name}"
    >
    <oracle:porttype
         interfaceName="oracle.test.wsif.HelloServiceInf">
           <oracle:wsifEjbPort name="EjbPort"
            className="oracle.test.wsif.HelloHome"
            jndiName="HelloServiceBean"
            jndiProviderUrl="deployer:oc4j:localhost:23791/HelloService"
            initialContextFactory="oracle.j2ee.rmi.RMIInitialContextFactory"
            />
    </oracle:porttype>
    <oracle:classpath> 
        <oracle:pathelement path="${additional.class.path}"/>
        <oracle:pathelement location="build/classes"/>
    </oracle:classpath>
</oracle:genWsdl>

Example 9-10 illustrates the WSIF EJB binding code that the previous example inserts into the WSDL's binding, binding operation, and port clauses.

Example 9-10 WSDL Extensions for WSIF EJB Bindings

...
<ejb:binding/>
    <format:typeMapping encoding="Java" style="Java">
        <format:typeMap typeName="xsd:string" formatType="java.lang.String"/>
    </format:typeMapping>
...
<operation name="sayHello">
    <ejb:operation 
         methodName="sayHello" 
         interface="remote" 
         parameterOrder="greeting" 
         returnPart="result"/>
... 
<port name="EjbPort" binding="tns:EjbPortBinding">
    <ejb:address  className="oracle.test.wsif.HelloHome"
        jndiName="HelloServiceBean"
        initialContextFactory="oracle.j2ee.rmi.RMIInitialContextFactory"
        jndiProviderURL="deployer:oc4j:localhost:23791/HelloService"/>
</port>  
...

Configuring a WSIF Endpoint for Multiple EJB Ports

Use the wsifEjbPort argument to define WSIF bindings for multiple EJB ports. This argument can be used by the ejbAssemble and the genWsdl Ant tasks. Example 9-11 illustrates the Ant task that creates a WSIF port named EjbPort and a SOAP port named SoapPort. The SOAP port is created by adding the <oracle:port name="... "/> subtask. The variable ${additional.class.path} represents the classpath. Table 9-2 describes the attributes that can be used by wsifEjbPort.

Example 9-11 Using wsifEjbPort to Configure Multiple EJB Ports

<oracle:genWsdl
    
    output="wsdl"
    style="rpc"
    use="literal"              serviceName="${app.name}"
    >
      <oracle:porttype interfaceName="oracle.test.wsif.HelloServiceInf"
        >
        <oracle:port name="SoapPort" uri="TestWsdlService"/>
        <oracle:wsifEjbPort name="EjbPort"
          className="oracle.test.wsif.HelloHome"
          jndiName="HelloServiceBean"
          jndiProviderUrl="deployer:oc4j:localhost:23791/HelloService"
          initialContextFactory="oracle.j2ee.rmi.RMIInitialContextFactory"
        />
     </oracle:porttype>
    <oracle:classpath>         <oracle:pathelement path="${additional.class.path}"/>
        <oracle:pathelement location="build/classes"/>
    </oracle:classpath>
</oracle:genWsdl>

WSIF EJB Extensions to the WSDL

To comply with the WSIF Framework definition, OracleAS Web Services inserts code into the WSDL that allows an EJB to be represented as a Web service. Example 9-10 illustrates how additional bindings, binding operations, and port clauses are added to the WSDL to describe a WSIF service. Example 9-12 illustrates the corresponding XML schema definitions for these extensions.

Example 9-12 Schema Definitions to Support WSIF EJB Bindings

...
<!-- EJB binding --> 
<binding ... > 
    <ejb:binding/> 
    <format:typeMapping style="uri" encoding="..."/>? 
        <format:typeMap typeName="qname"|elementName="qname"
                   formatType="nmtoken"/>* 
    </format:typeMapping> 
    ...
    <operation>* 
        <ejb:operation 
            methodName="nmtoken" 
            parameterOrder="nmtoken"? 
            returnPart="nmtoken"?
            interface="home|remote"? />? 
        <input name="nmtoken"? />? 
        <output name="nmtoken"? />? 
        <fault name="nmtoken"? />? 
    </operation> 
</binding> 
... 
<service ... > 
    <port>* 
         <ejb:address 
             className="nmtoken" 
             jndiName="nmtoken" 
             initialContextFactory="nmtoken"?
             jndiProviderURL="url"?  /> 
    </port> 
</service> 
...

Configuring a WSIF Endpoint for Database Resources

To insert WSIF extensions for database resources into the WSDL, OracleAS Web Services provides two arguments that can be used with the aqAssemble, dbJavaAssemble, plsqlAssemble, sqlAssemble and genWsdl WebServicesAssembler commands.

As you assemble a Web service based on a database resource with the aqAssemble, dbJavaAssemble, plsqlAssemble, sqlAssemble, or genWsdl commands, the wsifDbBinding and wsifDbPort arguments allow you to create a direct invocation to the database by using a WSIF binding. Note that database WSIF clients must provide a JNDI setup where the data source for connecting to the database can be determined at runtime.

These arguments add the appropriate WSDL extensions that allow a WSIF client to access database resources exposed as a Web service. The section "WSIF SQL Extensions to the WSDL" lists the schema definitions that can be added to the WSDL to support WSIF database resource bindings.

To configure the WSIF database resource binding for a single port, you can use either the wsifDbBinding or wsifDbPort argument. To configure WSIF database resource bindings for multiple ports, you must use the wsifDbPort argument.

While the wsifDbBinding argument can be used either on the command line or in an Ant task, wsifDbPort can be used only in an Ant task.

The following sections describe how to configure WSIF endpoints for single and multiple database resource ports.

Configuring a WSIF Endpoint for a Single Database Resource Port

The WSIF endpoint for a single database resource port can be configured with wsifDbBinding or wsifDbPort.

Configuring a Single Database Resource Port with wsifDbBinding

The wsifDbBinding argument can be used with aqAssemble, dbJavaAssemble, plsqlAssemble, sqlAssemble, and genWsdl WebServicesAssembler commands to specify the WSIF database resource bindings for a single port.

To establish the database connection, you must specify either dataSource or a combination of dbUser and dbConnection.

Table 9-3 Attributes for the wsifDbBinding and wsifDbPort Arguments

Attribute Description

className

(required) Specifies the name of the Java class generated by Oracle JPublisher. If you do not provide a value for this attribute, WebServicesAssembler will derive a value based on the port name.

dataSource

Specifies the JNDI location of the data source used by the Web service. For more information on the argument, see "datasource" in the "Database Assembly Commands" section of theOracle Application Server Web Services Developer's Guide.

dbConnection

Specifies the JDBC URL for the database. If you specify dbConnection, you must also provide a value for dbUser. See "dbConnection" in the "Database Assembly Commands" section of theOracle Application Server Web Services Developer's Guide for more information on this attribute.

dbUser

Specifies the database schema and password in the form user/password. If you specify dbUser, you must also provide a value for dbConnection. See "dbUser" in the "Database Assembly Commands" section of theOracle Application Server Web Services Developer's Guide for more information on this attribute.

name

(required for wsifDBPort only) Specifies the port name.


  • If the dataSource argument appears in an Ant task or on the command line, it will provide assembly time and runtime access to the database.

  • If the dbConnection and dbUser arguments appear in an Ant task or on the command line, they will provide assembly time access to the database.

  • If the dbConnection and dataSource arguments appear in an Ant task or on the command line, then dbConnection provides assembly time access to the database while dataSource provides runtime access.

  • If the dbConnection, dbUser, and dataSource arguments appear in an Ant task or on the command line, then dbConnection and dbUser will be used for assembly time access to the database. The dataSource argument will be used for runtime access.

Example 9-13 illustrates a WebServicesAssembler command line for sqlAssemble that calls wsifDbBinding to configure a single port for a database resource. Example 9-14 illustrates the corresponding Ant task. These examples provides values for dbUser and dbConnection which will be entered into the <port> element of the WSDL. The useDataSource argument is specified as false: the value of the dataSource argument will not be used in the WSDL <port> element. The variables ${wsdemo.common.class.path}, ${additional.class.path}, and ${service.classes.dir} represent classpath elements.

Example 9-13 Command Line, Using wsifDbBinding to Configure a Single Database Resource Port

java -jar wsa.jar -sqlAssemble 
                  -dbUser scott/tiger 
                  -dbConnection jdbc:oracle:thin:@... 
                  -dataSource jdbc/OracleManagedDS
                  -appName SqlWsifTest 
                  -serviceName sqlwsif 
                  -output build 
                  -ear dist/SqlWsifTest.ear 
                  -style rpc 
                  -use literal 
                  -wsifDbBinding true 
                  -sqlstatement "getEname=select ename from emp" 
                  -sqlstatement "updateSal=update emp SET sal=sal+500 where
                                 ename=:{myname VARCHAR}"
                   -classpath ${CLASSPATH}:build/classes

Example 9-14 Ant Task, Using wsifDbBinding to Configure a Single Database Resource Port

<oracle:sqlAssemble 
    dbUser="scott/tiger" 
    dbConnection="jdbc:oracle:thin@…" 
    dataSource="jdbc/OracleManagedDS"
    appName="SqlWsifTest"
    serviceName="sqlwsif"
    output="build"
    ear="dist/SqlWsifTest.ear"
    style="rpc"
    use="literal"
    debug="true"
    wsifDbBinding="true"
    > 
    <oracle:port name="sqlwsif" uri="SqlWsifTest" />
    <sqlstatement value="getEname=select ename from emp" /> 
    <sqlstatement value="updateSal=update emp SET sal=sal+500 where ename=:{myname VARCHAR}" />
    <oracle:classpath> 
        <oracle:pathelement path="${wsdemo.common.class.path}"/> 
        <oracle:pathelement path="${additional.class.path}"/> 
        <oracle:pathelement location="client/classes"/> 
        <oracle:pathelement location="${service.classes.dir}"/> 
    </oracle:classpath> 
</oracle:sqlAssemble>

Example 9-15 illustrates the WSIF database resource binding code that the previous example inserts into the WSDL's <port> element.

Example 9-15 WSDL Extensions for WSIF Database Resource Bindings

...
<service name="sqlwsif"> 
    <port name="JavaPort" binding="tns:JavaPortBinding"> 
        <java:address className="...User" 
            dataSource="jdbc/OracleManagedDS"/> 
    </port>
</service>
...

Configuring a Single Database Resource Port with wsifDbPort

The wsifDbPort argument can be used only in an Ant task. Although you typically use wsifDbPort to specify the WSIF database resource bindings for multiple ports, you can also use it to specify a single port. The argument has attributes that allow you to specify a WSIF port name, a class name for the Java files generated by Oracle JPublisher, and database connection information. These attributes are passed to the java:address element of the WSDL's <port> element.

Table 9-3 describes the attributes that can be used by the wsifDbPort argument. Except for className and name, all of the attributes are optional.

  • If the dataSource argument appears in an Ant task or on the command line, it will provide assembly time and runtime access to the database.

  • If the dbConnection and dbUser arguments appear in an Ant task or on the command line, they will provide assembly time access to the database.

  • If the dbConnection and dataSource arguments appear in an Ant task or on the command line, then dbConnection provides assembly time access to the database while dataSource provides runtime access.

  • If the dbConnection, dbUser, and dataSource arguments appear in an Ant task or on the command line, then dbConnection and dbUser will be used for assembly time access to the database. The dataSource argument will be used for runtime access.

Example 9-13 illustrates the WebServicesAssembler command line for wsifDbPort which inserts WSIF database resource code into the WSDL's binding, binding operation, and port clauses. Example 9-16 illustrates the corresponding Ant task. In the wsifDbPort argument, the name of the port is set to JavaPort and the name of the JPublisher-generated Java class is oracle.generated.sqlwsifUser.

Example 9-16 Ant Task, Using wsifDbPort to Configure a Single Database Resource Port

<oracle:sqlAssemble 
    dataSource="jdbc/OracleManagedDS" 
    appName="SqlWsifTest"
    portName="sqlwsif"
    serviceName="sqlwsif"
    output="build"
    ear="dist/SqlWsifTest.ear"
    style="rpc"
    use="literal"
    debug="true"
    >
    <oracle:port name="sqlwsif"  uri="SqlWsifTest" />
    <sqlstatement value="getEname=select ename from emp" />
    <sqlstatement value="updateSal=update emp SET sal=sal+500 where ename=:{myname VARCHAR}" />
    <oracle:wsifDbPort 
        name="JavaPort"
        className="oracle.generated.sqlwsifUser"
    /> 
    <oracle:classpath> 
        <oracle:pathelement path="${wsdemo.common.class.path}"/> 
        <oracle:pathelement path="${additional.class.path}"/> 
        <oracle:pathelement location="client/classes"/> 
        <oracle:pathelement location="service/classes"/> 
    </oracle:classpath> 
</oracle:sqlAssemble>

Example 9-17 illustrates the WSIF database resource binding code that the previous example inserts into the WSDL.

Example 9-17 WSDL Extensions for WSIF Database Resource Bindings

<service name="sqlwsif">           
    <port name="JavaPort" binding="tns:JavaPortBinding"> 
        <java:address className="oracle.generated.sqlwsifUser" 
            dataSource="jdbc/OracleManagedDS"/>            
    </port>
</service>

Configuring a WSIF Endpoint for Multiple Database Resource Ports

Use the wsifDbPort argument to define WSIF bindings for multiple database resource ports. This argument can be used in the Ant tasks for the aqAssemble, dbJavaAssemble, plsqlAssemble, sqlAssemble, and genWsdl commands.

Example 9-18 illustrates an Ant task that creates a SOAP port and a WSIF port. The port operations are based on the <sqlstatement value="..."/> subtasks. The wsifDbPort subtask creates the JavaPort port. The oracle:port subtask creates the SOAP port. The variables ${wsdemo.common.class.path}, ${additional.class.path}, and ${service.classes.dir} represent classpath elements. Table 9-3 describes the attributes that can be used by wsifDbPort.

Example 9-18 Ant Task, Using wsifDbPort to Configure Multiple Database Resource Ports

<oracle:sqlAssemble
        dbUser="scott/tiger"
        dbConnection="jdbc:oracle:thin:@${DB_HOST}:${DB_PORT}:${DB_SID}"
        dataSource="jdbc/OracleManagedDS"
        appName="wsifTest"
        portName="dbwsif"
        serviceName="dbwsif"
        output="build"
        ear="dist/wsifDbTest.ear"
        style="rpc"
        use="literal"
        debug="true"
        >
        <oracle:port name="dbwsif"  uri="wsifDbTest"/>
        <sqlstatement value="getEname=select ename from emp" />
        <sqlstatement value="updateSal=update emp SET sal=sal+500 where
            ename=:{myname VARCHAR}" />
        <oracle:wsifDbPort name="JavaPort" 
                className="oracle.generated.sqlwsifUser"
        >
        <oracle:classpath>
            <oracle:pathelement path="${wsdemo.common.class.path}"/>
            <oracle:pathelement path="${additional.class.path}"/>
            <oracle:pathelement location="${client.classes.dir}"/>
            <oracle:pathelement location="${service.classes.dir}"/>
        </oracle:classpath> 
    </oracle:sqlAssemble>

WSIF SQL Extensions to the WSDL

To comply with the WSIF Framework definition, OracleAS Web Services inserts code into the WSDL that allows a database resource to be represented as a Web service. Example 9-15 illustrates how additional database resource bindings are placed in the WSDL. Specifically, the WSIF JavaPortBinding is further extended with the optional dataSource attribute. The presence of this attribute indicates that this is a database port and not a Java port. Example 9-19 illustrates the corresponding XML schema definitions for this extension.

Example 9-19 Schema Definitions to Support WSIF Database Resource Bindings

...
<definitions .... > 
 
    <!-- Java binding --> 
    <binding ... > 
        <java:binding/> 
        <format:typeMapping style="uri" encoding="..."/>? 
            <format:typeMap typeName="qname"|elementName="qname" formatType="nmtoken"/>* 
        </format:typeMapping> 
        <operation>* 
            <java:operation 
                methodName="nmtoken" 
                parameterOrder="nmtoken"? 
                returnPart="nmtoken"?
                methodType="instance|static|constructor"? />? 
            <input name="nmtoken"? />? 
            <output name="nmtoken"? />? 
            <fault name="nmtoken"? />? 
        </operation> 
    </binding> 
 
    <service ... > 
        <port>* 
             <java:address 
                 className="nmtoken" 
                 classPath="nmtoken"? 
                 classLoader="nmtoken"?
                 dataSource="nmtoken"?
        </port> 
    </service>  
</definitions>
...

Writing a WSIF Client

A WSIF client is similar to a DII client in that it does not rely on any pre-generated stub. The WSDL plays a central role for the WSIF client. Since the WSDL contains all of the information to invoke the service, it must be available to the client at runtime. The WSIF client must create the WSIF service, port, operation, and messages, before it actually invokes the operation with the messages.

The WSIF API, which is based on the abstract service description portion of the WSDL, contains methods for obtaining this information from the WSDL. The WSIF API is available from the Apache Software Group Web site.

http://ws.apache.org/wsif/


Note:

There is no WebServicesAssembler support for generating WSIF clients.

To write a WSIF client, follow these general steps.

  1. Create a new instance of a WSIF service factory.

    The newInstance method of the WSIFServiceFactory class instantiates a new WSIF service factory. For example:

    // create a service factory
    WSIFServiceFactory factory = WSIFServiceFactory.newInstance();
    
    
  2. Create a WSIF service.

    Information in the WSDL file is used to build the WSIF service. The WSIFServiceFactory class provides a variety of getService methods to obtain the service definition from the WSDL. The location of the WSDL file can be specified either as a URL location available over HTTP, or as a file-based location available through the classLoader. Additional parameters for service creation are service name/namespace and portType/namespace. For example:

    WSIFService service = factory.getService( ... );
    
    
  3. Create the WSIF port, operation, and messages.

    Use the WSIF service to create the WSIF port. Use one of the WSIF API WSIFService.getPort methods to get the WSIF port for the port type that this factory supports. For example:

    WSIFPort port = service.getPort("portName");
    
    
  4. Create the WSIF operation.

    Use the WSIF port to create the WSIF operation. An operation is created using a service name or a combination of service name and input and output messages. There must be exactly one operation in this port's portType with this name. The WSIF API supports a variety of createOperation methods, depending on the type of J2EE component you are exposing as a Web service. For example:

    WSIFOperation operation = port.createOperation("operationName");
    
    
  5. Create the input, output, and fault messages.

    Use the WSIF operation to create the messages. The WSIFOperation interface in the WSIF API supports a variety of methods to create input, output, and fault messages. For example:

    WSIFMessage input = operation.createInputMessage();
    WSIFMessage output = operation.createOutputMessage();
    WSIFMessage fault = operation.createFaultMessage();
    
    
  6. Populate the input message.

    To populate the input message, set the parts (defined in the WSDL) of the input message. For example, use one of the WSIFMessage.setObjectPart methods to allow the operation to pass a value to the service. You can also set message types using Java classes based on the type map, which is set by the service.

    input.setObjectPart( ... );
    
    
  7. Make the call to the service.

    Use one of the WSIF API "execute" methods to execute the operation. The signature allows for input, output and fault messages. The WSIF API supports a variety of "execute" methods, depending on the type of J2EE component you are exposing as a Web service. For example:

    operation.executeRequestResponseOperation( ... ); 
    
    

    The call can return a Boolean variable that is equal to true if the operation succeeds, or false otherwise. If the call fails, a fault message can be examined to determine the exact reason for the failure. The fault message is populated based on the SOAPBody:Fault element defined in the SOAP specification. If the call succeeds, the content of the output message can be extracted into Java classes based on the output message parts (similar to the population of the input messages).

Example 9-20 illustrates a sample DII client. The client performs an invocation on the HelloService's sayHello method, and passes "Duke" as the value for the name parameter. The WSDL that defines the service is deployed at http://localhost:8888/helloWSIFDii/helloWSIFDii?WSDL. The portType is the QName {http://hello.demo.oracle/}HelloInterface, where http://hello.demo.oracle/ is the portType namespace and HelloInterface is the port name. The name of the WSIF port is HelloServicePort and the name of the operation is sayHello. The executeRequestResponseOperation method makes the call to the service.

Example 9-20 Sample WSIF Client Code

import org.apache.wsif.*;
...
// create a service factory
WSIFServiceFactory factory = WSIFServiceFactory.newInstance();
 
// parse the WSDL
WSIFService service =
        factory.getService("http://localhost:8888/helloWSIFDii/helloWSIFDii?WSDL",
        null, null, "http://hello.demo.oracle/", "HelloInterface");

// create WSIF port, operation, and messages
WSIFPort port = service.getPort("HelloServicePort");
WSIFOperation operation = port.createOperation("sayHello");
WSIFMessage input = operation.createInputMessage();
WSIFMessage output = operation.createOutputMessage();
WSIFMessage fault = operation.createFaultMessage();
input.setObjectPart("name", "Duke");
 
// make the actual call to the service
operation.executeRequestResponseOperation(input, output, fault); 
...

Writing a WSIF Client Using a Dynamic Proxy

A much simpler way of writing a WSIF client is to write it using a service endpoint interface. The WSIF runtime can create a corresponding implementation for you in the form of a dynamic proxy. This technique assumes that you already have a compiled service endpoint interface. The WSIF API provides a getStub method (org.apache.wsif.WSIFService.getStub) that gets the dynamic proxy that implements the interface.

The following steps summarize how to get the interface as a dynamic proxy.

  1. Create a new instance of a WSIF service factory.

    For example:

    WSIFServiceFactory factory = WSIFServiceFactory.newInstance(); 
    
    
  2. Create a WSIF service.

    For example:

    WSIFService service = factory.getService( ... );  
    
    
  3. Pass the service port name and the service endpoint interface class to the getStub method.

  4. Cast the dynamic proxy which is returned to the service endpoint interface.

    For example:

    HelloInterface stub = (HelloInterface) service.getStub( ... );  
    
    
  5. Call methods directly on the proxy that implements the interface.

    For example:

    String resp = stub.sayHello("Duke");  
    
    

Example 9-21 illustrates using the WSIF client as a dynamic proxy. The port name HttpSoap11 and the service endpoint interface class HelloInterface.class are passed to the getStub method. The returned dynamic proxy is cast to the HelloInterface service endpoint interface. Note that the stub parameter is also declared as type HelloInterface. Using the stub, you can then call methods on the interface directly.

Example 9-21 Using a WSIF Client as a Dynamic Proxy

// Create a service factory
WSIFServiceFactory factory = WSIFServiceFactory.newInstance();

// Parse the WSDL
WSIFService service = factory.getService(serviceURL + "?WSDL", null, null,
        "http://hello.demo.oracle/", "HelloInterface");

// Call the getStub method with the port name and 
//    the service endpoint interface class.
// Cast the returned dynamic proxy to the service endpoint interface. 
HelloInterface stub = (HelloInterface) service.getStub("HttpSoap11", HelloInterface.class);

// Call methods directly on the interface
String resp = stub.sayHello("Duke");

Using genInterface to Generate a Service Endpoint Interface

The steps in the previous section assume that you have a WSDL and a service endpoint interface. If you do not have the service endpoint interface, one way to obtain it is to write it by hand, using the WSDL as a guide.

As an alternative to writing the interface by hand, you can pass the WSDL to the WebServicesAssembler genInterface command. The command will generate the service endpoint interface for you. This is especially convenient if the WSDL has a large number of operations that must be converted to methods.

When genInterface converts WSDL operations to Java methods, it will always make the first letter of the method name lowercase. If the original operation name in the WSDL begins with an uppercase character, this will cause a mismatch when you attempt to call methods on the proxy. Typically, a "Method does not exist" error will be returned.

To avoid this error, edit the service endpoint interface, if necessary, to ensure that method names exactly match the operation names in the WSDL, character-for-character.

Accessing the Database from a WSIF Client

The wsifDbBinding and wsifDBPort arguments add the appropriate bindings to the WSDL that allow a WSIF client to access database resources exposed as a Web service. The dataSource argument identifies the database that contains the resources.

If the dbConnection argument is used identify the database URL, then WebServicesAssembler generates its value into the WSDL file. To access the database, the WSIF client must pass the user name and password values at runtime. The generated code provides two methods to do this.

public void _setDataSourceUser(String);  
public void _setDataSourcePassword(String);  

The following are the complete paths of these methods. The CLASSNAME variable represents the value specified by the className argument. If className is not specified, it defaults to portName.

CLASSNAME.setDataSourceUser(String user);
CLASSNAME.setDataSourceUser(String password);

If the dataSource argument is specified in the command or Ant task, then these two methods are not needed. The client will already have the privileges of accessing the database.

Example 9-22 illustrates a client for the Web service assembled by the Ant task in Example 9-14. The setDataSourceUser and setDataSourcePassword methods, which pass the user name and password to the server, are highlighted in bold.

Example 9-22 Client Code to Pass a User Name and Password to the Service

WSIFServiceFactory factory = WSIFServiceFactory.newInstance();
WSIFService service = factory.getService(wsdlPath1, null, null, 
                      "http://generated.oracle/", "sqlwsif");
oracle.generated.sqlwsif stub = null;
stub = (oracle.generated.sqlwsif)
service.getStub("JavaPort", oracle.generated.sqlwsif.class);
stub.setDataSourceUser("scott");
stub.setDataSourcePassword("tiger");
System.out.println("Run Sql...");
String[] names = stub.getEname();

Adding Management Configuration to a WSIF Client

You can add a Web service management configuration for security, reliability, and auditing to a WSIF client.

A Web service management configuration on the WSIF client is useful only when it invokes a SOAP port or operation that has a matching Web service management configuration.

OracleAS Web Services does not support Web service management configuration for Java and EJB ports on the Web service side.

If a WSIF client which has a Web service management configuration communicates with a Java or an EJB port, then the Web service management configuration is ignored. The Web service management is used, however, if SOAP port is used to invoke the service.

The J2EE_HOME/config/wsif-wsm-config.xml file provides a template where you can specify outgoing management policies for the client. The wsif-wsm-config.xml file is based on the oracle-webservices-client-10_0.xsd schema.

By default, the wsif-wsm-config.xml file resides in the J2EE_HOME/config directory. If you change the name of the file or call it from another location, you can use the wsif.wsm.config.file system property to override its default name and location.

To create the management configuration and make it available to the WSIF client:

  • Edit the wsif-wsm-config.xml file in the J2EE_HOME/config directory, or

  • Use the wsif-wsm-config.xml file as a template and store it in the location of your choice. Specify the new name and location of the file with the following system property.

    -Dwsif.ws.config.file=<path to file>

Example 9-23 illustrates the contents of the wsif-wsm-config.xml file. Table 9-4 describes the elements in the file.

Example 9-23 WSIF Client Configuration File

<?xml version="1.0" encoding="UTF-8"?>
<oracle-webservice-clients xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="/oracle-webservices-client-10_0.xsd">
    <webservice-client>
        <service-qname namespaceURI="" localpart=""/>
        <port-info>
            <wsdl-port namespaceURI="" localpart=""/>
            <service-endpoint-interface></service-endpoint-interface>
            <stub-property>
                <name></name>
                <value></value>
            </stub-property>
            <call-property>
                <name></name>
                <value></value>
            </call-property>
            <runtime>
                <security>

Port-level Security configuration. For more information on security configuration elements, see the Oracle Application Server Web Services Security Guide.

                </security>
                <reliability>

Port-level Reliability configuration. See "Port Level Reliability Elements on the Client" for a description of reliability configuration elements.

                </reliability>
            </runtime>
            <operations>
                <operation name="">
                    <runtime>
                        <security>

Operation-level Security configuration. For more information on security configuration elements, see the Oracle Application Server Web Services Security Guide.

                        </security>

Operation level auditing configuration. See "Managing Auditing on the Client" for a description of auditing configuration elements.

                        <auditing/>
                        <reliability>

Operation-level reliability configuration. See "Operation Level Reliability Elements on the Client" for a description of reliability configuration elements.

                        </reliability>
                    </runtime>
                </operation>
            </operations>
        </port-info>
    </webservice-client>
</oracle-webservice-clients>

Table 9-4 describes the subelements for the <port-info> element. This element provides all of the information for a port within a service reference. You can specify either a service-endpoint-interface or wsdl-port to indicate the port that the container will use for container-managed port selection. If you specify both, then the container will use the wsdl-port value. If you do not specify wsdl-port or service-endpoint-interface, then the <port-info> property values will apply to all available ports.

The <port-info> element also contains subelements that let you specify quality of service features that are available for the port and its operations.

Table 9-4 Subelements of the <port-info> Element

Element Name Description

<wsdl-port>

Specifies the namespaceURI and localpart of a port in the WSDL that the container will use for container-managed port selection.

<service-endpoint-interface>

Specifies the fully-qualified path to the service endpoint interface of a WSDL port. The container uses this port for container-managed port selection.

<stub-property>

Defines the stub property values applicable to the port defined by the <port-info> element. The name and value subelements of <stub-property> are described in Table 9-5.

<call-property>

Defines the call property values applicable to the port defined by the <port-info> element. The name and value sub-elements of <call-property> are described in Table 9-5.

<runtime>

Contains client-side quality of service runtime information (security and/or reliability) applicable to all the operations provided by the referenced Web service. Each child element contains configuration for a specific feature.

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

The <operations> element is a subelement of the <port-info> element. For a description of <operations>, and its subelements, see "Adding OC4J-Specific Platform Information" in the Oracle Application Server Web Services Developer's Guide.


Table 9-5 describes the name and value subelements of the <stub-property> and <call-property> elements.

Table 9-5 Subelements of <stub-property> and <call-property> Elements

Element Name Description

<name>

Defines the name of any property supported by the JAX-RPC Call or Stub implementation. See the output of the Javadoc tool for the valid properties for javax.xml.rpc.Call and javax.xml.rpc.Stub.

<value>

Defines a JAX-RPC property value that should be set on a Call object or a Stub object before it is returned to the Web service client.


Adding Message Attachments in WSIF

You can enable WSIF clients to add attachments to messages.

Adding Attachments with the WSIF API

To enable a WSIF client to add an attachment to a message, follow these general steps:

  1. Create a DataHandler object to encapsulate the attachment.

  2. Use the WSIF API's WSIFOperation.createInputMessage method to create an input message on the desired operation.

  3. Use the WSIF API's WSIFMessage.setObjectPart method to add the attachment to the message.

Example 9-24 illustrates how an attachment can be added to a message by using the WSIF API. In the code fragment, the JohnDoe.jpg attachment is saved as a DataHandler object. The operationName represents the operation that will be enabled to handle messages with attachments. The WSIFOperation's createInputMessage method creates an input message on the operation. The WSIFMessage's setObjectPart method attaches the attachment to the input message with the part name myAttachment.

Example 9-24 Adding an Attachment to a Message with the WSIF API

...
DataHandler dataHandler1 = new DataHandler(new URL("file:JohnDoe.jpg"));
WSIFOperation operation = port.createOperation(operationName);
WSIFMessage input = operation.createInputMessage();
input.setObjectPart("myAttachment", dataHandler1);
...

Adding Attachments with the OracleCall API

The oracle.webservices.OracleCall API enables you to add attachments to messages that will be handled by WSIF clients. Using this technique, you save the attachment as a DataHandler object. You then add the attachment to the DII call object that you obtain from the WSIF port.

Example 9-25 illustrates how an attachment can be added to a message by using the OracleCall API. In the code fragment, the JohnDoe.jpg attachment is saved as a DataHandler object. The getCall method gets the DII call from the WSIF port. This call must be cast to a SOAP port, then to an OracleCall object. The OracleCall.addAttachment method adds the attachment to the SOAP message in the call. Note that the addAttachment method enables you to directly set the content-transfer-encoding and content-ID of the attachment MIME part.

Example 9-25 Adding an Attachment to a Message with the WSIF API

...
DataHandler dataHandler1 = new DataHandler(new URL("file:JohnDoe.jpg"));
OracleCall call = (OracleCall) ((WSIFPort_JaxRpc) port).getCall();
call.addAttachment(dataHandler1, "BASE64", "<ID1@photo>");
...

Tool Support for WSIF

The Java J2EE Web Service wizard for Java classes in JDeveloper enables you to create WSIF bindings in addition to SOAP bindings for a Web service. Enter values for the class loader and class path that let the WSIF clients locate the service implementation class. These values are comparable to the classLoader and classPath parameters on the command line or Ant task.

The Web Service wizard for EJBs enables you to specify the initial context factory, JNDI provider URL, and JNDI name so that WSIF clients can locate the EJB through JNDI. These values are comparable to the initialContextFactory, jndiProviderUrl, and jndiName parameters on the command line or Ant task.

The Database Web Service wizard enables you to specify the user, connection, and datasource information necessary for defining WSIF bindings for a PL/SQL procedure.

Limitations

See "Using the Web Service Invocation Framework".

Additional Information

For more information on: