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

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

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

10 Assembling Database Web Services

This chapter describes how you can develop Oracle Application Server Web Services that interact with an Oracle database. There are two ways in which OracleAS Web Services can interact with a database: call-in and call-out. Web service call-in refers to providing a Web service that provides access to a database resource. The Web service runs in an OC4J instance and accesses the database resource through JDBC.

Web services call-out refers to invoking an external Web service from inside the database. The invocation can be performed by SQL, PL/SQL, or Java code running in the database.

This chapter contains these sections.

Understanding Database Web Services

Web service technology enables application-to-application interaction over the Web—regardless of platform, language, or data formats. The key ingredients, including XML, SOAP, WSDL, UDDI, WS-Security, and WS-Reliability have been adopted across the entire software industry. Web service technology usually refers to services implemented and deployed in middle-tier application servers. However, in heterogeneous and disconnected environments, there is an increasing need to access stored procedures, data and metadata, through Web service interfaces. Database Web service technology is a database approach to Web services. It works in two directions:

Database Call-In

Turning the Oracle database into a Web service provider takes advantage of your investment in Java stored procedures, PL/SQL packages, Advanced Queues, pre-defined SQL queries and DML. Client applications can query and retrieve data from Oracle databases and invoke stored procedures using standard Web service protocols. There is no dependency on Oracle specific database connectivity protocols. Applications can employ any cached OC4J connection. This approach is very beneficial in heterogeneous, distributed, and non-connected environments.

Since database Web services are a part of OracleAS Web Services, they can participate in a consistent and uniform development and deployment environment. Messages exchanged between the Web service exposed database and the Web service client can take advantage of all of the management features provided by OracleAS Web Services, such as security, reliability, auditing and logging.

Figure 10-1 illustrates Web service call-in. The following steps describe the process.

  1. A request for a type of database service arrives at the application server. The service endpoint implicitly specifies the type of service requested.

  2. The OC4J JAX-RPC processing servlet references the SOAP libraries and XML parser to decode the request.

  3. The servlet passes the request to the WebServicesAssembler-generated classes that correspond to the exposed database operations. WebServicesAssembler generates these classes by silently calling Oracle JPublisher. The generated classes can represent PL/SQL packages, queries, DML, AQ Streams, or Java classes in the database.

  4. The database passes the response to the OC4J JAX-RPC processing servlet, which references the SOAP libraries and XML parser to encode it.

  5. A SOAP response formed in accordance with the WSDL is returned to the client.

See Also:

"Developing Web Services that Expose Database Resources" for more information on exposing PL/SQL packages, SQL queries, DML statements, Oracle AQ Streams, or server-side Java classes database operations as a Web service.

Figure 10-1 Web Service Calling-In to the Database

This illustration is described in the text.
Description of "Figure 10-1 Web Service Calling-In to the Database"

Database Call Out

You can extend a relational database's storage, indexing, and searching capabilities to include Web Services. By calling a Web service, the database can track, aggregate, refresh, and query dynamic data produced on-demand, such as stock prices, currency exchange rates, or weather information.An example of using the database as a service consumer would be to call an external Web service from a predefined database job to obtain inventory information from multiple suppliers, then update your local inventory database. Another example is that of a Web Crawler: a database job can be scheduled to collate product and price information from a number of sources.

Figure 10-2 illustrates database call out.

Which method to use depends on whether you want to execute from SQL or PL/SQL, from Java classes, or whether the service is known ahead of time (static invocation) or only at runtime (DII).

See Also:

"Developing a Web Service Client in the Database" for more information about the support OracleAS Web Services offers for PL/SQL and Java call-outs from the database.

Figure 10-2 Calling Web Services From Within the Database

This illustration is described in the text.
Description of "Figure 10-2 Calling Web Services From Within the Database"

Type Mapping Between SQL and XML

The following sections describe the type mappings between SQL and XML for call-ins and call-outs when the Web service is known ahead of time (static invocation).

When the Web service is known at runtime you can use only the Dynamic Invocation Interface (DII) or the UTL_DBWS PL/SQL package. For more information on using the JAX-RPC DII, see the API at the following Web address.

http://java.sun.com/j2ee/1.4/docs/#api

See Also:

Oracle Database PL/SQL Packages and Types Reference for more information on using the UTL_DBWS package.

SQL to XML Type Mappings for Web Service Call-Ins

In a database Web service call-in, a SQL operation, such as a PL/SQL stored procedure or a SQL statement, is mapped into one or more Web service operations. The parameters to the SQL operation are mapped from SQL types into XML types.

Note:

The reason there may be more than one operation is because OracleAS Web Services may be providing additional data representation choices for the SQL values in XML, such as different representations of SQL result sets.

Table 10-1 illustrates the SQL to XML mappings for Web service call-ins. The first column lists the SQL types. The second column of the table, XML Type (Literal), shows SQL-to-XML type mappings for the default literal value of the use attribute. The third column, XML Type (Encoded), shows the mappings for the encoded value of the use attribute. The literal and encoded values refer to the rules for encoding the body of a SOAP message.

See Also:

"Literal and Encoded Uses" for more information on the rules for encoding the body of a SOAP message.

Table 10-1 SQL-to-XML Type Mappings for Web Services Call-Ins

SQL Type XML Type (Literal) XML Type (Encoded)

INT

int

int

INTEGER

int

int

FLOAT

double

double

NUMBER

decimal

decimal

VARCHAR2

string

string

DATE

dateTime

dateTime

TIMESTAMP

dateTime

dateTime

BLOB

byte[]

byte[]

CLOB

String

String

LONG

String

String

RAW

byte[]

byte[]

Primitive PL/SQL indexby table

Array

Array

PL/SQL Boolean

boolean

boolean

PL/SQL indexby table

complexType

complexType

PL/SQL record

complexType

complexType

REF CURSOR

(nameBeans)

Array

Array

REF CURSOR

(nameXML)

any

text_xml

REF CURSOR

(nameXMLRowSet)

swaRef

text_xml

SQL object

complexType

complexType

SQL table

complexType

complexType

SYS.XMLTYPE

any

text_xml


Note:

If National Language Support (also known as "NLS" or "Globalization Support") characters are used in a SQL SYS.XMLTYPE value, they may not be properly handled.

A query or a PL/SQL function returning REF CURSOR will be mapped into three methods, nameBeans, nameXMLRowSet, and nameXML, where name is the name of the query or the PL/SQL function.

  • nameBeans—this method returns an array, where each element is an instance of an XSD complex type that represents one row in the cursor. A complex type subelement corresponds to a column in that row.

  • nameXMLRowSet—this method returns a swaRef or text_xml response that contains an OracleWebRowSet instance in XML format. "Working with MIME Attachments" in the Oracle Application Server Advanced Web Services Developer's Guide provides more information on the swaRef MIME format.

  • nameXML—this method returns an XML any or text_xml response that contains an Oracle XDB row set.

Both OUT and IN OUT PL/SQL parameters are mapped to IN OUT parameters in the WSDL file.

See Also:

Note that Table 10-1 provides two different mappings: one for literal and another for encoded use. The default mapping is literal. From a database Web service's perspective, there is no special reason why encoded should be used. The mapping for encoded is provided in case you encounter scenarios which call for the encoded use setting. All of the descriptions in this chapter assume that you will be using the literal use setting unless otherwise specified.

Changing the SQL to XML Mapping for Numeric Types

Table 10-1 defines SQL to XML type mappings used for call-ins. The mappings for the numeric types is determined by how Oracle JPublisher maps SQL types to Java types. By default, the WebServicesAssembler tool uses the Oracle JPublisher option -numbertypes=objectjdbc. As a result, the XML types corresponding to the SQL numeric types are all declared nillable in the generated WSDL file.

To change the Oracle JPublisher mappings, and hence change the XML types, you can use the WebServicesAssembler jpubProp argument. For example, if you specify the following argument in the database WebServicesAssembler Ant task, then the XML types generated for SQL numeric types will not be declared nillable.

jpubProp="numbertypes=jdbc"

On the other hand, if you specify either oracle or bigdecimal as the target of the numbertypes option, then the XML types generated for SQL numeric types will all be decimal and nillable.

XML to SQL Type Mapping for Web Service Call-Outs

In database Web services call-outs, XML types are mapped into SQL types. Table 10-2 lists the XML-to-SQL type mappings used in call-outs.

Table 10-2 XML-to-SQL Type Mappings for Web Services Call-Outs

XML Type SQL Type

int

NUMBER

float

NUMBER

double

NUMBER

decimal

NUMBER

dateTime

DATE

String

VARCHAR2

byte[]

RAW

complexType

SQL OBJECT

Array

SQL TABLE

text_xml

XMLType


Developing Web Services that Expose Database Resources

This section describes how to develop Web services implemented as PL/SQL stored procedures, SQL statements, Oracle Streams AQ queues, and server-side Java classes.

How to Use Life Cycle for Web Service Call-in

Creating a database Web service call-in application is a bottom up process. In many cases, you will want to reuse existing database applications (such as PL/SQL packages or Java applications) or operational scripts (such as SQL query, DML, or AQ). You can also populate the database with the resources to be exposed as a Web service. Web service call-ins typically follow these steps:

  1. Determine which database resources to expose and make them available.

    For example, you can provide the resources in any of the following ways.

    • load the PL/SQL package into the database

    • create the schema used by SQL query or DML statement Web service

    • load the Java class into the database, for a database server-side Java Web service

  2. Run the WebServicesAssembler tool to assemble the Web service, based on the specified resources.

    Note that you could also use Oracle JDeveloper to assemble the Web service.

  3. If the Web service assembly generates a PL/SQL wrapper, load it into the database.

    PL/SQL Web service assembly may generate a wrapper if a PL/SQL record or INDEX BY table type is included in the PL/SQL package. You must load the wrapper into the database. Server-side Java call-in assembly always generates a PL/SQL wrapper. WebServicesAssembler will load the wrapper automatically if the sysUser argument is set. For more information, see sysUser.

    Note that you could also use Oracle JDeveloper to load the PL/SQL wrapper into the database.

  4. Configure the OC4J data sources to ensure that the Oracle JPublisher-generated Java classes that constitute the Web service implementation can connect to the database and the resource it is exposing.

    Add a data source entry in the J2EE data source file, so that the Web service application can connect to the database.

  5. Deploy the Web service application into a running instance of OC4J.

  6. (Optional) Check that deployment succeeded. OracleAS Web Services provides a Web Service Test Page for each deployed Web service.

    See "How to Use the Web Services Test Page" for information on accessing and using the Web Service Test Page.

  7. Use the WebServicesAssembler tool to generate the Web services client proxy and incorporate it into your client application.

  8. Invoke the Web service using the client proxy.

