2 Creating DBWS Services
This chapter includes the following sections:
Creating EclipseLink DBWS Service from a Database Table
You can create a web service that exposes a database table's CRUD (Create/Read[findByPK and findAll]/Update/Delete) operations. EclipseLink supports this for any table or multiple tables (use patterns supporting % for catalog, schema or table names) on any database on which the JDBC driver reliably and accurately delivers the table's metadata via the JDBC metadata APIs (java.sql.DatabaseMetaData
).
EclipseLink uses the DBWSBuilder
utility to generate a DBWS XML schema, using the following rules:
-
table name ==> translate any characters not supported by XMLFoot 1 ==> translate to_lowercase ==> add suffix 'Type' ==> top-level complex type in
.xsd
file -
column name ==> translate any characters not supported by XMLFoot 1 ==> translate to_lowercase ==> becomes
<element-tag>
name-
All columns are expressed as elements
-
BLOB
columns are automatically mapped toxsd:base64Binary
-
xsd:base64Binary
elements can be included in-line to the XML document, or handled as binary attachments (SwaRef
orMTOM
style).
-
Example 2-1 uses the EMP table (Table 2-1) from the Oracle scott database schema:
Table 2-1 Sample EMP Table
OWNER | TABLE_NAME | COLUMN_NAME | DATA_TYPE | DATA_LENGTH | DATA_PRECISION | DATA_SCALE | NULLABLE? |
---|---|---|---|---|---|---|---|
SCOTT |
EMP |
EMPNO |
NUMBER |
22 |
4 |
0 |
N |
SCOTT |
EMP |
ENAME |
VARCHAR2 |
10 |
(null) |
(null) |
Y |
SCOTT |
EMP |
JOB |
VARCHAR2 |
9 |
(null) |
(null) |
Y |
SCOTT |
EMP |
MGR |
NUMBER |
22 |
4 |
0 |
Y |
SCOTT |
EMP |
HIREDATE |
DATE |
7 |
(null) |
(null) |
Y |
SCOTT |
EMP |
SAL |
NUMBER |
22 |
7 |
2 |
Y |
SCOTT |
EMP |
COMM |
NUMBER |
22 |
7 |
2 |
Y |
SCOTT |
EMP |
DEPTNO |
NUMBER |
22 |
2 |
0 |
Y |
Example 2-1 Example
The DBWSBuilder utility requires a DBWS configuration file as input, as shown here:
<?xml version="1.0" encoding="UTF-8"?> <dbws-builder xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <properties> <property name="projectName">emp</property> ... database properties </properties> <table catalogPattern="%" tableNamePattern="EMP" /> </dbws-builder>
Use this command to execute the DBWSBuilder:
prompt > dbwsbuilder.cmd -builderFile dbws-builder.xml -stageDir output_directory -packageAs wls emp.war
where
-
dbws-builder.xml
is the DBWS configuration file (as shown previously) -
output_directory
is the output directory for the generated files -
-packageAs
is the platform on which the web service will be deployed
The DBWSBuilder
-generated eclipselink-dbws-schema.xsd
file derives <element-tag>
names from the Database table metadata in Table 2-1:
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" > <xsd:complexType name="empType"> <xsd:sequence> <xsd:element name="empno" type="xsd:int" xsi:nil="false"/> <xsd:element name="ename" type="xsd:string" xsi:nil="true"/> <xsd:element name="job" type="xsd:string" xsi:nil="true"/> <xsd:element name="mgr" type="xsd:int" minOccurs="0" xsi:nil="true"/> <xsd:element name="hiredate" type="xsd:dateTime" xsi:nil="true"/> <xsd:element name="sal" type="xsd:decimal" xsi:nil="true"/> <xsd:element name="comm" type="xsd:int" minOccurs="0" xsi:nil="true"/> <xsd:element name="deptno" type="xsd:int" xsi:nil="true"/> </xsd:sequence> </xsd:complexType> </xsd:schema>
Generated EclipseLink DBWS service descriptor
The CRUD operations are illustrated in the generated EclipseLink DBWS service descriptor (eclipselink-dbws.xml
) file, as shown here:
Example 2-2 Sample CRUD Operations
<?xml version="1.0" encoding="UTF-8"?> <dbws xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="urn:emp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <name>emp</name> <sessions-file>eclipselink-dbws-sessions.xml</sessions-file> <update> <name>update_empType</name> <parameter> <name>theInstance</name> <type>ns1:empType</type> </parameter> </update> <insert> <name>create_empType</name> <parameter> <name>theInstance</name> <type>ns1:empType</type> </parameter> </insert> <query> <name>findByPrimaryKey_empType</name> <parameter> <name>id</name> <type>xsd:decimal</type> </parameter> <result> <type>ns1:empType</type> </result> <named-query> <name>findByPrimaryKey</name> <descriptor>empType</descriptor> </named-query> </query> <delete> <name>delete_empType</name> <parameter> <name>theInstance</name> <type>ns1:empType</type> </parameter> </delete> <query> <name>findAll_empType</name> <result isCollection="true"> <type>ns1:empType</type> </result> <named-query> <name>findAll</name> <descriptor>empType</descriptor> </named-query> </query> </dbws>
SOAP Messaging
The following SOAP Message invokes the <findAll_empType
> operation for the emp DBWS service:
<?xml version="1.0" encoding="UTF-8"?> <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"> <env:Body> <findAll_empType xmlns="urn:empService" xmlns:urn="urn:emp"/> </env:Body> </env:Envelope>
returning:
<?xml version="1.0" encoding="utf-16"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header /> <SOAP-ENV:Body> <srvc:findAll_empTypeResponse xmlns="urn:emp" xmlns:srvc="urn:empService"> <srvc:result> <empType> <empno>7369</empno> <ename>SMITH</ename> <job>CLERK</job> <mgr>7902</mgr> <hiredate>1980-12-17T00:00:00.0-05:00</hiredate> <sal>800</sal> <deptno>20</deptno> </empType> <empType> <empno>7499</empno> <ename>ALLEN</ename> <job>SALESMAN</job> <mgr>7698</mgr> <hiredate>1981-02-20T00:00:00.0-05:00</hiredate> <sal>1600</sal> <comm>300</comm> <deptno>30</deptno> </empType> .... </srvc:result> </srvc:findAll_empTypeResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Using an EclipseLink SessionCustomizer
When using an EclipseLink SessionCustomizer
with DBWS, you can access to the EclipseLink API to retrieve the OR (object-relational
) or OX (object-XML
) mapping descriptors from the session. You can then use the descriptors to add, change, or delete mappings.
For more information, see "Session Customization in the EclipseLink documentation: http://wiki.eclipse.org/Introduction_to_EclipseLink_Sessions_%28ELUG%29#Session_Customization
For more information, see "Sessions" in Understanding Oracle TopLink.
Example
This example illustrates how to implement an EclipseLink SessionCustomizer
:
package some.java.package; import org.eclipse.persistence.config.SessionCustomizer; import org.eclipse.persistence.sessions.Session; import org.eclipse.persistence.sessions.DatabaseLogin; public class MySessionCustomizer implements SessionCustomizer { public MySessionCustomizer() { } public void customize(Sesssion session) { DatabaseLogin login = (DatabaseLogin)session.getDatasourceLogin(); // enable 'dirty' reads login.setTransactionIsolation(DatabaseLogin.TRANSACTION_READ_UNCOMMITTED); } }
In the DBWSBuilder
configuration file, you must use the orSessionCustomizerClassName
or oxSessionCustomizerClassName
to specify if the customization applies to the ORM or ORX project (respectively), as shown here:
Example 2-3 ORM Project
<?xml version="1.0" encoding="UTF-8"?> <dbws-builder xmlns:xsd="http://www.w3.org/2001/XMLSchema" <properties> <property name="projectName">customize_test</property> ... <property name="orSessionCustomizerClassName">some.java.package.MyORSessionCustomizer</property>
Example 2-4 ORX Project
<?xml version="1.0" encoding="UTF-8"?> <dbws-builder xmlns:xsd="http://www.w3.org/2001/XMLSchema" <properties> <property name="projectName">customize_test</property> ... <property name="oxSessionCustomizerClassName">some.java.package.MyOXSessionCustomizer</property>
Advanced Customization
You can further customize an EclipseLink DBWS service by creating your own EclipseLink project.xml
and sessions.xml
files. Using your preferred utility, you can:
-
map your objects to your relational database in an EclipseLink relational project
-
map your objects to your XML schema in an EclipseLink XML project
-
create an EclipseLink
sessions.xml
file that references both projects.
In this way, you can control all aspects of the relational and XML mapping. This approach is best when you want to customize most or all details.
In Example 2-5, a DBWS service is constructed from existing EclipseLink project maps with identical case-sensitive aliases (for Descriptors that are common between the projects).
Note:
When building a DBWS web service in this way (that is, without the DBWSBuilder
Utility) be sure to create all the necessary deployment artifacts.
Example 2-5 Sample DBWS Service
<?xml version="1.0" encoding="UTF-8"?> <object-persistence version="Eclipse Persistence Services - some version (some build date)" xmlns="http://www.eclipse.org/eclipselink/xsds/persistence" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:eclipselink="http://www.eclipse.org/eclipselink/xsds/persistence"> <name>SomeORProject</name> <class-mapping-descriptors> <class-mapping-descriptor xsi:type="relational-class-mapping-descriptor"> <class>some.package.SomeClass</class> <alias>SomeAlias</alias> ... <?xml version="1.0" encoding="UTF-8"?> <object-persistence version="Eclipse Persistence Services - some version (some build date)" xmlns="http://www.eclipse.org/eclipselink/xsds/persistence" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:eclipselink="http://www.eclipse.org/eclipselink/xsds/persistence"> <name>SomeOXProject</name> <class-mapping-descriptor xsi:type="xml-class-mapping-descriptor"> <class>some.package.SomeClass</class> <alias>SomeAlias</alias> ...
Using Existing EclipseLink ORM and OXM Mappings
A DBWS service may be constructed using pre-existing EclipseLink ORM and OXM maps (both Project classes and Project deployment XML are supported) with identical case-sensitive aliases for Descriptors that are common between the projects.
When building a DBWS web service in this way (that is, without the DBWSBuilder
Utility) be sure to create all the necessary deployment artifacts
Example 2-6 Using an ORM Map
<?xml version="1.0" encoding="UTF-8"?> <object-persistence version="Eclipse Persistence Services - some version (some build date)" xmlns="http://www.eclipse.org/eclipselink/xsds/persistence" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:eclipselink="http://www.eclipse.org/eclipselink/xsds/persistence"> <name>SomeORProject</name> <class-mapping-descriptors> <class-mapping-descriptor xsi:type="relational-class-mapping-descriptor"> <class>some.package.SomeClass</class> <alias>SomeAlias</alias> ...
Example 2-7 Using an OXM Map
<?xml version="1.0" encoding="UTF-8"?> <object-persistence version="Eclipse Persistence Services - some version (some build date)" xmlns="http://www.eclipse.org/eclipselink/xsds/persistence" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:eclipselink="http://www.eclipse.org/eclipselink/xsds/persistence"> <name>SomeOXProject</name> <class-mapping-descriptor xsi:type="xml-class-mapping-descriptor"> <class>some.package.SomeClass</class> <alias>SomeAlias</alias> ...
Creating a DBWS Service from SQL Statements
This section includes information on:
Creating from Results Sets from Custom SQL SELECT Statements
EclipseLink DBWS can create a Web service that exposes the results of executing custom SQL SELECT
statements, without exposing the actual SQL. There is no metadata to determine the structure of the returned data -- the Simple XML Format schema is used.
The SQL SELECT
statements targeted for this service are in the DBWSBuilder
builder XML file, as shown here:
Use this command to create the web service:
prompt > dbwsbuilder.cmd -builderFile dbws-builder.xml -stageDir output_directory -packageAs wls testSql.war
where
-
dbws-builder.xml
is the DBWS builder XML configuration file, as shown previously -
output_directory
is the output directory for the generated files -
-packageA
s the platform on which the web service will be deployed
The generated eclipselink-dbws-schema.xsd
file is the schema for the Simple XML format:
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" > <xsd:complexType name="simple-xml-format"> <xsd:sequence> <xsd:any minOccurs="0"/> </xsd:sequence> </xsd:complexType> </xsd:schema>
The element tags simple-xml-format
and simple-xml
are customized in the SQL operations. For example, <simple-xml-format>
= <aggregate-info>
, <simple-xml>
= <count-and-max-salary>
.
Example 2-8 Sample DBWSBuilder XML File
<?xml version="1.0" encoding="UTF-8"?> <dbws-builder xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <properties> <property name="projectName">testSql</property> ... database properties </properties> <sql name="count" simpleXMLFormatTag="aggregate-info" xmlTag="count" > <text><![CDATA[select count(*) from EMP]]></text> </sql> <sql name="countAndMaxSalary" simpleXMLFormatTag="aggregate-info" xmlTag="count-and-max-salary" > <text><![CDATA[select count(*) as "COUNT", max(SAL) as "MAX-Salary" from EMP]]></text> </sql> </dbws-builder>
Generated EclipseLink DBWS Service Descriptor
The SQL operations are included in the DBWS service descriptor file (eclipselink-dbws.xml
) created by EclipseLink, as well as the settings to alter the default Simple XML Format <element-tag>
name.
Example 2-9 Sample XML File
<?xml version="1.0" encoding="UTF-8"?> <dbws xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="urn:testSql" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <name>testSql</name> <sessions-file>eclipselink-dbws-sessions.xml</sessions-file> <query> <name>count</name> <result> <type>simple-xml-format</type> <simple-xml-format> <simple-xml-format-tag>aggregate-info</simple-xml-format-tag> <simple-xml-tag>count</simple-xml-tag> </simple-xml-format> </result> <sql> <![CDATA[select count(*) from EMP]]> </sql> </query> <query> <name>countAndMaxSalary</name> <result> <type>simple-xml-format</type> <simple-xml-format> <simple-xml-format-tag>aggregate-info</simple-xml-format-tag> <simple-xml-tag>count-and-max-salary</simple-xml-tag> </simple-xml-format> </result> <sql> <![CDATA[select count(*) as "COUNT", max(SAL) as "MAX-Salary" from EMP]]> </sql> </query> </dbws>
SOAP Messaging
The following SOAP Message invokes the <count>
operation for the testSql
DBWS service:
<?xml version="1.0" encoding="UTF-8"?> <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"> <env:Body> <count xmlns="urn:testSqlService" xmlns:urn="urn:testSql"/> </env:Body> </env:Envelope>
returning:
<?xml version="1.0" encoding="utf-16"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header /> <SOAP-ENV:Body> <srvc:countResponse xmlns:srvc="urn:testSqlService"> <srvc:result> <aggregate-info xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="simple-xml-format"> <count> <COUNT_x0028__x002A__x0029_>14</COUNT_x0028__x002A__x0029_> </count> </aggregate-info> </srvc:result> </srvc:countResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Note:
You should be aware of the resultSet
for select count(*);
the characters '(', '*' and ')' are not valid for XML element tags and are replaced by the well-known transformation, which documented as part of the SQL/X specification (SQL/XML:2003).
Custom SQL as Sub-operation of Table-based Web Service
The "SOAP Messaging" operation returns unstructured data. However, it is possible to nest such operations within the context of a Table-based operation; then, the nested operations can be configured to re-use the schema element type of the parent table and return structured data:
<dbws-builder> <properties> <property name="projectName">empSql</property> ... database properties </properties> <table catalogPattern="%" tableNamePattern="EMP" > <sql name="findEmpByName" isCollection="true" returnType="empType" > <text><![CDATA[select * from EMP where ENAME like ?]]></text> <binding name="ENAME" type="xsd:string"/> </sql> </table> </dbws-builder>
The generated EclipseLink DBWS service descriptor eclipselink-dbws.xml
file:
Example 2-10 Sample eclipselink-dbws.xml File
<dbws xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="urn:testSql" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <name>empSql</name> <sessions-file>eclipselink-dbws-sessions.xml</sessions-file> <update> <name>update_empType</name> <parameter> <name>theInstance</name> <type>ns1:empType</type> </parameter> </update> ... <query> <name>findEmpByName</name> <parameter> <name>ENAME</name> <type>xsd:string</type> </parameter> <result isCollection="true"> <type>ns1:empType</type> </result> <sql> <![CDATA[select * from EMP where ENAME like #ENAME]]> </sql> </query> </dbws>
Creating based on Schema-formatted Results from Custom SQL SELECT Statements
EclipseLink can also create a web service in which the "shape" of the returned result is determined at design-time, not runtime. Normally, the custom SQL SELECT
statement returns java.sql.ResultSets
and the java.sql.ResultSetMetaData
APIs (getColumnCount
, getColumnLabel
, getColumnType
, etc.) can be used to determine the name and datatype of the returned information.
EclipseLink DBWS uses the Simplified XML Format (SXF) to create an XML document to describe the ResultSet's information. However, because this document can change arbitrarily, the SXF schema is extremely "loose" – the use of xsd:any
places virtually no restriction on the document.
Example 2-11 Sample Schema
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" > <xsd:complexType name="simple-xml-format"> <xsd:sequence> <xsd:any minOccurs="0"/> </xsd:sequence> </xsd:complexType> </xsd:schema>
Example 2-12 Instance document:
<source lang="xml"> <?xml version = '1.0' encoding = 'UTF-8'?> <simple-xml-format> <simple-xml> <EMPNO>7788</EMPNO> <ENAME>SCOTT</ENAME> <JOB>ANALYST</JOB> <MGR>7566</MGR> <HIREDATE>1987-04-19</HIREDATE> <SAL>3000</SAL> <DEPTNO>20</DEPTNO> </simple-xml> <simple-xml> <EMPNO>7369</EMPNO> <ENAME>SMITH</ENAME> <JOB>CLERK</JOB> <MGR>7902</MGR> <HIREDATE>1980-12-17</HIREDATE> <SAL>800</SAL> <DEPTNO>20</DEPTNO> </simple-xml> </simple-xml-format>
Additional information at Design Time
As indicated previously, the java.sql.ResultSetMetaData
APIs provide enough information, if available at design-time, from which you could generate a schema, as shown here:
Example 2-13 Sample Schema
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:emp" xmlns="urn:emp" elementFormDefault="qualified"> <xsd:complexType name="empType"> <xsd:sequence> <xsd:element name="empno" type="xsd:decimal"/> <xsd:element name="ename" type="xsd:string" minOccurs="0" nillable="true"/> <xsd:element name="job" type="xsd:string" minOccurs="0" nillable="true"/> <xsd:element name="mgr" type="xsd:decimal" minOccurs="0" nillable="true"/> <xsd:element name="hiredate" type="xsd:date" minOccurs="0" nillable="true"/> <xsd:element name="sal" type="xsd:decimal" minOccurs="0" nillable="true"/> <xsd:element name="comm" type="xsd:decimal" minOccurs="0" nillable="true"/> <xsd:element name="deptno" type="xsd:decimal" minOccurs="0" nillable="true"/> </xsd:sequence> </xsd:complexType> <xsd:element name="empType" type="empType"/> </xsd:schema>
The DBWS sql operation is enhanced with an additional SQL statement that is executed at design-time -- the statement will not return any rows (such as when the WHERE
clause evaluates to false in Example 2-14):
Example 2-14 Executing Additional SQL Statements
<?xml version="1.0" encoding="UTF-8"?> <dbws-builder xmlns:xsd="http://www.w3.org/2001/XMLSchema" <properties> <property name="projectName">emp</property> ... </properties> <sql name="Semployees" isCollection="false" returnType="empType" > <statement><![CDATA[select * from EMP where ENAME like 'S%']]></statement> <build-statement><![CDATA[select * from EMP where 0=1]]></build-statement> </sql> </dbws-builder>
Understanding Issues and Limitations
Be aware of the following limitation:
Repeated labels
Valid SQL allows multiple identical columns. For example, consider the following SQL:
SELECT ENAME, ENAME FROM EMP WHERE LIKE 'S%'
ENAME | ENAME |
---|---|
SMITH |
SMITH |
... |
... |
SCOTT |
SCOTT |
In this example, a SELECT
statement that uses UNION
could return a set of column labels where a label is repeated.
DBWSBuilder
maintains a list of "already processed columns" and will throw an exception when it detects a duplicate.
Creating from a Stored Procedure
EclipseLink DBWS can create a Web service that exposes a Stored Procedure (or multiple procedures). Because it is not possible to determine the structure of the returned data from the Stored Procedure's metadata, EclipseLink uses the Simple XML Format schema. The EclipseLink DBWS runtime produces an XML document that is simple and "human-readable."
EclipseLink DBWS supports any combination of IN
, OUT
and IN OUT
arguments. Additionally, EclipseLink also supports procedures in packages that are overloaded (that is, the same name but different parameters).
Example
This example uses the following Stored Procedure:
DROP PROCEDURE TESTECHO; CREATE OR REPLACE PROCEDURE TESTECHO(T IN VARCHAR2, U OUT VARCHAR2) AS BEGIN U := CONCAT(T, '-test'); END;
The DBWSBuilder utility requires a DBWS configuration XML file as input, as shown here:
<?xml version="1.0" encoding="UTF-8"?> <dbws-builder xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <properties> <property name="projectName">testEcho</property> ... database properties </properties> <procedure name="testEcho" procedurePattern="TESTECHO" isSimpleXMLFormat="true" /> </dbws-builder>
Execute the DBWSBuilder
, as shown here:
prompt > dbwsbuilder.cmd -builderFile dbws-builder.xml -stageDir output_directory -packageAs wls testEcho.war
where
-
dbws-builder.xml
is the DBWS builder configuration XML file above -
output_directory
is the output directory for the generated files -
-
packageAs
specifies the platform on which the web service will be deployed
The generated eclipselink-dbws-schema.xsd
file is the schema for the Simple XML format, as shown here:
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" > <xsd:complexType name="simple-xml-format"> <xsd:sequence> <xsd:any minOccurs="0"/> </xsd:sequence> </xsd:complexType> </xsd:schema>
You can customize the simple-xml-format
and simple-xml
tags by setting the appropriate properties on an SQL operation.
Creating from a Stored Function
EclipseLink DBWS can create a Web service that exposes a simple Stored Function.
Example
In this example, the following stored function will be used:
DROP FUNCTION TESTECHO; CREATE OR REPLACE FUNCTION TESTECHO(T IN VARCHAR2) RETURN VARCHAR2 IS retVal VARCHAR2 BEGIN retVal := CONCAT('test-' , T); RETURN retVal; END TESTECHO;
The DBWSBuilder utility requires a DBWS configuration XML file as input, as shown here:
<?xml version="1.0" encoding="UTF-8"?> <dbws-builder xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <properties> <property name="projectName">testEcho</property> ... database properties </properties> <procedure name="testEcho" procedurePattern="TESTECHO" returnType="xsd:string" /> </dbws-builder>
Execute the DBWSBuilder, as shown here:
prompt > dbwsbuilder.cmd -builderFile dbws-builder.xml -stageDir output_directory -packageAs wls testEcho.war
where
-
dbws-builder.xml
is the DBWS builder configuration XML file above -
output_directory
is the output directory for the generated files -
-packageAs
the platform on which the web service will be deployed
Creating from a Stored Procedure with complex PL/SQL arguments
With TopLink, you can create a DBWS web service from a stored procedure that uses complex PL/SQL types as either an IN
, OUT
, or IN
OUT
argument.
Example
In this example, the following stored procedure is used:
PROCEDURE P1(OLDREC IN ARECORD, FOO IN VARCHAR2, AREC OUT ARECORD) IS BEGIN AREC.T1 := ... some processing based upon OLDREC AREC.T2 := ... AND FOO AREC.T3 := ... END P1;
Type ARECORD
is defined in the PL/SQL package SOMEPACKAGE
as follows:
CREATE OR REPLACE PACKAGE SOMEPACKAGE AS TYPE TBL1 IS TABLE OF VARCHAR2(111) INDEX BY BINARY_INTEGER; TYPE TBL2 IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; TYPE ARECORD IS RECORD ( T1 TBL1, T2 TBL2, T3 BOOLEAN ); PROCEDURE P1(OLDREC IN ARECORD, FOO IN VARCHAR2, AREC OUT ARECORD); END SOMEPACKAGE;
Because PL/SQL record and collection types cannot be transported via JDBC, TopLink will generate an anonymous block of PL/SQL code that contains the functions to convert to and from JDBC and PL/SQl types. To be successful, each PL/SQL type or collection type that will appear in an IN
, IN OUT
, or OUT OF RETURN
argument (or any PL/SQL record or collection type that is nested within these arguments) must have an equivalent JDBC type. The name of this type must be in the form <package name>_<type name>
.
For this example, the following JDBC types are required:
CREATE OR REPLACE TYPE SOMEPACKAGE_TBL1 AS TABLE OF VARCHAR2(111) CREATE OR REPLACE TYPE SOMEPACKAGE_TBL2 AS TABLE OF NUMBER CREATE OR REPLACE TYPE SOMEPACKAGE_ARECORD AS OBJECT ( T1 SOMEPACKAGE_TBL1, T2 SOMEPACKAGE_TBL2, T3 BOOLEAN )
The DBWSBuilder utility requires a DBWS configuration file as input.
<?xml version="1.0" encoding="UTF-8"?> <dbws-builder xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <properties> <property name="projectName">testPLSQLProcedure</property> ... database properties </properties> <plsql-procedure name="plsqlprocedure" catalogPattern="SOMEPACKAGE" procedurePattern="P1" /> </dbws-builder>
Notice that returnType
is set to SOMEPACKAGE_ARECORD
. This value indicates a complex type in the generated EclipseLink DBWS schema (as shown below). In this case, it is constructed based on the contents of the SOMEPACKAGE
package.
Execute the DBWSBuilder
, as shown here:
prompt > dbwsbuilder.cmd -builderFile dbws-builder.xml -stageDir output_directory -packageAs wls testPLSQLProcedure.war
where
-
dbws-builder.xml
is the DBWS builder configuration file (as shown previously). -
output_directory
is the output directory for the generated files. -
-packageAs
is the platform on which the web service will be deployed.
The generated eclipselink-dbws-schema.xsd
file follows:
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:plsqlprocedure" xmlns="urn:plsqlprocedure" elementFormDefault="qualified"> <xsd:complexType name="SOMEPACKAGE_TBL1"> <xsd:sequence> <xsd:element name="item" type="xsd:string" maxOccurs="unbounded" nillable="true"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="SOMEPACKAGE_TBL2"> <xsd:sequence> <xsd:element name="item" type="xsd:decimal" maxOccurs="unbounded" nillable="true"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="SOMEPACKAGE_ARECORD"> <xsd:sequence> <xsd:element name="t1"> <xsd:complexType> <xsd:sequence> <xsd:element name="item" type="xsd:string" maxOccurs="unbounded" nillable="true"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="t2"> <xsd:complexType> <xsd:sequence> <xsd:element name="item" type="xsd:decimal" maxOccurs="unbounded" nillable="true"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="t3" type="xsd:boolean" nillable="true"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="simple-xml-format"> <xsd:sequence> <xsd:any minOccurs="0"/> </xsd:sequence> </xsd:complexType> <xsd:element name="SOMEPACKAGE_TBL1" type="SOMEPACKAGE_TBL1"/> <xsd:element name="SOMEPACKAGE_TBL2" type="SOMEPACKAGE_TBL2"/> <xsd:element name="SOMEPACKAGE_ARECORD" type="SOMEPACKAGE_ARECORD"/> </xsd:schema>
Creating from a Stored Function with complex PL/SQL arguments
Starting with EclipseLink 2.3, you can create a DBWS web service from a stored function that uses complex PL/SQL types as either an IN
or return argument.
Example
In this example, the following stored function is used:
FUNCTION F1(OLDREC IN ARECORD, FOO IN VARCHAR2) RETURN ARECORD IS arec ARECORD; -- temp var BEGIN arec.T1 := ... some processing based upon OLDREC arec.T2 := ... AND FOO arec.T3 := ... RETURN arec; END F1;
Type ARECORD
is defined in the PL/SQL package SOMEPACKAGE
as follows:
CREATE OR REPLACE PACKAGE SOMEPACKAGE AS TYPE TBL1 IS TABLE OF VARCHAR2(111) INDEX BY BINARY_INTEGER; TYPE TBL2 IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; TYPE ARECORD IS RECORD ( T1 TBL1, T2 TBL2, T3 BOOLEAN ); FUNCTION F1(OLDREC IN ARECORD, FOO IN VARCHAR2) RETURN ARECORD; END SOMEPACKAGE;
Because PL/SQL types and collection types cannot be transported via JDBC, TopLink will generate an anonymous block of PL/SQL code that contains the functions to convert to and from JDBC and PL/SQl types. To be successful, each PL/SQL type or collection type that will appear in an IN
, IN OUT
, or OUT OF RETURN
argument (or any PL/SQL record or collection type that is nested within these arguments) must have an equivalent JDBC type. The name of this type must be in the form <package name>_<type name>
.
For this example, the following JDBC types are required:
CREATE OR REPLACE TYPE SOMEPACKAGE_TBL1 AS TABLE OF VARCHAR2(111) CREATE OR REPLACE TYPE SOMEPACKAGE_TBL2 AS TABLE OF NUMBER CREATE OR REPLACE TYPE SOMEPACKAGE_ARECORD AS OBJECT ( T1 SOMEPACKAGE_TBL1, T2 SOMEPACKAGE_TBL2, T3 BOOLEAN )
The DBWSBuilder utility requires a DBWS configuration file as input.
<?xml version="1.0" encoding="UTF-8"?> <dbws-builder xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <properties> <property name="projectName">testPLSQLFunction</property> ... database properties </properties> <plsql-procedure name="plsqlfunction" catalogPattern="SOMEPACKAGE" procedurePattern="F1" returnType="SOMEPACKAGE_ARECORD" /> </dbws-builder>
Notice that returnType
is set to SOMEPACKAGE_ARECORD
. This value indicates a complex type in the generated EclipseLink DBWS schema (as shown below). In this case, it is constructed based on the contents of the SOMEPACKAGE
package.
Execute the DBWSBuilder
, as shown here:
prompt > dbwsbuilder.cmd -builderFile dbws-builder.xml -stageDir output_directory -packageAs wls testPLSQLFunction.war
where
-
dbws-builder.xml
is the DBWS builder configuration file (as shown previously). -
output_directory
is the output directory for the generated files. -
-packageAs
is the platform on which the web service will be deployed.
The generated eclipselink-dbws-schema.xsd
file follows:
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:plsqlfunction" xmlns="urn:plsqlfunction" elementFormDefault="qualified"> <xsd:complexType name="SOMEPACKAGE_TBL1"> <xsd:sequence> <xsd:element name="item" type="xsd:string" maxOccurs="unbounded" nillable="true"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="SOMEPACKAGE_TBL2"> <xsd:sequence> <xsd:element name="item" type="xsd:decimal" maxOccurs="unbounded" nillable="true"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="SOMEPACKAGE_ARECORD"> <xsd:sequence> <xsd:element name="t1"> <xsd:complexType> <xsd:sequence> <xsd:element name="item" type="xsd:string" maxOccurs="unbounded" nillable="true"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="t2"> <xsd:complexType> <xsd:sequence> <xsd:element name="item" type="xsd:decimal" maxOccurs="unbounded" nillable="true"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="t3" type="xsd:boolean" nillable="true"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="simple-xml-format"> <xsd:sequence> <xsd:any minOccurs="0"/> </xsd:sequence> </xsd:complexType> <xsd:element name="SOMEPACKAGE_TBL1" type="SOMEPACKAGE_TBL1"/> <xsd:element name="SOMEPACKAGE_TBL2" type="SOMEPACKAGE_TBL2"/> <xsd:element name="SOMEPACKAGE_ARECORD" type="SOMEPACKAGE_ARECORD"/> </xsd:schema>
Creating from an Overloaded PL/SQL Stored Procedure
Starting in release 2.3, EclipseLInk DBWS can create a web service that exposes multiple PL/SQL stored procedures. Instead of specifying all the stored procedures within the DBWS builder file, you can specify a single procedure name and "overload" it with different parameters.
Note:
This feature requires a database, such as Oracle, that supports overloading.
Example
In this example, the stored procedure contains different parameters:
CREATE PROCEDURE P(SIMPLARRAY IN TBL1, FOO IN VARCHAR2) AS BEGIN -- 2 arguments SIMPLARRAY and FOO END P; CREATE PROCEDURE P(SIMPLARRAY IN TBL1, FOO IN VARCHAR2, BAR IN VARCHAR2) AS BEGIN -- (same name 'P') 3 arguments SIMPLARRAY, FOO and BAR END P;
EclipseLink DBWS supports any combination of the IN
, OUT
and IN OUT
arguments.
Type TBL1 is defined in PL/SQL Package SOMEPACKAGE
as follows:
CREATE OR REPLACE PACKAGE SOMEPACKAGE AS TYPE TBL1 IS TABLE OF VARCHAR2(111) INDEX BY BINARY_INTEGER; PROCEDURE P(SIMPLARRAY IN TBL1, FOO IN VARCHAR2); PROCEDURE P(SIMPLARRAY IN TBL1, FOO IN VARCHAR2, BAR IN VARCHAR2); END SOMEPACKAGE;
The DBWSBuilder
utility requires a DBWS configuration file as input, as shown here:
<?xml version="1.0" encoding="UTF-8"?> <dbws-builder xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <properties> <property name="projectName">testOverloadedProcedure</property> ... database properties </properties> <plsql-procedure name="overloadedProcedure" catalogPattern="SOMEPACKAGE" procedurePattern="P" /> </dbws-builder>
Use this command to execute the DBWSBuilder
:
prompt > dbwsbuilder.cmd -builderFile dbws-builder.xml -stageDir output_directory -packageAs wls testEcho.war
where
-
dbws-builder.xml
– The DBWS configuration file (as shown previously) -
output_directory
– The output directory for the generated files -
-packageAs
– Specifies the platform on which the web service will be deployed
When generating queries and the WSDL in which overloaded procedures are used, a unique index identifies each procedure. The index starts at 1 and increments by one, for each overloaded procedure.
In this example, EclipseLink generates the following eclipselink-dbws.wsdl
(Web Services Description Language):
<wsdl:definitions name="plsqloverloadService" targetNamespace="urn:plsqloverloadService" xmlns:ns1="urn:plsqloverload" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="urn:plsqloverloadService" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" > <wsdl:types> <xsd:schema elementFormDefault="qualified" targetNamespace="urn:plsqloverloadService" xmlns:tns="urn:plsqloverloadService" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:import namespace="urn:plsqloverload" schemaLocation="eclipselink-dbws-schema.xsd"/> <xsd:complexType name="p1ResponseType"> <xsd:sequence> <xsd:element name="result"> <xsd:complexType><xsd:sequence><xsd:any/></xsd:sequence></xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> <xsd:complexType name="p1RequestType"> <xsd:sequence> <xsd:element name="SIMPLARRAY" type="ns1:SOMEPACKAGE_TBL1"/> <xsd:element name="FOO" type="xsd:string"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="p2ResponseType"> <xsd:sequence> <xsd:element name="result"> <xsd:complexType><xsd:sequence><xsd:any/></xsd:sequence></xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> <xsd:complexType name="p2RequestType"> <xsd:sequence> <xsd:element name="SIMPLARRAY" type="ns1:SOMEPACKAGE_TBL1"/> <xsd:element name="FOO" type="xsd:string"/> <xsd:element name="BAR" type="xsd:string"/> </xsd:sequence> </xsd:complexType> <xsd:element name="p2" type="tns:p2RequestType"/> <xsd:element name="p1" type="tns:p1RequestType"/> <xsd:element name="p1Response" type="tns:p1ResponseType"/> <xsd:element name="p2Response" type="tns:p2ResponseType"/> </xsd:schema> </wsdl:types> <wsdl:message name="p2Request"><wsdl:part name="p2Request" element="tns:p2"/></wsdl:message> <wsdl:message name="p2Response"><wsdl:part name="p2Response" element="tns:p2Response"/></wsdl:message> <wsdl:message name="p1Request"><wsdl:part name="p1Request" element="tns:p1"/></wsdl:message> <wsdl:message name="p1Response"><wsdl:part name="p1Response" element="tns:p1Response"/></wsdl:message> <wsdl:portType name="plsqloverloadService_Interface"> <wsdl:operation name="p2"> <wsdl:input message="tns:p2Request"/> <wsdl:output message="tns:p2Response"/> </wsdl:operation> <wsdl:operation name="p1"> <wsdl:input message="tns:p1Request"/> <wsdl:output message="tns:p1Response"/> </wsdl:operation> </wsdl:portType> <wsdl:binding name="plsqloverloadService_SOAP_HTTP" type="tns:plsqloverloadService_Interface"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="p2"> <soap:operation soapAction="urn:plsqloverloadService:p2"/> <wsdl:input><soap:body use="literal"/></wsdl:input> <wsdl:output><soap:body use="literal"/></wsdl:output> </wsdl:operation> <wsdl:operation name="p1"> <soap:operation soapAction="urn:plsqloverloadService:p1"/> <wsdl:input><soap:body use="literal"/></wsdl:input> <wsdl:output><soap:body use="literal"/></wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="plsqloverloadService"> <wsdl:port name="plsqloverloadServicePort" binding="tns:plsqloverloadService_SOAP_HTTP"> <soap:address location="REPLACE_WITH_ENDPOINT_ADDRESS"/> </wsdl:port> </wsdl:service> </wsdl:definitions>
Footnote Legend
Footnote 1:Same algorithm documented as part of the SQL/X (a.k.a. SQL/XML:2003) specification.