WebServicesAssembler Support for Web Service Call-in

For all Web service call-in types, the WebServicesAssembler tool requires the following arguments.

  • dataSource—the data source JNDI name; used at runtime

  • dbConnection—the database connection URL; used at code generation time

  • dbUser—the database user and password; used at code generation time

The appName argument specifies the Web service application name. The dataSource argument defines the data source's JNDI location for the database being accessed. At runtime, the Web service code accesses the database through that data source.

The WebServicesAssembler tool uses the dbConnection and dbUser arguments to define the connection to the database during Web service creation. The values of these arguments are used at code generation time, not at runtime. The dbConnection argument is used to access the information on the resource that is to be exposed. For example, it accesses information about the PL/SQL package, the schema, or the query.

The database used at Web service creation time and the one used at runtime do not have to be the same database. However, both should include the schema that contains the database resources being exposed.

At runtime, database Web services obtain the database connection from the data source. The database Web service deals with connection loss by reconnecting to the database. When the connection is in an invalid state, the Web service will attempt to reestablish the connection. If the Web service fails to re-connect, it will return a fault. The next time the client invokes the Web service, the Web service will attempt to connect to the database. Therefore, it is possible for the Web service to return a fault at one moment, but succeed later, due to connection failure handling.

The following arguments are optional and can be used in all Web service call-in scenarios.

  • contextroot context for the web application

  • debugdisplays detailed diagnostic messages

  • earname and location of the generated EAR

  • jpubPropspecifies Oracle JPublisher options to fine-tune Oracle JPublisher code generation

  • outputlocation for storing generated files

  • portNamethe name of the port in the generated WSDL

  • serviceNamelocal part of the service name in the generated WSDL

  • stylethe style part of the message format used in the generated WSDL

  • uriURI to use for the Web service in the deployment descriptors

  • usethe use part of the message format used in the generated WSDL

The common prerequisite for all call-in types is that the database is populated with the resource to be exposed. The WebServicesAssembler employs Oracle JPublisher to generate Java code to access database resources. The jpubProp argument, which can appear more than once on the command line or in an Ant task, lets you pass options to Oracle JPublisher.

See Also:

Oracle Database JPublisher User's Guide for the list of Oracle JPublisher options and for information on how it maps PL/SQL, SQL types, SQL statements, and server-side Java into client-side Java wrappers.

How to Assemble a Web Service from a PL/SQL Package

Use the plsqlAssemble command to assemble Web services from a PL/SQL stored procedure. In the generated Web service, each Web service operation corresponds to a PL/SQL stored procedure.

This section has the following subsections:

Prerequisites

Before you begin, provide the following files and information.

  • The PL/SQL package that you want to expose as a Web service

    See Also:

    "Sample PL/SQL Package" for the stored procedure that is used in this example.

  • A name for the Web service application

  • A JNDI location for the JDBC data source

  • The JDBC database connection URL, and the username and password

Steps for Assembling a Web Service from a PL/SQL Package

The following steps describe how to assemble a Web service for the PL/SQL package echo_plsql.

  1. Provide the PL/SQL package and the information described in the Prerequisites section as input to the WebServicesAssembler plsqlAssemble command.

    Command line:

    java -jar wsa.jar 
        -plsqlAssemble 
        -appName Echo 
        -sql echo_plsql 
        -dataSource jdbc/OracleManagedDS 
        -dbConnection jdbc:oracle:thin:@stacd15:1521:lsqlj 
        -dbUser scott/tiger
        -style rpc 
        -use encoded
    

    Ant task:

    <oracle:plsqlAssemble
        dbUser="scott/tiger"
        sql="echo_plsql"
        dbConnection="jdbc:oracle:thin:@stacd15:1521:1sqlj"
        dataSource="jdbc/OracleManagedDS"
        appName="EchoPlsql"
        style="rpc"
        use="encoded"
    />
    

    In this command and Ant task:

    • plsqlAssemble—Generates Web services from a PL/SQL package containing stored procedures and functions. To use this command, you must connect to a database. See "plsqlAssemble".

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

    • sql—Specifies a PL/SQL package name. See "sql".

    • dataSource—Specifies the JNDI location of the data source used by the Web services at runtime. See "dataSource".

    • dbConnection—Specifies the JDBC URL for the database. See "dbConnection".

    • dbUser—Specifies the database schema and password in the form of user/password. See "dbUser".

    • style—For bottom up Web service assembly, this argument specifies the style attribute of the message format in the generated WSDL. See "style".

    • use—For bottom up Web service assembly, this argument specifies the use attribute of the message format in the generated WSDL. See "use".

    The arguments that can be used with the plsqlAssemble command are described in "plsqlAssemble".

    By default, WebServicesAssembler generates services using document-wrapped style. However, JAX-RPC clients that use document-wrapped style do not support IN OUT parameters directly. Instead, WebServicesAssembler packages IN and IN OUT parameters separately. Since the PL/SQL package used in this example contains IN OUT parameters, the plsqlAssemble command includes the -style rpc argument. For more information on parameters and different document styles, see "How to Access PL/SQL IN and IN OUT Parameters from Client Code".

    The command generates a Web service application, EchoPlsql.ear, and optionally, the following PL/SQL scripts.

    • Echo_plsql_wrapper.sql—the PL/SQL wrapper generated to support PL/SQL record and INDEX BY table.

    • Echo_plsql_dropper.sql—the PL/SQL script to tear down the types and packages created by the wrapper script.

  2. Install any PL/SQL wrappers created during Web service generation into the database.

    Not all PL/SQL Web services assembly generates PL/SQL wrappers. If it does, you must load them into the appropriate user schema in the database before running the Web service.

    The wrappers can be loaded automatically or manually. To load the wrappers automatically, add the following line to the plsqlAssemble command:

    -jpubProp plsqload (for the command line), or

    jpubprop="plsqlload" (for an Ant task)

    To manually load the wrapper package after Web service assembly, use SQL*PLUS. The following command line provides a sample SQL*PLUS command to load a wrapper package.

    SQL>@Echo_plsql_wrapper.sql
    
  3. Deploy the service into a running instance of OC4J and bind the application.

    The data source referenced by the -dataSource argument in Step 1 must be set up in this OC4J instance.

    The following command lines provide sample deployment and bind commands.

    % java –jar <J2EE_HOME>/admin_client.jar deployer:oc4j:localhost:port admin welcome –deploy -file dist/echo.ear –deploymentName echo
    
    % java –jar <J2EE_HOME>/admin_client.jar deployer:oc4j:localhost:port admin welcome –bindWebApp plsql plsql-web default-web-site /plsql
    

    In this example, <J2EE_HOME> is the directory where J2EE is installed.

    For more information on deploying EAR files, see the Oracle Containers for J2EE Deployment Guide.

  4. (Optional) Check that deployment succeeded.

    OracleAS Web Services provides a Web Service Test Page for each deployed Web service. See "How to Use the Web Services Test Page" for information on accessing and using the Web Service Test Page.

  5. Generate the client-side code.

    • For the J2SE environment, generate stubs (client proxies) for a J2SE Web service client by running the WebServicesAssembler tool with the genProxy command. See Chapter 15, "Assembling a J2SE Web Service Client" for more information on generating and assembling client-side code for the J2SE environment.

    • For the J2EE environment, generate a service endpoint interface and a JAX-RPC mapping file for a J2EE Web service client by running the WebServicesAssembler tool with the genInterface command. See Chapter 14, "Assembling a J2EE Web Service Client" for more information on generating and assembling client-side code.

    For example, the following command uses the genProxy command to generate a J2SE client in the build/classes/client directory.

    % java –jar wsa.jar –genProxy 
                        –wsdl http://locahost:8888/plsql/echo?WSDL 
                        -output build/src/client 
                        –mappingFileName ./mapping.xml 
                        –packageName oracle.demo.db.plsql.stub 
                        -unwrapParameters true
    

    In this command:

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

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

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

    • mappingFileName—Specifies a file location that points to a JAX-RPC mapping file. See "mappingFileName".

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

    • unwrapParameters—This argument can be set only for document-literal operations and will be ignored for other message formats. When unwrapParameters is set to true, which is the default, the return type and response type will be unwrapped. This is usually easier to use, especially if the types are simple. See "unwrapParameters".

  6. Compile and run the client.

    List the appropriate JARs on the classpath before compiling the client. Table A-2, "Classpath Components for a Client Using a Client-Side Proxy" lists all of the JAR files that can possibly be used on the client classpath. As an alternative to listing individual JARs, you can include the client-side JAR, wsclient_extended.jar on the client classpath. This JAR file contains all the classes necessary to compile and run a Web service client. The classes are from the individual JAR files listed in Table A-2. See "Setting the Classpath for a Web Service Proxy" for more information on wsclient_extended.jar and the client classpath.

    The following command line provides sample compile and run commands.

    % javac –classpath path:
             <ORACLE_HOME>/webservices/lib/wsclient_extended.jar:
             :<ORACLE_HOME>/webservices/lib/jaxrpc-api.jar EchoClient.java
    
    % java -classpath path:
           <ORACLE_HOME>/webservices/lib/wsclient_extended.jar:
           <ORACLE_HOME>/webservices/lib/jaxrpc-api.jar:
           <J2EE_HOME>/lib/jax-qname-namespace.jar:
           <J2EE_HOME>/lib/activation.jar:
           <J2EE_HOME>/lib/mail.jar:
           <J2EE_HOME>/lib/http_client.jar:
           <ORACLE_HOME>/lib/xmlparserv2.jar EchoClient
    

    In this example, <J2EE_HOME> is the directory where J2EE is installed, <ORACLE_HOME> is the directory where OracleAS Web Services is installed.

Sample PL/SQL Package

Example 10-1 illustrates a PL/SQL package in the database that can be exposed as a Web service. The package contains procedures and functions that exercise various SQL and PL/SQL data types.

Example 10-1 Sample PL/SQL Package

create or replace type address as object( 
     street varchar2(30), city varchar2(30), state varchar2(2), zip varchar2(5));
create or replace type employee as object (eid int, efirstname varchar(30),
     elastname varchar(30), addr address, salary float);
create table employees (eid int, emp employee);
create table employee_espp (eid int, status int);
create table employee_accounts (eid int, accounts sys.xmltype);
create table employee_biodata (eid int, biodata CLOB);
create table employee_image (eid int, image BLOB);
create table employee_hiredate(eid int, hiredate TIMESTAMP);
                                                              
create or replace package echo_plsql as
procedure set_object (emp IN employee);
function get_object1(id IN int) return employee;
function get_object2(id IN int) return address;
function hold_varchar(id IN int, firstname OUT varchar2, lastname OUT varchar2) return float;
procedure set_boolean(id IN int , status IN boolean);
function get_boolean(id IN int) return boolean;
procedure hold_float_inout(id IN int, newsalary IN OUT float);
procedure clear_object (id IN int);
procedure set_clob (id int, biodata IN CLOB);
function get_clob(id IN int) return CLOB;
procedure set_blob(id int, image IN BLOB);
function get_blob(id IN int) return BLOB;
procedure set_xmltype(id IN number, accounts sys.xmltype);
function get_xmltype(id IN number) return sys.xmltype;
procedure set_date(id IN int, hiredate IN TIMESTAMP);
function get_date(id IN int) return TIMESTAMP;
TYPE rec is RECORD (emp_id int, manager_id int);
TYPE index_tbl is TABLE OF rec INDEX BY BINARY_INTEGER;
function echo_rec(mrec rec) return rec;
function echo_index_tbl(mtbl index_tbl) return index_tbl;
end echo_plsql;

How PL/SQL Function Names are Mapped to Web Service Operation Names

WebServicesAssembler maps PL/SQL functions or procedures into Web service operations, often with adjusted names. Typically, the underscore in a PL/SQL name is removed and the letter following the underscore is capitalized. For example, notice the PL/SQL function echo_index_tbl in Example 10-1. This function is mapped into the Web service operation echoIndexTbl. The WSDL fragment in Example 10-2 shows how the PL/SQL function echo_index_tbl is expressed as the echoIndexTbl Web service operation.

Example 10-2 WSDL Fragment, Illustrating the Mapping of a PL/SQL Function

<operation name="echoIndexTbl" parameterOrder="EchobaseIndexTblBase_1">
<input message="tns:Echo_echoIndexTbl"/>
<output message="tns:Echo_echoIndexTblResponse"/>
</operation>

How to Access PL/SQL IN and IN OUT Parameters from Client Code

The PL/SQL parameters OUT and IN OUT in Example 10-1 are represented as XML IN OUT parameters, as shown by the holder parameters of holdVarchar. The entries in the WSDL fragment in Example 10-3 illustrate the holdVarchar operation. The second and third parameters appear in both the input and output messages, which indicates that both parameters are IN OUT parameters.

Example 10-3 WSDL Fragment, Illustrating IN OUT Parameters

<operation name="holdVarchar"
   parameterOrder="Integer_1 String_2 String_3">
  <input message="tns:Echo_holdVarchar"/>
  <output message="tns:Echo_holdVarcharResponse"/>
</operation>
<message name="Echo_holdVarchar">
<part name="Integer_1" type="xsd:int"/>
<part name="String_2" type="xsd:string"/>
<part name="String_3" type="xsd:string"/>
</message> 
<message name="Echo_holdVarcharResponse">
<part name="result" type="ns1:double"/>
<part name="String_2" type="xsd:string"/>
<part name="String_3" type="xsd:string"/>
</message>

To access the IN OUT parameters in JAX-RPC client code, you must use JAX-RPC holders. For example, the code in Example 10-4 retrieves the returned values as firstName.value and lastName.value, where firstName and lastName are both String holders. The actual values in the holders are accessed by the member value, as shown in the println statement.

Example 10-4 Accessing IN OUT Parameters in Client Code by Using JAX-RPC Holders

System.out.println("holdVarchar");
StringHolder firstName = new StringHolder("Tom");
StringHolder lastName = new StringHolder("Gordon");
System.out.println("Holder returned:  empid="
+ ci.holdVarchar(id, firstName, lastName)
+ ", name="
+ firstName.value
+ "."
+ lastName.value);

Note that the plsqlAssemble command line specified -style rpc. The RPC style supports holders. The default document-wrapped style does not support holders.

If the Web service had been created with the default document-wrapped style, then a different holdVarchar signature would have been generated. The OUT arguments would be captured as attributes on the return value.

The following WSDL segment shows the holdVarchar operation in the document-wrapped style. In the return type, EchoUser_holdVarchar_Out, the attributes lastnameOut and firstnameOut record the OUT value of the PL/SQL parameters firstname and lastname.

Example 10-5 WSDL Fragment, Illustrating IN OUT Parameters Handled in Document-Wrapped Style

<operation name="holdVarchar" parameterOrder="Integer_1">
            <input message="tns:Echo_holdVarchar"/>
            <output message="tns:Echo_holdVarcharResponse"/>
 </operation>
 
<message name="Echo_holdVarchar">
  <part name="Integer_1" type="xsd:int"/>
</message>
<message name="Echo_holdVarcharResponse">
  <part name="result" type="tns:Echo_holdVarchar_Out"/>
</message>
 
<complexType name="Echo_holdVarchar_Out">
     <sequence>
         <element name="return" type="double" nillable="true"/>
        <element name="lastnameOut" type="string" nillable="true"/>
         <element name="firstnameOut" type="string" nillable="true"/>
     </sequence>
</complexType>

How to Access SQL XMLType Types from Client Code

The SQL XMLType in Example 10-1 is mapped into the XML any type. The getXmltype operation in the WSDL fragment in Example 10-6 illustrates this mapping.

Example 10-6 WSDL Fragment, Illustrating the Mapping of SQL XMLType into text_xml

<message name="Echo_getXmltypeResponse">
<part name="result" type="ns2:any"/>
</message>
<operation name="getXmltype" parameterOrder="BigDecimal_1">
<input message="tns:Echo_getXmltype"/>
<output message="tns:Echo_getXmltypeResponse"/>
</operation>

WebServicesAssembler generates a proxy that maps XML any to the Java type org.w3c.org.dom.Element. Therefore, a Java client accesses a SQL XMLType instance as an Element instance.

How to Assemble a Web Service from a SQL Query or DML Statement

Use the sqlAssemble command to generate Web services from a SQL statement. The statement can include SQL queries and DML (Data Manipulation Language) statements.

Unlike PL/SQL Web services generation, SQL statement assembly does not generate PL/SQL wrappers. PL/SQL wrappers are generated only to handle PL/SQL record or INDEX BY table types. These types cannot be used in a SQL statement.

This section contains the following subsections:

Prerequisites

Before you begin, provide the following files and information.

  • The SQL statements or queries. Example 10-7, "Sample SQL Statements" illustrates the SQL statements used in the following example.

    Multiple sqlstatement arguments can be specified on the command line or Ant task. For information on the format of the sqlstatement argument, see "sqlstatement".

  • A name for the Web service application.

  • The JNDI location of the JDBC data source. This information is used at runtime.

  • The JDBC database connection URL. This information is used at compile time.

  • The name and password of the schema which the query or statement is based on. This information is used at compile time.

Steps for Assembling a Web Service from a SQL Statement or Query

The following steps use the sqlAssemble command to assemble a Web service for the queries and statements on the SCOTT schema.

  1. Provide the SQL statements or query, the name and password for the database that they are based on, and the other information described in the Prerequisites section as input to the WebServicesAssembler sqlAssemble command.

    For example, the following command generates the Web service application query.ear.

    Command line:

    java -jar wsa.jar -sqlAssemble
       -appName query
       -dataSource jdbc/OracleManagedDS
       -sqlstatement "getEmpCount=select ename, sal from emp where 
                          sal>:{mysal NUMBER}" 
       -sqlstatement "getEmpBySal=select ename, sal from emp where 
                          sal>:{mysal NUMBER}"
       -sqlstatement "updateEmp=update emp SET sal=sal+500 where 
                          ename=:{myname VARCHAR}"
       -dbConnection jdbc:oracle:thin:@stacd15:1521:lsqlj
       -dbUser scott/tiger
    

    Ant task:

    <oracle:sqlAssemble
            appName="query"
            dataSource="jdbc/OracleManagedDS"
            dbConnection="jdbc:oracle:thin:@dsunrde22:1521:sqlj"
            dbUser="scott/tiger">
            <sqlstatement="getEmpCount=select ename, sal from emp where sal>:{mysal NUMBER}"/>
            <sqlstatement="getEmpBySal=select ename, sal from emp where sal>:{mysal NUMBER}"/>
            <sqlstatement="updateEmp=update emp SET sal=sal+500 where  ename=:{myname VARCHAR}"/>
    />
    

    In this command and Ant task:

    • sqlAssemble—Generates Web services from SQL statements, including SQL queries and DMLs (Data Manipulation Language). To use this command, you must connect to a database. See "sqlAssemble".

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

    • dataSource—Specifies the JNDI location of the data source used by the Web services at runtime. See "dataSource".

    • dbConnection—Specifies the JDBC URL for the database. See "dbConnection".

    • dbUser—Specifies the database schema and password in the form of user/password. See "dbUser".

    • sqlStatement—Specifies the DML statement or SQL query to be published as a Web service. See "sqlstatement".

  2. Deploy the service into a running instance of OC4J and bind the application.

    The data source referenced in the dataSource argument must have been set up for this OC4J instance.

    The following command lines provide sample deployment and bind commands.

    % java –jar <J2EE_HOME>/admin_client.jar deployer:oc4j:localhost:port admin welcome –deploy -file dist/query.ear –deploymentName query
    
    % java –jar <J2EE_HOME>/admin_client.jar deployer:oc4j:localhost:port admin welcome –bindWebApp plsql plsql-web default-web-site /query
    

    In these sample command lines, <J2EE_HOME> is the directory where J2EE is installed.

    For more information on deploying EAR files, see the Oracle Containers for J2EE Deployment Guide.

  3. (Optional) Check that deployment succeeded. OracleAS Web Services provides a Web Service Test Page for each deployed Web service. See "How to Use the Web Services Test Page" for information on accessing and using the Web Service Test Page.

  4. Generate the client-side code.

    • For the J2SE environment, generate stubs (client proxies) for a J2SE Web service client by running the WebServicesAssembler tool with the genProxy command. For more information on generating and assembling client-side code for the J2SE environment, see Chapter 15, "Assembling a J2SE Web Service Client".

    • For the J2EE environment, generate a service endpoint interface and a JAX-RPC mapping file for a J2EE Web service client by running the WebServicesAssembler tool with the genInterface command. For more information on generating and assembling client-side code, see Chapter 14, "Assembling a J2EE Web Service Client".

    For example, the following command uses genProxy to generate code for a J2SE client.

    % java –jar wsa.jar –genProxy 
                        –wsdl http://locahost:8888/query/query?WSDL 
                        -output build/src/client 
                        –mappingFileName ./mapping.xml 
                        –packageName oracle.demo.db.query.stub 
                        -unwrapParameters true
    

    The command generates the client in the build/src/client directory.

    In this command:

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

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

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

    • mappingFileName—Specifies a file location that points to a JAX-RPC mapping file. See "mappingFileName".

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

    • unwrapParameters—This argument can be set only for document-literal operations and will be ignored for other message formats. When unwrapParameters is set to true, which is the default, the return type and response type will be unwrapped. This is usually easier to use, especially if the types are simple. See "unwrapParameters".

  5. Compile and run the client.

    List the appropriate JARs on the classpath before compiling the client. Table A-2, "Classpath Components for a Client Using a Client-Side Proxy" lists all of the JAR files that can possibly be used on the client classpath. As an alternative to listing individual JARs, you can include the client-side JAR, wsclient_extended.jar on the client classpath. This JAR file contains all the classes necessary to compile and run a Web service client. The classes are from the individual JAR files listed in Table A-2. See "Setting the Classpath for a Web Service Proxy" for more information on wsclient_extended.jar and the client classpath.

    The following command lines provide sample compile and run commands.

    % javac –classpath path:
         <ORACLE_HOME>/webservices/lib/wsclient_extended.jar: 
         :<ORACLE_HOME>/webservices/lib/jaxrpc-api.jar QueryClient.java
     
    % java -classpath path
         <ORACLE_HOME>/webservices/lib/wsclient_extended.jar:
         <ORACLE_HOME>/webservices/lib/jaxrpc-api.jar:
         <J2EE_HOME>/lib/jax-qname-namespace.jar:
         <J2EE_HOME>/lib/activation.jar:
         <J2EE_HOME>/lib/mail.jar:
         <J2EE_HOME>/lib/http_client.jar:
         <ORACLE_HOME>/webservices/lib/commons-logging.jar:
         <ORACLE_HOME>/lib/xmlparserv2.jar QueryClient 
    

In this example, <J2EE_HOME> is the directory where J2EE is installed; <ORACLE_HOME> is the directory where the OC4J is installed.

Sample SQL Statements

Example 10-7 illustrates the definitions of the SQL statements that are exposed as a Web service.

Example 10-7 Sample SQL Statements

getEmpCount=select ename, sal from emp where sal>:{mysal NUMBER}
getEmpBySal=select ename, sal from emp where sal>:{mysal NUMBER}
updateEmp=update emp SET sal=sal+500 where  ename=:{myname VARCHAR}

How SQL Queries are Mapped to Web Service Operations

A SQL query, when exposed as a Web service, is mapped to three service operations. For example, the getEmpBySal query in Example 10-7 generates these service operations.

  • getEmpBySalBeans—returns an array. The array element is an object type with attributes corresponding to the columns in the row of the query result.

  • getEmpBySalXMLRowSet—returns an XML document with the query result in the WebRowSet format.

  • getEmpBySalXML—returns an XML document with the query result in Oracle XDB rowset format.

Providing three operations from one query is a convenience. The return values differ only in format. Note the naming convention is to attach Beans, XMLRowSet, and XML to the original query name.

The WSDL fragment in Example 10-8 describes the return types of the three operations in the WSDL file.

Example 10-8 WSDL Fragment, Illustrating Service Operations for a SQL Query

<complexType name="getEmpBySalBeansResponse">
<sequence>
<element name="result" type="tns:Query_getEmpBySalRowUser" nillable="true"
     minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
<complexType name="Query_getEmpBySalRowUser">
<sequence>
<element name="ename" type="string" nillable="true"/>
<element name="sal" type="decimal" nillable="true"/>
</sequence>
</complexType>

<complexType name="getEmpBySalXMLRowSetResponse">
<sequence>
<element name="result" type="ns1:swaRef" nillable="true"/>
</sequence>
</complexType>
 
<complexType name="getEmpBySalXMLResponse">
<sequence>
<element name="result" type="xsd:any" nillable="true"/>
</sequence>
</complexType>

Two of the methods, getEmpBySalXMLRowSetResponse and getEmpBySalXMLResponse, have parameters of swaRef type. For this type, the assembler generates javax.xml.soap.AttachmentPart in the client proxy. Example 10-9 illustrates the client code to access the returned query result.

Example 10-9 Accessing Returned Query Results from a swaRef Type in Client Code

import oracle.jdbc.pool.OracleDataSource;
import oracle.jdbc.rowset.OracleWebRowSet;
import javax.xml.soap.AttachmentPart;
import org.w3c.org.Element;
import javax.xml.transform.dom.*;
import java.io.*;
   ...
 
/* Access the query result as Oracle XDB RowSet */
Element element = eme.getEmpBySalXML(new BigDecimal(500));
DOMSource doms = new javax.xml.transform.doc.DOMSource(element);
buf = new jav.io.ByteArrayOutputStream();
StreamResult streamr = new StreamResult(buf);
trnas.transform(doms, streamr);
System.out.println(buf, toString());


/* Access the query result as Oracle WebRowSet */
ap = eme.getEmpBySalXMLRowSet(new BigDecimal(500));
source = (Source) ap.getContent();
trans = TransformerFactory.newInstance().newTransformer();
buf = new ByteArrayOutputStream();
streamr = new StreamResult(buf);
trans.transform(source, streamr);
InputStream istream = new ByteArrayInputStream(buf.toString().getBytes());
OracleWebRowSet rowset = new OracleWebRowSet();
System.setProperty("http.proxyHost", "www-proxy.us.oracle.com");
System.setProperty("http.proxyPort", "80");
         System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "oracle.xml.jaxp.JXDocumentBuilderFactory");
rowset.readXml(new InputStreamReader(istream));
rowset.writeXml(new PrintWriter(System.out));

The code in Example 10-9 emits the query result in two formats: Oracle XDB row set (ROWSET) and Oracle Web row set (OracleWebRowSet). Example 10-10 shows the query result as an Oracle XDB row set. Example 10-11 prints the result in WebRowSet format. In practice, you can access the variable rowset OracleWebRowSet instance in Example 10-9 using oracle.jdbc.rowset.OracleWebRowSet APIs.

See Also:

Oracle Database JDBC Developer's Guide and Reference for more information on these data types.

Example 10-10 Query Results as an Oracle XDB Row Set

<ROWSET>
<ROW num="1">
<ENAME>SMITH</ENAME><SAL>800</SAL>
</ROW>
<ROW num="2">
<ENAME>ALLEN</ENAME><SAL>1600</SAL>
</ROW>
<ROW num="3">
<ENAME>WARD</ENAME><SAL>1250</SAL>
</ROW>
</ROWSET>

Example 10-11 Query Results as a JDBC Web Row Set

<?xml version="1.0" encoding="UTF-8"?>
 <webRowSet xmlns="http://java.sun.com/xml/ns/jdbc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/jdbc http://java.sun.com/xml/ns/jdbc/webrowset.xsd">
   <properties>
<command></command>
<concurrency>1007</concurrency>
<datasource></datasource>
<escape-processing>true</escape-processing>
<fetch-direction>1002</fetch-direction>
<fetch-size>10</fetch-size>
<isolation-level>2</isolation-level>
<key-columns>
</key-columns>
<map>
</map>
<max-field-size>0</max-field-size>
<max-rows>0</max-rows>
<query-timeout>0</query-timeout>
<read-only>false</read-only><rowset-type>1005</rowset-type>
<show-deleted>false</show-deleted>
<table-name></table-name>
<url>jdbc:oracle:thin:@stacd15:1521:lsqlj1</url>
<sync-provider>
  <sync-provider-name>com.sun.rowset.providers.RIOptimisticProvider</sync-provider-name>
  <sync-provider-vendor>Sun Microsystems Inc.</sync-provider-vendor>
  <sync-provider-version>1.0</sync-provider-version>
  <sync-provider-grade>2</sync-provider-grade>
  <data-source-lock>1</data-source-lock>
</sync-provider>
   </properties>
   <metadata>
<column-count>2</column-count>
<column-definition>
  <column-index>1</column-index>
  <auto-increment>false</auto-increment>
  <case-sensitive>true</case-sensitive>
  <currency>false</currency>
  <nullable>1</nullable>
  <signed>true</signed>
  <searchable>true</searchable>
  <column-display-size>10</column-display-size>
  <column-label>ENAME</column-label>
  <column-name>ENAME</column-name>
  <schema-name></schema-name>
  <column-precision>0</column-precision>
  <column-scale>0</column-scale>
  <table-name></table-name>
  <catalog-name></catalog-name>
  <column-type>12</column-type>
  <column-type-name>VARCHAR2</column-type-name>
               </column-definition>
 
<column-definition>
  <column-index>2</column-index>
  <auto-increment>false</auto-increment>
  <case-sensitive>true</case-sensitive>
  <currency>false</currency>
  <nullable>1</nullable>
  <signed>true</signed>
  <searchable>true</searchable>
  <column-display-size>10</column-display-size>
  <column-label>SAL</column-label>
  <column-name>SAL</column-name>
  <schema-name></schema-name>
  <column-precision>0</column-precision>
  <column-scale>0</column-scale>
  <table-name></table-name>
  <catalog-name></catalog-name>
  <column-type>2</column-type>
  <column-type-name>NUMBER</column-type-name>
</column-definition>
   </metadata>
   <data>
<currentRow>
  <columnValue>SMITH</columnValue>
              <columnValue>800</columnValue>
</currentRow>
<currentRow>
  <columnValue>ALLEN</columnValue>
             <columnValue>1600</columnValue>
     </currentRow>
     <currentRow>
       <columnValue>WARD</columnValue>
             <columnValue>1250</columnValue>
     </currentRow>
   </data>
 </webRowSet> 

How DML Operations are Mapped to Web Service Operations

A DML statement is an UPDATE, DELETE, or INSERT SQL statement. The sqlAssemble command can expose DML statements into operations in a Web Service. DML operations are automatically committed when successful and automatically rolled back when they are not.

Example 10-12 illustrates a WSDL fragment that exposes the DML statement in Example 10-7:

updateEmp=update emp SET sal=sal+500 where ename=:{myname VARCHAR}

The DML statement is exposed as two operations. In this example, updateEmp executes the statement; updateEmpiS executes it in batch mode. The batched operation takes an array for each original DML argument. Each element in the array is used for one execution in the batch. The result of a batched operation reflects the total number of rows updated by the batch.

Example 10-12 WSDL Fragment, Illustrating the Response Type of a DML Operation

<message name="SqlStmts_updateEmp">
      <part name="salary" type="xsd:string"/>
  </message>
  <message name="SqlStmts_updateSchemaResponse">
      <part name="result" type="xsd:int"/>
  </message>
  <message name="SqlStmts_updateEmpiS">
      <part name="salary" type="tns:ArrayOfstring"/>
  </message>
  <message name="SqlStmts_updateEmpiSResponse">
      <part name="result" type="xsd:int"/>
  </message>

How to Assemble a Web Service from an Oracle Streams AQ

Oracle Streams Advanced Queuing is an asynchronous messaging system provided by Oracle databases. By exposing an Advanced Queue (AQ) as a Web service, the client can send a message to a receiver inside the database, or eventually, to another client of the same Web service.

The WebServicesAssembler tool can generate a Web service from an AQ existing in a database. An AQ can have a single consumer or multiple consumers. A single consumer is often referred to as a queue. A multiple consumer AQ is often referred to as a topic. Each Oracle Streams AQ belongs to a queue table, which defines the payload type of all its AQs, and whether the AQs support only queues or topics. The generated Java code employs the Oracle Streams AQ JMS APIs.

Example 10-14 and Example 10-15 illustrate the Web service operations that the WebServicesAssembler exposes for a queue and a topic, respectively. The assembler creates the operations based on Oracle Streams AQ and AQ JMS APIs.

This section has the following subsections:

See Also:

Oracle Streams Advanced Queuing Java API Reference for information regarding Oracle Streams AQ and AQ JMS APIs.

Prerequisites

Before you begin, provide the following files and information.

  • A database connection URL to the database where the AQ resides. As an alternative to JDBC, WebServicesAssembler gives you the flexibility of using a JMS queue instance to access an Oracle AQ. For more information, see "How to Access an Oracle AQ Queue with JMS".

  • The name of the schema where the AQ resides and the user name and password to access it. This is used at compile time.

  • The name of the queue or topic that you want to expose as a Web service. You can publish only a single queue or topic to be exposed by a Web service. See "Sample AQ Queue and Topic Declaration" for a sample queue and topic.

  • A name for the Web service application.

  • The data source JNDI name. This information is used at runtime.

Steps for Assembling a Web Service from an Oracle AQ

The following steps describe how to use WebServicesAssembler to assemble a Web service from an Oracle AQ queue.

  1. Provide the files and other information described in the Prerequisites section as input to WebServicesAssembler -aqAssemble command.

    For example, the following command creates a Web service application with the queue.ear file generated in the current directory. The WebServicesAssembler tool generates Java files to access the queue at runtime. "Sample AQ Queue and Topic Declaration" illustrates the AQ sample_queue declaration.

    Command line:

    java -jar $ORACLE_HOME/webservices/lib/wsa.jar 
      -aqAssemble 
      -appName queue 
      -dataSource jdbc/OracleManagedDS 
      -portName assembleQueuePort
      -sql sample_queue 
      -dbConnection jdbc:oracle:thin:@stacd15:1521:lsqlj 
      -dbUser scott/tiger
    

    Ant task:

    <aqAssemble
       appName="queue"
       dataSource="jdbc/OracleManagedDS"
       sql="sample_queue"
       portName="assembleQueuePort"
       dbConnection="jdbc:oracle:thin:@stacd15:1521:lsqlj"
       dbUser="scott/tiger"
    />
    

    You can publish the sample topic in the declaration, sample_topic, in the same way as sample_queue (but in a different WebServicesAssembler invocation). The only difference would be the values for sql and appName arguments in the aqAssemble command.

    In this command and Ant task:

    • aqAssemble—Generate Web services from an advanced queue in the database. To use this command, you must connect to a database. See "aqAssemble".

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

    • dataSource—Specifies the JNDI location of the data source used by the Web services at runtime. See "dataSource".

    • portName—See "portName".

    • sql—Specifies a PL/SQL package name. See "sql".

    • dbConnection—Specifies the JDBC URL for the database. See "dbConnection".

    • dbUser—Specifies the database schema and password in the form of user/password. See "dbUser".

  2. Deploy the service into a running instance of OC4J and bind the application.

    This step assumes that the AQ has been set up as a data source in the OC4J instance.

    The following command lines provide sample deployment and bind commands.

    % java –jar <J2EE_HOME>/admin_client.jar deployer:oc4j:localhost:port admin welcome –deploy -file dist/queue.ear –deploymentName queue
    
    % java –jar <J2EE_HOME>/admin_client.jar deployer:oc4j:localhost:port admin welcome –bindWebApp queue queue-web default-web-site /queue
    

    In this example, <J2EE_HOME> is the directory where J2EE is installed.

    For more information on deploying EAR files, see the Oracle Containers for J2EE Deployment Guide.

  3. (Optional) Check that deployment succeeded.

    OracleAS Web Services provides a Web Service Test Page for each deployed Web service. See "How to Use the Web Services Test Page" for information on accessing and using the Web Service Test Page.

  4. Generate the client-side code.

    • For the J2SE environment, generate stubs (client proxies) for a J2SE Web service client by running the WebServicesAssembler tool with the genProxy command. For more information on generating and assembling client-side code for the J2SE environment, see Chapter 15, "Assembling a J2SE Web Service Client".

    • For the J2EE environment, generate a service endpoint interface and a JAX-RPC mapping file for a J2EE Web service client by running the WebServicesAssembler tool with the genInterface command. For more information on generating and assembling client-side code, see Chapter 14, "Assembling a J2EE Web Service Client".

    For example, the following command uses genProxy to generate code for a J2SE client.

    % java –jar wsa.jar –genProxy 
                        –wsdl http://locahost:8888/queue/queue?WSDL 
                        -output build/src/client 
                        –mappingFileName ./mapping.xml 
                        –packageName oracle.demo.db.queue.stub 
                        -unwrapParameters true
    

    In this command:

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

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

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

    • mappingFileName—Specifies a file location that points to a JAX-RPC mapping file. See "mappingFileName".

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

    • unwrapParameters—This argument can be set only for document-literal operations and will be ignored for other message formats. When unwrapParameters is set to true, which is the default, the return type and response type will be unwrapped. This is usually easier to use, especially if the types are simple. See "unwrapParameters".

  5. Compile and run the client.

    List the appropriate JARs on the classpath before compiling the client. Table A-2, "Classpath Components for a Client Using a Client-Side Proxy" lists all of the JAR files that can possibly be used on the client classpath. As an alternative to listing individual JARs, you can include the client-side JAR, wsclient_extended.jar on the client classpath. This JAR file contains all the classes necessary to compile and run a Web service client. The classes are from the individual JAR files listed in Table A-2. See "Setting the Classpath for a Web Service Proxy" for more information on wsclient_extended.jar and the client classpath.

    The following command lines provide sample compile and run commands.

    % javac –classpath path
    <ORACLE_HOME>/webservices/lib/wsclient_extended.jar: 
    :<ORACLE_HOME>/webservices/lib/jaxrpc-api.jar QueueClient.java
     
    % java -classpath path
    <ORACLE_HOME>/webservices/lib/wsclient_extended.jar:
    <ORACLE_HOME>/webservices/lib/jaxrpc-api.jar:
    <J2EE_HOME>/lib/jax-qname-namespace.jar:
    <J2EE_HOME>/lib/activation.jar:<J2EE_HOME>/lib/mail.jar:
    <J2EE_HOME>/lib/http_client.jar:
    <ORACLE_HOME>/webservices/lib/commons-logging.jar:
    <ORACLE_HOME>/lib/xmlparserv2.jar QueueClient
    

In this example, <J2EE_HOME> is the directory where J2EE is installed; <ORACLE_HOME> is the directory where OracleAS Web Services is installed.

Sample AQ Queue and Topic Declaration

The PL/SQL script in Example 10-13 defines a queue, sample_queue, and a topic, sample_topic. The queue payload type is queue_message, a SQL object type. The topic payload type is topic_message, also a SQL object type.

Example 10-13 Sample Queue and Topic Declaration

create type scott.queue_message as object (
   Subject                VARCHAR2(30),
   Text                   VARCHAR2(80));
create type scott.topic_message as object (
   Subject                VARCHAR2(30),
   Text                   VARCHAR2(80));
BEGIN
  dbms_aqadm.create_queue_table (
           Queue_table            => 'scott.queue_queue_table',
           Queue_payload_type     => 'scott.queue_message');
  dbms_aqadm.create_queue(
    queue_name  => 'scott.sample_queue',
    queue_table => 'scott.queue_queue_table' );
  dbms_aqadm.start_queue(queue_name => 'scott.sample_queue');
 
  dbms_aqadm.create_queue_table (
    Queue_table            => 'scott.topic_queue_table',
    Multiple_consumers => TRUE,
    Queue_payload_type     => 'scott.topic_message');
  dbms_aqadm.create_queue(
    queue_name  => 'scott.sample_topic',
    queue_table => 'scott.topic_queue_table' );
  dbms_aqadm.start_queue(queue_name => 'scott.sample_topic');
END;
/

Sample Web Service for a Queue Generated by WebServicesAssembler

For the queue described in "Sample AQ Queue and Topic Declaration", Example 10-14 lists the Web service operations exposed by WebServicesAssembler.

In this example, the send operation enqueues a payload to the queue. The payload type is the complex type tns:QueueMessageUser, which corresponds to the SQL type QUEUE_MESSAGE, as shown by <send/> element.The receive operation returns a payload from the queue. The <receiveResponse/> element shows that the type of the returned payload is tns:QueueMessage. The operation blocks until a message becomes available.The receiveNoWait operation returns a payload from the queue. If no message is available in the queue, the operation returns null without waiting. The receive2 operation has two arguments.

  • selector of type xsd:string

  • noWait of type xsd:boolean

The selector is a filter condition specified in the AQ convention. It allows the receive operation to return only messages that satisfies that condition. For example, the JMSPriority < 3 AND PRICE < 300 selector exposes only messages with priority 3 or higher, and the attribute PRICE is lower than 300. If the parameter noWait is true, the operation does not block.

Example 10-14 Web Service Operations Exposed for a Queue

<operation name="receive">
  <input message="tns:SampleQueue_receive" /> 
  <output message="tns:SampleQueue_receiveResponse" /> 
  </operation>
<operation name="receive2">
  <input message="tns:SampleQueue_receive2" /> 
  <output message="tns:SampleQueue_receive2Response" /> 
  </operation>
<operation name="receiveNoWait">
  <input message="tns:SampleQueue_receiveNoWait" /> 
  <output message="tns:SampleQueue_receiveNoWaitResponse" /> 
  </operation>
<operation name="send">
  <input message="tns:SampleQueue_send" /> 
  <output message="tns:SampleQueue_sendResponse" /> 
  </operation>
 
<complexType name="receive">
  <sequence /> 
  </complexType>
<complexType name="receiveResponse">
<sequence>
  <element name="result" type="tns:QueueMessageUser" nillable="true" /> 
  </sequence>
  </complexType>
<complexType name="QueueMessageUser">
<sequence>
  <element name="text" type="string" nillable="true" /> 
  <element name="subject" type="string" nillable="true" /> 
  </sequence>
  </complexType>
<complexType name="receive2">
<sequence>
  <element name="String_1" type="string" nillable="true" /> 
  <element name="boolean_2" type="boolean" /> 
  </sequence>
  </complexType>
<complexType name="receive2Response">
<sequence>
  <element name="result" type="tns:QueueMessageUser" nillable="true" /> 
  </sequence>
  </complexType>
<complexType name="receiveNoWait">
  <sequence /> 
  </complexType>
<complexType name="receiveNoWaitResponse">
<sequence>
  <element name="result" type="tns:QueueMessageUser" nillable="true" /> 
  </sequence>
  </complexType>
<complexType name="send">
<sequence>
  <element name="QueueMessageUser_1" type="tns:QueueMessageUser" nillable="true" /> 
  </sequence>
  </complexType>
<complexType name="sendResponse">
  <sequence /> 
  </complexType>

Sample Web Service for a Topic Generated by WebServicesAssembler

For the topic described in "Sample AQ Queue and Topic Declaration", Example 10-15 lists the Web service operations exposed by WebServicesAssembler.

In this example, the publish operation enters a payload to the topic. The argument is a payload type, for instance, tns:TopicMessageUser, as shown in Example 10-15. The message will be received by all topic subscribers.

The publish2 operation sends the payload to all the subscribers in the recipients list. This operation takes the following arguments.

  • payload of type tns:TopicMessageUser

  • recipients of String array type

The publish3 operation broadcasts the payload to the topic. This operation takes the following arguments.

  • payload, the message to be sent

  • deliveryMode, of type xsd:int—can be either javax.jms.DeliveryMode.PERSISTENT or javax.jms.DeliveryMode.NON_PERSISTENT. However, only DeliveryMode.PERSISTENT is supported in this release. The interface javax.jms.DeliveryMode is from the JMS APIs

  • priority, of type xsd:int—specifies the priority of the message. Values can be from 0 to 9, with 0 as lowest priority and 9 as highest.

  • timeToLive, of type xsd:long—indicates the life span of the message in milliseconds. Zero means no limit.

The receive operation returns a message sent to the receiver. This operation takes one argument: receiver.

The receiveNoWait operation returns a message sent to the specified recipient without waiting.

The receive2 operation returns a filtered message sent to the specified recipient. This operation takes the following arguments.

  • receiver, of type xsd:string—recipient of the filtered message.

  • selector, of type xsd:string—a filter condition specified in the AQ convention.

The receive3 operation returns filtered payload for the specified recipient. This operation takes the following arguments.

  • receiver, of type xsd:string—recipient of the filtered message.

  • selector, of type xsd:string—a filter condition specified in the AQ convention.

  • timeout, of type xsd:long—specifies the timeout for the operation in milliseconds. Zero means no timeout.

The subscribe operation subscribes a user to the topic. The underlying connection supporting the Web service must have appropriate privileges to subscribe a consumer. Otherwise, this operation has no effect.

The unsubscribe operation unsubscribes a user from the topic. Again, the underlying connection supporting the Web service must have appropriate privileges to unsubscribe a consumer. Otherwise, this operation has no effect.

See Also:

Oracle Streams Advanced Queuing Java API Reference for information on the privileges needed for subscribing and unsubscribing consumers.

Example 10-15 Web Service Operations Exposed for a Topic

<operation name="publish">
  <input message="tns:SampleTopic_publish" /> 
  <output message="tns:SampleTopic_publishResponse" /> 
  </operation>
<operation name="publish2">
  <input message="tns:SampleTopic_publish2" /> 
  <output message="tns:SampleTopic_publish2Response" /> 
  </operation>
<operation name="publish3">
  <input message="tns:SampleTopic_publish3" /> 
  <output message="tns:SampleTopic_publish3Response" /> 
  </operation>
<operation name="receive">
  <input message="tns:SampleTopic_receive" /> 
  <output message="tns:SampleTopic_receiveResponse" /> 
  </operation>
<operation name="receive2">
  <input message="tns:SampleTopic_receive2" /> 
  <output message="tns:SampleTopic_receive2Response" /> 
  </operation>
<operation name="receive3">
  <input message="tns:SampleTopic_receive3" /> 
  <output message="tns:SampleTopic_receive3Response" /> 
  </operation>
<operation name="receiveNoWait">
  <input message="tns:SampleTopic_receiveNoWait" /> 
  <output message="tns:SampleTopic_receiveNoWaitResponse" /> 
  </operation>
<complexType name="publish">
<sequence>
  <element name="TopicMessageUser_1" type="tns:TopicMessageUser" nillable="true" /> 
  </sequence>
  </complexType>
<complexType name="TopicMessageUser">
<sequence>
  <element name="text" type="string" nillable="true" /> 
  <element name="subject" type="string" nillable="true" /> 
  </sequence>
  </complexType>
<complexType name="publishResponse">
  <sequence /> 
  </complexType>
<complexType name="publish2">
<sequence>
  <element name="TopicMessageUser_1" type="tns:TopicMessageUser" nillable="true" /> 
  <element name="arrayOfString_2" type="string" nillable="true" minOccurs="0" maxOccurs="unbounded" /> 
  </sequence>
  </complexType>
<complexType name="publish2Response">
  <sequence /> 
  </complexType>
<complexType name="publish3">
<sequence>
  <element name="TopicMessageUser_1" type="tns:TopicMessageUser" nillable="true" /> 
  <element name="int_2" type="int" /> 
  <element name="int_3" type="int" /> 
  <element name="long_4" type="long" /> 
  </sequence>
  </complexType>
<complexType name="publish3Response">
  <sequence /> 
  </complexType>
<complexType name="receive">
<sequence>
  <element name="String_1" type="string" nillable="true" /> 
  </sequence>
  </complexType>
<complexType name="receiveResponse">
<sequence>
  <element name="result" type="tns:TopicMessageUser" nillable="true" /> 
  </sequence>
  </complexType>
<complexType name="receive2">
<sequence>
  <element name="String_1" type="string" nillable="true" /> 
  <element name="String_2" type="string" nillable="true" /> 
  </sequence>
  </complexType>
<complexType name="receive2Response">
<sequence>
  <element name="result" type="tns:TopicMessageUser" nillable="true" /> 
  </sequence>
  </complexType>
<complexType name="receive3">
<sequence>
  <element name="String_1" type="string" nillable="true" /> 
  <element name="String_2" type="string" nillable="true" /> 
  <element name="long_3" type="long" /> 
  </sequence>
  </complexType>
<complexType name="receive3Response">
<sequence>
  <element name="result" type="tns:TopicMessageUser" nillable="true" /> 
  </sequence>
  </complexType>
<complexType name="receiveNoWait">
<sequence>
  <element name="String_1" type="string" nillable="true" /> 
  </sequence>
  </complexType>
<complexType name="receiveNoWaitResponse">
<sequence>
  <element name="result" type="tns:TopicMessageUser" nillable="true" /> 
  </sequence>
  </complexType>

How to Access an AQ Queue Exposed as a Web Service from Client Code

Example 10-16 illustrates a sample JAX-RPC Web service client that accesses the published Web service. "Sample Web Service for a Topic Generated by WebServicesAssembler" illustrates the operations exposed by the queues and topics.

Example 10-16 Client Code to Access an AQ Queue Exposed as a Web Service

SampleQueuePortClient queue = new SampleQueuePortClient();
     QueueMessageUser m;
     queue.send(new QueueMessageUser( "star chopper", "sample 1"));
     queue.send(new QueueMessageUser("easy blocks", "sample 2"));
     queue.send(new QueueMessageUser("back to future", "sample 3"));
     m = queue.receive();
     while (m != null) {
         System.out.println("Message received from SampleQueue: " + m.getSubject() + ": " + m.getText());
         m = queue.receiveNoWait();
          }

This client returns the following responses.

Message received from SampleQueue: sample 1: star chopper
      Message received from SampleQueue: sample 2: easy blocks
      Message received from SampleQueue: sample 3: back to future

How to Access an Oracle AQ Queue with JMS

By default, the Web service interface code uses the data source to get a JDBC connection. It then uses the connection to access the queue inside the database.

As an alternative to JDBC, you can use JMS to access the queue. The WebServicesAssembler tool provides these specialized arguments to the aqAssemble command that let you access the exposed Oracle AQ with a JMS queue instance.

  • aqConnectionLocationthe JDNI location of the Oracle Streams AQ JMS queue connection connecting to the exposed AQ.

  • aqConnectionFactoryLocationthe JNDI location of the Oracle Streams AQ JMS queue connection factory for the exposed AQ.

Instead of specifying the dataSource argument in the aqAssemble command, you can specify either of the preceding parameters. The Web service will use a JMS queue at runtime instead of a JDBC-based queue.

How to Assemble a Server-Side Java Class as a Web Service

Use the dbJavaAssemble command to generate Web services that invoke a Java class inside the Java VM in an Oracle database. You can expose either static or instance methods as Web service operations. An instance method can be invoked through either a default or singleton instance in the session.

The Java class that you want to expose can contain any of the following parameters and return types.

  • primitive types (except char)

  • serializable types (that is, classes that implement java.io.Serializable)

  • Java Beans whose attributes are supported types

  • JDBC types; that is, oracle.sql.* types

  • arrays of supported types

This section contains the following subsections:

Prerequisites

Before you begin, supply the following information.

  • The fully-qualified class name of the server-side Java class

  • A database connection URL; used at code generation time

  • The name and password of the schema which contains the Java class; used at code generation time

  • A name for the Web service application

  • The data source JNDI name; used at runtime

Steps for Assembling a Web Service from a Server-Side Java Class

The following steps describe how to use WebServicesAssembler to assemble a Web service from a server-side Java class.

  1. Supply the information described in the Prerequisites section as input to WebServicesAssembler dbJavaAssemble command.

    For example, in the following dbAssemble command, the server-side class, oracle.sqlj.checker.JdbcVersion, is part of the SQLJ server-side translator. This command assembles a Web service application for the class, javacallin.ear. It also generates a PL/SQL wrapper and a Java stored procedure wrapper. The purpose of the Java stored procedure wrapper is to convert signature types in the server-side Java class into types can be exposed to PL/SQL stored procedures. Since the sysUser argument is declared, the WebServicesAssembler automatically loads the generated wrappers into the database.

    Command line:

    java -jar wsa.jar 
      -dbJavaAssemble 
      -appName javacallin
      -dbJavaClassName oracle.sqlj.checker.JdbcVersion
      -dbConnection jdbc:oracle:thin:@stacd15:1521:lsqlj 
      -dataSource jdbc/OracleManagedDS 
      -dbUser scott/tiger 
      -sysUser sys/knl_test7
    

    Ant task:

    <oracle:dbJavaAssemble 
       appName="javacallin"
       dbJavaClassName="oracle.sqlj.checker.JdbcVersion"
       dbConnection="jdbc:oracle:thin:@stacd15:1521:lsqlj" 
       dataSource="jdbc/OracleManagedDS" 
       dbUser="scott/tiger" 
       sysUser="sys/knl_test7"
    />
    

    In this command and Ant task:

    • dbJavaAssemble—Generates Web services from a Java class inside the Java VM in an Oracle database. To use this command, you must connect to a database. See "dbJavaAssemble".

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

    • dbJavaClassName—Specifies the name of the server-side Java class to be published as a Web service. See "dbJavaClassName".

    • dbConnection—Specifies the JDBC URL for the database. See "dbConnection".

    • dataSource—Specifies the JNDI location of the data source used by the Web services at runtime. See "dataSource".

    • dbUser—Specifies the database schema and password in the form of user/password. See "dbUser".

    • sysUser—Specifies the name and password of a user with SYS privileges in the form of dbSysUser/syspassword. Using this argument allows PL/SQL and Java wrapper code to be installed automatically into the database at code-generation time.See "sysUser".

    At run time, the Web service code uses JDBC to invoke the PL/SQL wrapper, which in turns calls the Java stored procedure wrapper, which eventually calls the server-side class. Example 10-18 illustrates some Web service operations generated by this command.

  2. Deploy the service into a running instance of OC4J and bind the application.

    This step assumes that the data source specified in Step 1 has been installed in this instance of OC4J.

    The following command lines provide sample deployment and bind commands.

    % java –jar <J2EE_HOME>/admin_client.jar deployer:oc4j:localhost:port admin welcome  –deploy -file dist/javacallin.ear –deploymentName javacallin
    
    % java –jar <J2EE_HOME>/admin_client.jar deployer:oc4j:localhost:port admin welcome  –bindWebApp javacallin javacallin-web default-web-site /javacallin
    

    In this example, <J2EE_HOME> is the directory where J2EE is installed.

    For more information on deploying EAR files, see the Oracle Containers for J2EE Deployment Guide.

  3. (Optional) Check that deployment succeeded.

    OracleAS Web Services provides a Web Service Test Page for each deployed Web service. See "How to Use the Web Services Test Page" for information on accessing and using the Web Service Test Page.

  4. Generate the client-side code.

    • For the J2SE environment, generate stubs (client proxies) for a J2SE Web service client by running the WebServicesAssembler tool with the genProxy command. See Chapter 15, "Assembling a J2SE Web Service Client" for more information on generating and assembling client-side code for the J2SE environment.

    • For the J2EE environment, generate a service endpoint interface and a JAX-RPC mapping file for a J2EE Web service client by running the WebServicesAssembler tool with the genInterface command. See Chapter 14, "Assembling a J2EE Web Service Client" for more information on generating and assembling client-side code.

    For example, the following command uses genProxy to generate code for a J2SE client.

    % java –jar wsa.jar –genProxy 
                        –wsdl http://locahost:8888/javacallin/javacallin?WSDL 
                        -output build/src/client 
                        –mappingFileName ./mapping.xml 
                        –packageName oracle.demo.db.queue.stub 
                        -unwrapParameters true
    

    In this command:

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

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

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

    • mappingFileName—Specifies a file location that points to a JAX-RPC mapping file. See "mappingFileName".

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

    • unwrapParameters—This argument can be set only for document-literal operations and will be ignored for other message formats. When unwrapParameters is set to true, which is the default, the return type and response type will be unwrapped. This is usually easier to use, especially if the types are simple. See "unwrapParameters".

  5. Compile and run the client.

    List the appropriate JARs on the classpath before compiling the client. Table A-2, "Classpath Components for a Client Using a Client-Side Proxy" lists all of the JAR files that can possibly be used on the client classpath. As an alternative to listing individual JARs, you can include the client-side JAR, wsclient_extended.jar on the client classpath. This JAR file contains all the classes necessary to compile and run a Web service client. The classes are from the individual JAR files listed in Table A-2. See "Setting the Classpath for a Web Service Proxy" for more information on wsclient_extended.jar and the client classpath.

    The following command lines provide sample compile and run commands.

    % javac –classpath path
    <ORACLE_HOME>/webservices/lib/wsclient_extended.jar: 
    :<ORACLE_HOME>/webservices/lib/jaxrpc-api.jar JavacallinClient.java
     
    % java -classpath path
    <ORACLE_HOME>/webservices/lib/wsclient_extended.jar:
    <ORACLE_HOME>/webservices/lib/jaxrpc-api.jar:
    <J2EE_HOME>/lib/jax-qname-namespace.jar:
    <J2EE_HOME>/lib/activation.jar:<J2EE_HOME>/lib/mail.jar:
    <J2EE_HOME>/lib/http_client.jar:
    <ORACLE_HOME>/webservices/lib/commons-logging.jar:
    <ORACLE_HOME>/lib/xmlparserv2.jar JavacallinClient
    

    In this example, <J2EE_HOME> is the directory where J2EE is installed; <ORACLE_HOME> is the directory where the OC4J is installed.

Sample Server-Side Java Class

Example 10-17 illustrates two APIs in oracle.sqlj.checker.JdbcVersion, a server-side Java class distributed with Oracle9i and 10g databases. The dbJavaAssemble command exposes these APIs as a Web service.

Example 10-17 Sample Server-Side Java Class

public class oracle.sqlj.checker.JdbcVersion extends java.lang.Object {
    public static int getDriverMajorVersion();
    public static int getDriverMinorVersion();
    ...
}

Sample Web Service Operations Generated from a Server-Side Java Class

The WSDL fragment in Example 10-18 illustrates the Web service operations generated for the JdbcVersion APIs getDriverMajorVersion and getDriverMinorVersion in Example 10-17.

Example 10-18 WSDL Fragment, Illustrating Operations Generated for a Server-Side Java Class

<complexType name="getDriverMajorVersion">
  <sequence /> 
  </complexType>
<complexType name="getDriverMajorVersionResponse">
<sequence>
  <element name="result" type="decimal" nillable="true" /> 
  </sequence>
  </complexType>
<complexType name="getDriverMinorVersion">
  <sequence /> 
  </complexType>
<complexType name="getDriverMinorVersionResponse">
<sequence>
  <element name="result" type="decimal" nillable="true" /> 
  </sequence>
  </complexType>
 
<portType name="JdbcVersion">
<operation name="getDriverMajorVersion">
  <input message="tns:JdbcVersion_getDriverMajorVersion" /> 
  <output message="tns:JdbcVersion_getDriverMajorVersionResponse" /> 
  </operation>
<operation name="getDriverMinorVersion">
  <input message="tns:JdbcVersion_getDriverMinorVersion" /> 
  <output message="tns:JdbcVersion_getDriverMinorVersionResponse" /> 
  </operation>
  </portType>

Note:

A server-side Java class can also be invoked through JDBC (rather than through Web services). If this is the case, refer to the Oracle Database JPublisher User's Guide to find out how to generate a proxy class for invoking database server-side Java.

Developing a Web Service Client in the Database

This section contains the following subsections:

Understanding Web Service Call-Out

Oracle JPublisher supports PL/SQL and Java Web service call-outs by creating the appropriate stub code. This enables you to use PL/SQL or Java to invoke a Web service client from inside the database. For a Web service call-out, you supply a WSDL file or location to Oracle JPublisher. Oracle JPublisher generates a PL/SQL wrapper and the necessary database server-side Java classes that implement the PL/SQL wrapper. The generated PL/SQL wrapper contains a PL/SQL procedure or function for each Web service operation.

As an alternative, Oracle JPublisher has the ability to generate Java client proxies only. These Java client proxies can be used for Web service call-outs by Java code in the database.

Figure 10-3 illustrates the stub code that Oracle JPublisher can generate.

Figure 10-3 Creating Web Service Call Out Stubs

This illustration is described in the text.
Description of "Figure 10-3 Creating Web Service Call Out Stubs"

Note:

If you must dynamically construct invocations of external Web services based on a WSDL which is available only at runtime, use the JAX-RPC Dynamic Invocation Interface API for Java or the PL/SQL UTL_DBWS package.

The client proxy which Oracle JPublisher generates is based on the simplified client code generated for Java proxies in OracleAS Web Services 10.1.3. Therefore, the Java and PL/SQL client which Oracle JPublisher generates is fully supported by OracleAS Web Services 10.1.3.1. In addition, Oracle JPublisher can also generate OracleAS Web Services 9.0.4-style Web service clients.

Web service call-out requires these utilities and tools.

These are the required Oracle JPublisher options for Web service call-outs.

  • proxywsdl—the URL of the WSDL file for the Web service to be invoked

  • userthe database schema (and password) for which the PL/SQL wrapper is generated

These are the optional Oracle JPublisher parameters.

  • httpproxythe HTTP proxy host and port for accessing the WSDL file

  • sysuserthe database user (and password) with SYSDBA privileges

  • proxyoptsa list of options specific to proxywsdl

  • dirthe directory storing all the generated files

The sysUser argument allows Oracle JPublisher to load the generated file into the database. If this argument is not declared, you must manually load the generated file into the database to invoke the Web service from PL/SQL.

See Also:

Oracle Database JPublisher User's Guide for examples and options related to Web service call-out, such as proxywsdl, proxyopts, and httpproxy.

How to Call Web Services from the Database

The Web services call-out utility allows a client to access Web services from the database. Web services call-out can be employed by PL/SQL clients, SQL statements and Java in the database. This utility is based on Oracle JPublisher 10g Release 2 (10.2) and OracleAS Web Services 10g Release 3 (10.1.3.1).

Two versions of the utility are available, based on whether your target is the Oracle Database 10g (Release 10.1 or 10.2), or a pre-10g Oracle Database.

The call-out utility is available at the following Web site under the heading "Database as Web Services consumer: Calling-out external Web services".

http://www.oracle.com/technology/sample_code/tech/java/jsp/dbwebservices.html

The following sections describe how a client in the database can perform Web services call-out:

How to Perform Web Services Call-Out using Static Proxy and JPublisher

The Oracle JPublisher command line option -proxywsdl can be used to generate database-side Java and PL/SQL wrappers from the WSDL file of a Web service. To allow JPublisher to generate and load wrappers for Web service clients into the database, the dbwsa.jar and dbwsclient.jar files must be present in the classpath and inside the database respectively.

The following procedure sets up the environment and the database for Oracle JPublisher-supported Web service call-out. This procedure needs to be performed only once.

  1. Download and install the Oracle JPublisher 10g Release 2 (10.2) if it is not already on your system.

    You can obtain the Oracle JPublisher release from the following Web site:

    http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/index.html

  2. Add the dbwsa.jar to the directory ORACLE_HOME\sqlj\lib (Windows) or ORACLE_HOME/sqlj/lib (Solaris).

  3. Set up the appropriate JDK as the Java VM and Java compiler.

    The version of the JDK must be the same as the Java VM in the target database:

    • use the JDK 1.4 for the Oracle Database 10g (Release 10.1 or 10.2)

    • use the JDK 1.3 for the Oracle Database 9.2

  4. Add dbwsa.jar file to the classpath environment variable.

  5. Load the dbwsclient.jar file either into the SYS schema or into the schema where the Web service client will be invoked.

    For example, the following loadjava command will load the dbwsclient.jar file into the SYS schema.

    %loadjava -u sys/change_on_install -r -v -f -s -grant public -noverify -genmissing dbwsclient.jar
    

    The following loadjava command illustrates how to load the dbwsclient.jar file into a specific schema.

    % loadjava -u scott/tiger -r -v -f -noverify -genmissing dbwsclient.jar
    

Example

The following example illustrates how to generate Java and PL/SQL wrappers for a Web service client and then invoke it by using SQL statements. The example follows these general steps:

  1. Identify the Web service you want to invoke.

  2. Call Oracle JPublisher with the appropriate options to generate the client proxy, the PL/SQL and Java wrappers, and load them into the database.

    An Oracle JPublisher command to do this would include the required -proxywsdl and -user options. The command could also include the optional -endpoint, -httpproxy, -sysuser, -dir, and -proxyopts options. For example:

    % jpub -user=username/password -sysuser=superuser_name/superuser_password -proxywsdl=WSDL_URL -endpoint=Web_services_endpoint  
    

    It is assumed that the Web service has been previously deployed at http://localhost:8888/javacallout/javacallout

    The following command creates the Web service client and its Java and PL/SQL wrappers in the subdirectory tmp, then loads the wrappers into the database.

    % jpub -user scott/tiger -sysuser sys/change_on_install -proxywsdl=sample/javacallout.wsdl   -endpoint=http://localhost:8888/javacallout/javacallout -dir=tmp
    

    This command produces the following output:

    tmp/HelloServiceEJBJPub.java
    tmp/plsql_wrapper.sql
    tmp/plsql_dropper.sql
    tmp/plsql_grant.sql
    tmp/plsql_revoke.sql
    Executing tmp/plsql_dropper.sql
    Executing tmp/plsql_wrapper.sql
    Executing tmp/plsql_grant.sql
    Loading tmp/plsql_proxy.jar
    
  3. Invoke the Web service from inside the database.

    You can invoke the PL/SQL functions provided in tmp/plsql_wrapper.sql. Each PL/SQL function corresponds to an operation in the Web service. For example, if your Web service is available at the following endpoint:

    http://localhost:8888/javacallout/javacallout
    

    Then you can issue the following SQL command.

    SQL> select jpub_plsql_wrapper.sayhello('hello') from dual;
    

    The command will return the following output.

    JPUB_PLSQL_WRAPPER.SAYHELLO('HELLO')
    -----------------------------------
    HELLO!! You just said :hello
    

For more information about Oracle JPublisher call-out support, see "Web service Call-out using Dynamic Invocation Interface and the SYS.UTL_DBWS Utility" in Oracle Database JPublisher User's Guide. This is available from the following Web site.

http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/index.html

How to Perform Web Services Call-Out using DII and the SYS.UTL_DBWS Utility

A PL/SQL user can invoke Web services using the PL/SQL package SYS.UTL_DBWS. This package provides wrapper functions for the JAX-RPC Dynamic Invocation Interface (DII) APIs.

The following procedure applies to Oracle Database 10g Release 1 or later. The procedure sets up the database for Web service call-out using SYS.UTL_DBWS, and refreshes the utility with more recent features provided in by the download.

  1. Load the dbwsclient.jar file into the database, as described in "How to Perform Web Services Call-Out using Static Proxy and JPublisher".

  2. Execute utl_dbws_decl.sql and utl_dbws_body.sql SQL scripts as SYS.

    You can now use SYS.UTL_DBWS to call Web services.

Example

The call-out utilities download includes the SQL scripts samples/test-plsql-dii.sql and samples/test-plsql-dii2.sql. Both scripts invoke the sayHello operation defined in javacallout.wsdl. Examine the two scripts for their correspondences with the WSDL file. Both scripts produce the following output; the phrase PL/SQL DII client return is produced by the client code.

PL/SQL DII client return HELLO!! You just said :hello  

For more information on the SYS.UTL_DBWS utility, see Oracle Database PL/SQL Packages and Types Reference available from the following Web site.

http://www.oracle.com/technology/documentation/database10g.html

Tool Support for Web Services that Expose Database Resources

With Oracle JDeveloper, you can create a Web service based on program units in a PL/SQL package that is stored in an Oracle database. You can use the wizards in Oracle JDeveloper to perform the following tasks.

For more information on using Oracle JDeveloper to create PL/SQL package units and expose them as a Web service, see the Oracle JDeveloper on-line help.

Limitations

See "Developing Web Services From Database Resources".

Additional Information

For more information on: