Oracle® Database JPublisher User's Guide 10g Release 1 (10.1) Part Number B10983-01 |
|
|
View PDF |
This appendix contains generated code examples that do not fit conveniently into the corresponding sections earlier in the manual:
This section contains generated code for the example in "JPublisher-Generated Subclasses for Java-to-Java Type Transformations". This example uses style files and holder classes in generating a user subclass that supports PL/SQL output arguments and uses Java types supported by Web services.
To review, this example shows the JPublisher-generated interface, base class, and user subclass to publish the following PL/SQL package foo_pack
, consisting of the stored function foo
, using Java types suitable for Web services:
create or replace package foo_pack as function foo(a IN OUT sys.xmltype, b integer) return CLOB; end; /
Assume that you translate the foo_pack
package as follows:
% jpub -u scott/tiger -s foo_pack:FooPack -style=webservices10
Note the following:
The SQL type xmltype
is initially mapped to the Java type oracle.sql.SimpleXMLType
in the JPublisher type map.
SimpleXMLType
is mapped to javax.xml.transform.Source
in the style file webservices10.properties
, for use in Web services. (See "Support for XMLTYPE".)
The holder class for Source
data, javax.xml.rpc.holders.SourceHolder
, is used for the output Source
argument. (See "Passing Output Parameters in JAX-RPC Holders".)
The style file specifies the generated code naming pattern "%2Base:%2User#%2
" relating to the JPublisher command "-s foo_pack:FooPack
", which results in generation of interface code in FooPack.java
, base class code in FooPackBase.java
, and user subclass code in FooPackUser.java
.
The wrapper method foo()
in the user subclass FooPackUser
uses the following type transformation functionality and a call to the corresponding _foo()
method of the generated base class, which is where the JDBC calls occur to invoke the wrapped stored function foo
:
foo (SourceHolder, Integer) { SourceHolder -> Source Source -> SimpleXMLType _foo (SimpleXMLType[], Integer); SimpleXMLType -> Source Source -> SourceHolder }
This is code for the Java interface that JPublisher generates in FooPack.java
.
import java.sql.SQLException; import sqlj.runtime.ref.DefaultContext; import sqlj.runtime.ConnectionContext; import java.sql.Connection; // Ensure that the java.io.* package etc. is imported. import java.io.*; public interface FooPack extends java.rmi.Remote { public java.lang.String foo(SourceHolder _xa_inout_x, Integer b) throws java.rmi.RemoteException; }
This is code for the base class that JPublisher generates in FooPackBase.java
. The _foo()
method is called by the foo()
method of the user subclass and uses JDBC to invoke the foo
stored function of the foo_pack
PL/SQL package that JPublisher is publishing.
Comments indicate corresponding SQLJ code, which JPublisher translates automatically during generation of the class.
import java.sql.SQLException; import sqlj.runtime.ref.DefaultContext; import sqlj.runtime.ConnectionContext; import java.sql.Connection; // Ensure that the java.io.* package etc. is imported. import java.io.*; public class FooPackBase { /* connection management */ protected DefaultContext __tx = null; protected Connection __onn = null; public void _setConnectionContext(DefaultContext ctx) throws SQLException { release(); __tx = ctx; ctx.setStmtCacheSize(0); ctx.setDefaultStmtCacheSize(0); if (ctx.getConnection() instanceof oracle.jdbc.OracleConnection) { try { java.lang.reflect.Method m = ctx.getConnection().getClass().getMethod("setExplicitCachingEnabled", new Class[]{Boolean.TYPE}); m.invoke(ctx.getConnection(), new Object[]{Boolean.FALSE}); } catch(Exception e) { /* do nothing for pre-9.2 JDBC drivers*/ } }} public DefaultContext _getConnectionContext() throws SQLException { if (__tx==null) { __tx = (__onn==null) ? DefaultContext.getDefaultContext() : new DefaultContext(__onn); } return __tx; }; public Connection _getConnection() throws SQLException { return (__onn==null) ? ((__tx==null) ? null : __tx.getConnection()) : __onn; } public void release() throws SQLException { if (__tx!=null && __onn!=null) __tx.close(ConnectionContext.KEEP_CONNECTION); __onn = null; __tx = null; } /* constructors */ public FooPackBase() throws SQLException { __tx = DefaultContext.getDefaultContext(); } public FooPackBase(DefaultContext c) throws SQLException { __tx = c; } public FooPackBase(Connection c) throws SQLException {__onn = c; __tx = new DefaultContext(c); } /* *** _foo() USES JDBC TO INVOKE WRAPPED foo STORED PROCEDURE *** */ public oracle.sql.CLOB _foo ( oracle.sql.SimpleXMLType a[], Integer b) throws SQLException { oracle.sql.CLOB __jPt_result; // ************************************************************ // #sql [_getConnectionContext()] __jPt_result = { VALUES(SCOTT.FOO_PACK.FOO( // :a[0], // :b)) }; // ************************************************************ { // declare temps oracle.jdbc.OracleCallableStatement __sJT_st = null; sqlj.runtime.ref.DefaultContext __sJT_cc = _getConnectionContext(); if (__sJT_cc==null) sqlj.runtime.error.RuntimeRefErrors.raise_NULL_CONN_CTX(); sqlj.runtime.ExecutionContext.OracleContext __sJT_ec = ((__sJT_cc.getExecutionContext()==null) ? sqlj.runtime.ExecutionContext.raiseNullExecCtx() : __sJT_cc.getExecutionContext().getOracleContext()); try { String theSqlTS = "BEGIN :1 := SCOTT.FOO_PACK.FOO (\n :2 ,\n :3 ) \n; END;"; __sJT_st = __sJT_ec.prepareOracleCall(__sJT_cc,"0FooPackBase",theSqlTS); if (__sJT_ec.isNew()) { __sJT_st.registerOutParameter(1, Oracle.jdbc.OracleTypes.CLOB); __sJT_st.registerOutParameter(2,2007,"SYS.XMLTYPE"); } // set IN parameters if (a[0]==null) __sJT_st.setNull(2,2007,"SYS.XMLTYPE"); else __sJT_st.setORAData(2,a[0]); if (b == null) __sJT_st.setNull(3, Oracle.jdbc.OracleTypes.INTEGER); else __sJT_st.setInt(3,b.intValue()); // execute statement __sJT_ec.oracleExecuteUpdate(); // retrieve OUT parameters __jPt_result = (oracle.sql.CLOB) __sJT_st.getCLOB(1); a[0] = (oracle.sql.SimpleXMLType)__sJT_st.getORAData (2, Oracle.sql.SimpleXMLType.getORADataFactory()); } finally { __sJT_ec.oracleClose(); } } // ************************************************************ return __jPt_result; } }
This is code for the user subclass that JPublisher generates in FooPackUser.java
. The foo()
method calls the _foo()
method of the base class. Java-to-Java transformations are handled in try
blocks as indicated in code comments.
This class extends the class FooPackBase
and implements the interface FooPack
.
import java.sql.SQLException; import sqlj.runtime.ref.DefaultContext; import sqlj.runtime.ConnectionContext; import java.sql.Connection; // Ensure that the java.io.* package etc. is imported. import java.io.*; public class FooPackUser extends FooPackBase implements FooPack, java.rmi.Remote { /* constructors */ public FooPackUser() throws SQLException { super(); } public FooPackUser(DefaultContext c) throws SQLException { super(c); } public FooPackUser(Connection c) throws SQLException { super(c); } /* superclass methods */ public java.lang.String foo(SourceHolder _xa_inout_x, Integer b) throws java.rmi.RemoteException { oracle.sql.CLOB __jRt_0 = null; java.lang.String __jRt_1 = null; /* *** FOLLOWING try BLOCK CONVERTS SourceHolder TO Source *** */ try { javax.xml.transform.Source[] a_inout; // allocate an array for holding the OUT value a_inout = new javax.xml.transform.Source[1]; if (_xa_inout_x!=null) a_inout[0] = _xa_inout_x.value; oracle.sql.SimpleXMLType[] xa_inoutx; xa_inoutx = new oracle.sql.SimpleXMLType[1]; /* *** FOLLOWING try BLOCK TRANSFORMS Source TO SimpleXMLType *** */ try { javax.xml.transform.Transformer trans = javax.xml.transform.TransformerFactory.newInstance().newTransformer(); xa_inoutx[0] = null; if (a_inout[0]!=null) { java.io.ByteArrayOutputStream buf = new java.io.ByteArrayOutputStream(); javax.xml.transform.stream.StreamResult streamr = new javax.xml.transform.stream.StreamResult(buf); trans.transform(a_inout[0], streamr); xa_inoutx[0] = new oracle.sql.SimpleXMLType(_getConnection()); xa_inoutx[0] = xa_inoutx[0].createxml(buf.toString()); } } catch (java.lang.Throwable t) { throw OC4JWsDebugPrint(t); } /* *** CALL _foo() FROM BASE CLASS (SUPER CLASS) *** */ __jRt_0 = super._foo(xa_inoutx, b); /* *** FOLLOWING try BLOCK TRANSFORMS SimpleXMLType TO Source *** */ try { javax.xml.parsers.DocumentBuilder db = javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder(); a_inout[0] = null; if (xa_inoutx[0]!=null) { org.w3c.dom.Document _tmpDocument_ = db.parse (new java.io.ByteArrayInputStream(xa_inoutx[0].getstringval().getBytes())); a_inout[0]= new javax.xml.transform.dom.DOMSource(_tmpDocument_); } } catch (java.lang.Throwable t) { throw OC4JWsDebugPrint(t); } /* *** FOLLOWING CODE CONVERTS Source TO SourceHolder *** */ // convert OUT value to a holder if (a_inout!=null) _xa_inout_x.value = a_inout[0]; if (__jRt_0==null) { __jRt_1=null; } else { __jRt_1=readerToString(__jRt_0.getCharacterStream()); } } catch (Exception except) { try { Class sutil = Class.forName("com.evermind.util.SystemUtils"); java.lang.reflect.Method getProp = sutil.getMethod("getSystemBoolean", new Class[]{String.class, Boolean.TYPE}); if (((Boolean)getProp.invoke(null, new Object[]{"ws.debug", Boolean.FALSE})).booleanValue()) except.printStackTrace(); } catch (Throwable except2) {} throw new java.rmi.RemoteException(except.getMessage(), except); } return __jRt_1; } private java.lang.String readerToString(java.io.Reader r) throws java.sql.SQLException { CharArrayWriter caw = new CharArrayWriter(); try { //Read from reader and write to writer boolean done = false; while (!done) { char[] buf = new char[4096]; int len = r.read(buf, 0, 4096); if(len == -1) { done = true; } else { caw.write(buf,0,len); } } } catch(Throwable t) { throw OC4JWsDebugPrint(t); } return caw.toString(); } private void populateClob(oracle.sql.CLOB clb, java.lang.String data) throws Exception { java.io.Writer writer = clb.getCharacterOutputStream(); writer.write(data.toCharArray()); writer.flush(); writer.close(); } private boolean OC4JWsDebug() { boolean debug = false; try { // Server-side Debug Info for "java -Dws.debug=true -jar oc4j.jar" Class sutil = Class.forName("com.evermind.util.SystemUtils"); java.lang.reflect.Method getProp = sutil.getMethod("getSystemBoolean", new Class[]{String.class, Boolean.TYPE}); if (((Boolean)getProp.invoke(null, new Object[]{"ws.debug", Boolean.FALSE})).booleanValue()) { debug = true; } } catch (Throwable except2) {} return debug; } private java.sql.SQLException OC4JWsDebugPrint(Throwable t) { java.sql.SQLException t0 = new java.sql.SQLException(t.getMessage()); if (!OC4JWsDebug()) return t0; t.printStackTrace(); try { java.lang.reflect.Method getST = Exception.class.getMethod("getStackTrace", new Class[]{}); java.lang.reflect.Method setST = Exception.class.getMethod("setStackTrace", new Class[]{}); setST.invoke(t0, new Object[]{getST.invoke(t, new Object[]{})}); } catch (Throwable th){} return t0; } }
This section contains a generated code example for a specified SQL statement, relating to the discussion in "Declaration of SQL Statements to Translate (-sqlstatement)".
The example is for the following sample settings of the -sqlstatement
option:
-sqlstatement.class=MySqlStatements -sqlstatement.getEmp="select ename from emp where ename=:{myname VARCHAR}" -sqlstatement.return=both
Note the following for this example:
Code comments show #sql
statements that correspond to the translated code shown.
The getEmpBeans()
method, generated because of the -sqlstatement.return=both
setting, returns an array of JavaBeans. Each element represents a row of the result set. The GetEmpRow
class is defined for this purpose.
JPublisher generates a SQLJ class. The result set is mapped to a SQLJ iterator.
(For UPDATE
, INSERT
, or DELETE
statements, code is generated both with and without batching for array binds.)
Here is the translated SQLJ code that JPublisher would produce:
public class MySqlStatements_getEmpRow { /* connection management */ /* constructors */ public MySqlStatements_getEmpRow() { } public String getEname() throws java.sql.SQLException { return ename; } public void setEname(String ename) throws java.sql.SQLException { this.ename = ename; } private String ename; } /*@lineinfo:filename=MySqlStatements*/ /*@lineinfo:user-code*/ /*@lineinfo:1^1*/ import java.sql.SQLException; import sqlj.runtime.ref.DefaultContext; import sqlj.runtime.ConnectionContext; import java.sql.Connection; import oracle.sql.*; public class MySqlStatements { /* connection management */ protected DefaultContext __tx = null; protected Connection __onn = null; public void setConnectionContext(DefaultContext ctx) throws SQLException { release(); __tx = ctx; } public DefaultContext getConnectionContext() throws SQLException { if (__tx==null) { __tx = (__onn==null) ? DefaultContext.getDefaultContext() : new DefaultContext(__onn); } return __tx; }; public Connection getConnection() throws SQLException { return (__onn==null) ? ((__tx==null) ? null : __tx.getConnection()) : __onn; } public void release() throws SQLException { if (__tx!=null && __onn!=null) __tx.close(ConnectionContext.KEEP_CONNECTION); __onn = null; __tx = null; } /* constructors */ public MySqlStatements() throws SQLException { __tx = DefaultContext.getDefaultContext(); } public MySqlStatements(DefaultContext c) throws SQLException { __tx = c; } public MySqlStatements(Connection c) throws SQLException {__onn = c; __tx = new DefaultContext(c); } /*@lineinfo:generated-code*/ /*@lineinfo:36^1*/ // ************************************************************ // SQLJ iterator declaration: // ************************************************************ public static class getEmpIterator extends sqlj.runtime.ref.ResultSetIterImpl implements sqlj.runtime.NamedIterator { public getEmpIterator(sqlj.runtime.profile.RTResultSet resultSet) throws java.sql.SQLException { super(resultSet); enameNdx = findColumn("ename"); m_rs = (oracle.jdbc.OracleResultSet) resultSet.getJDBCResultSet(); } private oracle.jdbc.OracleResultSet m_rs; public String ename() throws java.sql.SQLException { return m_rs.getString(enameNdx); } private int enameNdx; } // ************************************************************ /*@lineinfo:user-code*/ /*@lineinfo:36^56*/ public MySqlStatements_getEmpRow[] getEmpBeans (String myname) throws SQLException { getEmpIterator iter; /*@lineinfo:generated-code*/ /*@lineinfo:43^5*/ // ************************************************************ // #sql [getConnectionContext()] // iter = { select ename from emp where ename=:myname }; // ************************************************************ { // declare temps oracle.jdbc.OraclePreparedStatement __sJT_st = null; sqlj.runtime.ref.DefaultContext __sJT_cc = getConnectionContext(); if (__sJT_c c==null) sqlj.runtime.error.RuntimeRefErrors.raise_NULL_CONN_CTX(); sqlj.runtime.ExecutionContext.OracleContext __sJT_ec = ((__sJT_cc.getExecutionContext()==null) ? sqlj.runtime.ExecutionContext.raiseNullExecCtx() : __sJT_cc.getExecutionContext().getOracleContext()); try { String theSqlTS = "select ename from emp where ename= :1"; __sJT_st = __sJT_ec.prepareOracleStatement (__sJT_cc,"0MySqlStatements",theSqlTS); // set IN parameters __sJT_st.setString(1,myname); // execute query iter = new MySqlStatements.getEmpIterator (new sqlj.runtime.ref.OraRTResultSet (__sJT_ec.oracleExecuteQuery(),__sJT_st,"0MySqlStatements",null)); } finally { __sJT_ec.oracleCloseQuery(); } } // ************************************************************ /*@lineinfo:user-code*/ /*@lineinfo:43^84*/ java.util.Vector v = new java.util.Vector(); while (iter.next()) { MySqlStatements_getEmpRow r = new MySqlStatements_getEmpRow(); r.setEname(iter.ename()); v.addElement(r); } MySqlStatements_getEmpRow[] __jPt_result = new MySqlStatements_getEmpRow[v.size()]; for (int i = 0; i < v.size(); i++) __jPt_result[i] = (MySqlStatements_getEmpRow) v.elementAt(i); return __jPt_result; } public java.sql.ResultSet getEmp (String myname) throws SQLException { sqlj.runtime.ResultSetIterator iter; /*@lineinfo:generated-code*/ /*@lineinfo:62^5*/ // ************************************************************ // #sql [getConnectionContext()] iter = // { select ename from emp where ename=:myname }; // ************************************************************ { // declare temps oracle.jdbc.OraclePreparedStatement __sJT_st = null; sqlj.runtime.ref.DefaultContext __sJT_cc = getConnectionContext(); if (__sJT_c c==null) sqlj.runtime.error.RuntimeRefErrors.raise_NULL_CONN_CTX(); sqlj.runtime.ExecutionContext.OracleContext __sJT_ec = ((__sJT_cc.getExecutionContext()==null) ? sqlj.runtime.ExecutionContext.raiseNullExecCtx() : __sJT_cc.getExecutionContext().getOracleContext()); try { String theSqlTS = "select ename from emp where ename= :1"; __sJT_st = __sJT_ec.prepareOracleStatement (__sJT_cc,"1MySqlStatements",theSqlTS); // set IN parameters __sJT_st.setString(1,myname); // execute query iter = new sqlj.runtime.ref.ResultSetIterImpl (new sqlj.runtime.ref.OraRTResultSet (__sJT_ec.oracleExecuteQuery(),__sJT_st,"1MySqlStatements",null)); } finally { __sJT_ec.oracleCloseQuery(); } } // ************************************************************ /*@lineinfo:user-code*/ /*@lineinfo:62^84*/ java.sql.ResultSet __jPt_result = iter.getResultSet(); return __jPt_result; } } /*@lineinfo:generated-code*/
This section contains code examples for JAX-RPC client proxies and the associated Java and PL/SQL wrappers, generated according to the WSDL document indicated by the -proxywsdl
setting. The code in this example is for use with an EJB Web service, and also uses a table function. The following are included:
WSDL document
JPublisher accesses the WSDL document, the content of which determines the JAX-RPC client proxy classes to generate.
JAX-RPC client proxy stub class, an associated factory class, and the interfaces they implement
These classes and interfaces are generated by the Oracle Database Web services assembler tool, which is invoked by JPublisher. Resulting proxy classes and interfaces are loaded into the database. The client proxy stub class is used for invoking the Web service.
Java wrapper class and PL/SQL wrapper
These wrappers are generated by JPublisher for use in the database. Use the PL/SQL wrapper to access the client proxy class from PL/SQL. The client proxy class, in turn, invokes the Web service. The wrapper class is a required intermediate layer to publish instance methods of the client proxy class as static methods, because PL/SQL supports only static methods.
Associated PL/SQL utility scripts
These scripts are generated by JPublisher. The scripts are to create the PL/SQL wrapper in the database schema, grant permission to execute it, revoke that permission, and drop the PL/SQL wrapper from the database schema.
For this example, assume that a JAX-RPC Web service, called HelloServiceEJB
, is deployed to the following endpoint:
http://localhost:8888/javacallout/javacallout
The WSDL document for this Web service is at the following location:
http://localhost:8888/javacallout/javacallout?WSDL
The Web service provides an operation called getProperty
that takes a Java string specifying the name of a system property, and returns the value of that property. For example, getProperty("os.name")
may return "SunOS
".Based on the WSDL description of the Web service, JPublisher can direct the generation of a Web service client proxy, and generate Java and PL/SQL wrappers for the client proxy. Here is the command to perform these functions:
% jpub -user=scott/tiger -sysuser=sys/change_on_install -url=jdbc:oracle:thin:@localhost:1521:orcl -proxywsdl=http://localhost:8888/javacallout/javacallout?WSDL -endpoint=http://localhost:8888/javacallout/javacallout -proxyopts=jaxrpc,tabfun -package=javacallout -dir=genproxy
The -proxyopts
setting directs the generation of the JAX-RPC client proxy and wrappers, and the use of a table function to wrap the Web service operation. The -url
setting indicates the database, and the -user
setting indicates the schema, where JPublisher loads the generated Java and PL/SQL wrappers. The -sysuser
setting specifies the SYS
account that has the privileges to grant permissions to execute the wrapper script.
See "WSDL Document for Java and PL/SQL Wrapper Generation (-proxywsdl)" and "Web Services Endpoint (-endpoint)" for information about those options. The -endpoint
setting is used in the Java wrapper class that JPublisher generates, shown in "Java Wrapper Class and PL/SQL Wrapper". See "Code Generation for Table Functions" for general information about table functions.
For more Java and PL/SQL wrapper examples, also see "Generated Code: Java and PL/SQL Wrappers for General Use".
This section contains the WSDL document for the Web service. HelloServiceInf
in the <message>
element is the name of the service bean and determines the name of the interface that is generated and that is implemented by the generated JAX-RPC client proxy stub class. The HelloServiceInf
interface has the following signature:
public interface HelloServiceInf extends java.rmi.Remote { public String getProperty(String prop) throws java.rmi.RemoteException; }
The method getProperty()
corresponds to the getProperty
operation specified in the WSDL document. It returns the value of a specified system property (prop
). For example, specify the property "os.version
" to return the operating system version.
<?xml version="1.0" encoding="UTF-8"?> <definitions name="HelloServiceEJB" targetNamespace="http://oracle.j2ee.ws/javacallout/Hello" xmlns:tns="http://oracle.j2ee.ws/javacallout/Hello" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"> <types/> <message name="HelloServiceInf_getProperty"> <part name="String_1" type="xsd:string"/> </message> <message name="HelloServiceInf_getPropertyResponse"> <part name="result" type="xsd:string"/> </message> <portType name="HelloServiceInf"> <operation name="getProperty" parameterOrder="String_1"> <input message="tns:HelloServiceInf_getProperty"/> <output message="tns:HelloServiceInf_getPropertyResponse"/> </operation> </portType> <binding name="HelloServiceInfBinding" type="tns:HelloServiceInf"> <operation name="getProperty"> <input> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="encoded" namespace="http://oracle.j2ee.ws/javacallout/Hello"/> </input> <output> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="encoded" namespace="http://oracle.j2ee.ws/javacallout/Hello"/> </output> <soap:operation soapAction=""/> </operation> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/> </binding> <service name="HelloServiceEJB"> <port name="HelloServiceInfPort" binding="tns:HelloServiceInfBinding"> <soap:address location="/javacallout"/> </port> </service> </definitions>
This section shows the JAX-RPC client proxy stub class, the interface that it implements, a factory class to produce instances of the stub class, and the interface that the factory class implements. These classes and interfaces are all generated by the Oracle Database Web services assembler tool, which is invoked by JPublisher. The stub class is for invoking the Web service, through Java and PL/SQL wrappers that JPublisher produces.
Here is code for the interface, HelloServiceInf
, implemented by the JAX-RPC client proxy stub class, HelloServiceInf_Stub
, which is shown immediately following.
// !DO NOT EDIT THIS FILE! // This source file is generated by Oracle tools // Contents may be subject to change // For reporting problems, use the following // Version = [failed to localize] wscompile.version(Oracle WebServices, 10i, J1) package javacallout; public interface HelloServiceInf extends java.rmi.Remote { public java.lang.String getProperty(java.lang.String string_1) throws java.rmi.RemoteException;}
Here is code for the JAX-RPC client proxy stub class, HelloServiceInf_Stub
. It implements the interface HelloServiceInf
, shown immediately preceding.
// !DO NOT EDIT THIS FILE! // This source file is generated by Oracle tools // Contents may be subject to change // For reporting problems, use the following // Version = [failed to localize] wscompile.version(Oracle WebServices, 10i, J1) package javacallout; import oracle.j2ee.ws.server.MessageContextProperties; import oracle.j2ee.ws.common.streaming.*; import oracle.j2ee.ws.common.encoding.*; import oracle.j2ee.ws.common.encoding.soap.SOAPConstants; import oracle.j2ee.ws.common.encoding.soap.SOAP12Constants; import oracle.j2ee.ws.common.encoding.literal.*; import oracle.j2ee.ws.common.soap.streaming.*; import oracle.j2ee.ws.common.soap.message.*; import oracle.j2ee.ws.common.soap.SOAPVersion; import oracle.j2ee.ws.common.soap.SOAPEncodingConstants; import oracle.j2ee.ws.common.wsdl.document.schema.SchemaConstants; import javax.xml.namespace.QName; import java.rmi.RemoteException; import java.util.Iterator; import java.lang.reflect.*; import oracle.j2ee.ws.client.SenderException; import oracle.j2ee.ws.client.*; import oracle.j2ee.ws.client.http.*; import javax.xml.rpc.handler.*; import javax.xml.rpc.JAXRPCException; import javax.xml.rpc.soap.SOAPFaultException; public class HelloServiceInf_Stub extends oracle.j2ee.ws.client.StubBase implements javacallout.HelloServiceInf { /* * public constructor */ public HelloServiceInf_Stub(HandlerChain handlerChain) { super(handlerChain); _setProperty(ENDPOINT_ADDRESS_PROPERTY, "http://localhost:8888/javacallout/javacallout"); } /* * implementation of getProperty */ public java.lang.String getProperty(java.lang.String string_1) throws java.rmi.RemoteException { try { StreamingSenderState _state = _start(_handlerChain); InternalSOAPMessage _request = _state.getRequest(); _request.setOperationCode(getProperty_OPCODE); javacallout.HelloServiceInf_getProperty_RequestStruct _myHelloServiceInf_getProperty_RequestStruct = new javacallout.HelloServiceInf_getProperty_RequestStruct(); _myHelloServiceInf_getProperty_RequestStruct.setString_1(string_1); SOAPBlockInfo _bodyBlock = new SOAPBlockInfo(ns1_getProperty_getProperty_QNAME); _bodyBlock.setValue(_myHelloServiceInf_getProperty_RequestStruct); _bodyBlock.setSerializer (myHelloServiceInf_getProperty_RequestStruct_SOAPSerializer); _request.setBody(_bodyBlock); _state.getMessageContext().setProperty("http.soap.action", ""); _send((String) _getProperty(ENDPOINT_ADDRESS_PROPERTY), _state); javacallout.HelloServiceInf_getProperty_ResponseStruct _myHelloServiceInf_getProperty_ResponseStruct = null; Object _responseObj = _state.getResponse().getBody().getValue(); if (_responseObj instanceof SOAPDeserializationState) { _myHelloServiceInf_getProperty_ResponseStruct = (javacallout.HelloServiceInf_getProperty_ResponseStruct) ((SOAPDeserializationState)_responseObj).getInstance(); } else { _myHelloServiceInf_getProperty_ResponseStruct = (javacallout.HelloServiceInf_getProperty_ResponseStruct)_responseObj; } return _myHelloServiceInf_getProperty_ResponseStruct.getResult(); } catch (RemoteException e) { // let this one through unchanged throw e; } catch (JAXRPCException e) { throw new RemoteException(e.getMessage(), e); } catch (Exception e) { if (e instanceof RuntimeException) { throw (RuntimeException)e; } else { throw new RemoteException(e.getMessage(), e); } } } /* * this method deserializes the request/response structure in the body */ protected void _readFirstBodyElement(XMLReader bodyReader, SOAPDeserializationContext deserializationContext, StreamingSenderState state) throws Exception { int opcode = state.getRequest().getOperationCode(); switch (opcode) { case getProperty_OPCODE: _deserialize_getProperty(bodyReader, deserializationContext, state); break; default: throw new SenderException("sender.response.unrecognizedOperation", Integer.toString(opcode)); } } /* * This method deserializes the body of the getProperty operation. */ private void _deserialize_getProperty(XMLReader bodyReader, SOAPDeserializationContext deserializationContext, StreamingSenderState state) throws Exception { Object myHelloServiceInf_getProperty_ResponseStructObj = myHelloServiceInf_getProperty_ResponseStruct_SOAPSerializer.deserialize (ns1_getProperty_getPropertyResponse_QNAME, bodyReader, deserializationContext); SOAPBlockInfo bodyBlock = new SOAPBlockInfo(ns1_getProperty_getPropertyResponse_QNAME); bodyBlock.setValue(myHelloServiceInf_getProperty_ResponseStructObj); state.getResponse().setBody(bodyBlock); } public String _getEncodingStyle() { return SOAPNamespaceConstants.ENCODING; } public void _setEncodingStyle(String encodingStyle) { throw new UnsupportedOperationException("cannot set encoding style"); } /* * This method returns an array containing (prefix, nsURI) pairs. */ protected String[] _getNamespaceDeclarations() { return myNamespace_declarations; } /* * This method returns an array containing the names of the headers * we understand. */ public QName[] _getUnderstoodHeaders() { return understoodHeaderNames; } public void _initialize(InternalTypeMappingRegistry registry) throws Exception { super._initialize(registry); myHelloServiceInf_getProperty_RequestStruct_SOAPSerializer = (CombinedSerializer)registry.getSerializer (SOAPConstants.NS_SOAP_ENCODING, javacallout.HelloServiceInf_getProperty_RequestStruct.class, ns1_getProperty_TYPE_QNAME); myHelloServiceInf_getProperty_ResponseStruct_SOAPSerializer = (CombinedSerializer)registry.getSerializer (SOAPConstants.NS_SOAP_ENCODING, javacallout.HelloServiceInf_getProperty_ResponseStruct.class, ns1_getPropertyResponse_TYPE_QNAME); } private static final QName _portName = new QName("http://oracle.j2ee.ws/javacallout/Hello", "HelloServiceInfPort"); private static final int getProperty_OPCODE = 0; private static final QName ns1_getProperty_getProperty_QNAME = new QName("http://oracle.j2ee.ws/javacallout/Hello", "getProperty"); private static final QName ns1_getProperty_TYPE_QNAME = new QName("http://oracle.j2ee.ws/javacallout/Hello", "getProperty"); private CombinedSerializer myHelloServiceInf_getProperty_RequestStruct_SOAPSerializer; private static final QName ns1_getProperty_getPropertyResponse_QNAME = new QName("http://oracle.j2ee.ws/javacallout/Hello", "getPropertyResponse"); private static final QName ns1_getPropertyResponse_TYPE_QNAME = new QName("http://oracle.j2ee.ws/javacallout/Hello", "getPropertyResponse"); private CombinedSerializer myHelloServiceInf_getProperty_ResponseStruct_SOAPSerializer; private static final String[] myNamespace_declarations = new String[] { "ns0", "http://oracle.j2ee.ws/javacallout/Hello" }; private static final QName[] understoodHeaderNames = new QName[] { };}
Here is the code for the interface, HelloServiceEJB
, implemented by the client proxy factory class, HelloServiceEJB_Impl
, which is shown immediately following.
// !DO NOT EDIT THIS FILE! // This source file is generated by Oracle tools // Contents may be subject to change // For reporting problems, use the following // Version = [failed to localize] wscompile.version(Oracle WebServices, 10i, J1) package javacallout; import javax.xml.rpc.*; public interface HelloServiceEJB extends javax.xml.rpc.Service { public javacallout.HelloServiceInf getHelloServiceInfPort();}
Here is code for the client proxy factory class, HelloServiceEJB_Impl
, used to create instances of the client proxy stub class, HelloServiceInf_Stub
, which is shown earlier in this section. The HelloServiceEJB_Impl
class implements the HelloServiceEJB
interface, shown immediately preceding.
// !DO NOT EDIT THIS FILE! // This source file is generated by Oracle tools // Contents may be subject to change // For reporting problems, use the following // Version = null package javacallout; import oracle.j2ee.ws.common.encoding.*; import oracle.j2ee.ws.client.ServiceExceptionImpl; import oracle.j2ee.ws.common.util.exception.*; import oracle.j2ee.ws.common.soap.SOAPVersion; import oracle.j2ee.ws.client.HandlerChainImpl; import javax.xml.rpc.*; import javax.xml.rpc.encoding.*; import javax.xml.rpc.handler.HandlerChain; import javax.xml.rpc.handler.HandlerInfo; import javax.xml.namespace.QName; public class HelloServiceEJB_Impl extends oracle.j2ee.ws.client.BasicService implements HelloServiceEJB { private static final QName serviceName = new QName("http://oracle.j2ee.ws/javacallout/Hello", "HelloServiceEJB"); private static final QName ns1_HelloServiceInfPort_QNAME = new QName("http://oracle.j2ee.ws/javacallout/Hello", "HelloServiceInfPort"); private static final Class helloServiceInf_PortClass = javacallout.HelloServiceInf.class; public HelloServiceEJB_Impl() { super(serviceName, new QName[] { ns1_HelloServiceInfPort_QNAME }, new javacallout.HelloServiceEJB_SerializerRegistry().getRegistry()); } public java.rmi.Remote getPort(QName portName, Class serviceDefInterface) throws javax.xml.rpc.ServiceException { try { if (portName.equals(ns1_HelloServiceInfPort_QNAME) && serviceDefInterface.equals(helloServiceInf_PortClass)) { return getHelloServiceInfPort(); } } catch (Exception e) { throw new ServiceExceptionImpl(new LocalizableExceptionAdapter(e)); } return super.getPort(portName, serviceDefInterface); } public java.rmi.Remote getPort(Class serviceDefInterface) throws javax.xml.rpc.ServiceException { try { if (serviceDefInterface.equals(helloServiceInf_PortClass)) { return getHelloServiceInfPort(); } } catch (Exception e) { throw new ServiceExceptionImpl(new LocalizableExceptionAdapter(e)); } return super.getPort(serviceDefInterface); } public javacallout.HelloServiceInf getHelloServiceInfPort() { String[] roles = new String[] {}; HandlerChainImpl handlerChain = new HandlerChainImpl (getHandlerRegistry().getHandlerChain(ns1_HelloServiceInfPort_QNAME)); handlerChain.setRoles(roles); javacallout.HelloServiceInf_Stub stub = new javacallout.HelloServiceInf_Stub(handlerChain); try { stub._initialize(super.internalTypeRegistry); } catch (JAXRPCException e) { throw e; } catch (Exception e) { throw new JAXRPCException(e.getMessage(), e); } return stub; }}
This section shows code for the Java wrapper class and PL/SQL wrapper that JPublisher generates. These are used to call the proxy client stub class from PL/SQL.
Here is the class, HelloServiceEJBJPub
, that JPublisher generates as a Java wrapper for the proxy client stub class. The Java wrapper is required to publish instance methods of the stub class as static methods, to allow accessibility from PL/SQL. The Web service endpoint in the code, "http://localhost:8888/javacallout/javacallout
", is according to the -endpoint
setting in the JPublisher command line.
The corresponding PL/SQL wrapper is shown immediately following.
package javacallout; import javax.xml.rpc.Stub; public class HelloServiceEJBJPub{ public static void release() { m_service = null; m_port0 = null; } private static void init() { m_service = new javacallout.HelloServiceEJB_Impl(); m_port0 = (javacallout.HelloServiceInf)(m_service.getHelloServiceInfPort()); ((Stub)m_port0)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, "http://localhost:8888/javacallout/javacallout"); } private static javacallout.HelloServiceEJB_Impl m_service; private static javacallout.HelloServiceInf m_port0 = null; public static java.lang.String getProperty(java.lang.String p0) throws java.rmi.RemoteException { try { if (m_port0==null) init(); java.lang.String o; o = m_port0.getProperty(p0); return o; } catch (Exception e) { throw new java.rmi.RemoteException(e.getMessage()); } } }
Here is the PL/SQL wrapper script, plsql_wrapper.sql
, that creates the PL/SQL wrapper package, JPUB_PLSQL_WRAPPER
. This package is created for invoking the Web service from PL/SQL. Note that it includes the definition of a table function—data from the Web service is returned through a database table, rather than through a normal function return.
An intermediate Java wrapper class, shown immediately preceding, is required to publish instance methods of the JAX-RPC client proxy stub class as static methods, which is required for accessibility from PL/SQL.
-- SQL types assisting the procedures that invoke web services CREATE OR REPLACE TYPE GRAPH_getProperty AS OBJECT(p0 VARCHAR2(32767), res VARCHAR2(32767));/ SHOW ERRORS CREATE OR REPLACE TYPE GRAPH_TAB_getProperty AS TABLE OF GRAPH_getProperty;/ SHOW ERRORS -- PL/SQL procedures that invoke webserviecs CREATE OR REPLACE PACKAGE JPUB_PLSQL_WRAPPER AS FUNCTION getProperty(p0 VARCHAR2) RETURN VARCHAR2; FUNCTION TO_TABLE_getProperty(cur SYS_REFCURSOR) RETURN GRAPH_TAB_getProperty PIPELINED; END JPUB_PLSQL_WRAPPER;/ SHOW ERRORS CREATE OR REPLACE PACKAGE BODY JPUB_PLSQL_WRAPPER IS FUNCTION getProperty(p0 VARCHAR2) RETURN VARCHAR2 as language java name 'javacallout.HelloServiceEJBJPub.getProperty(java.lang.String) return java.lang.String'; FUNCTION TO_TABLE_getProperty(cur SYS_REFCURSOR) RETURN GRAPH_TAB_getProperty PIPELINED IS p0 VARCHAR2(32767); res VARCHAR2(32767); BEGIN LOOP FETCH cur INTO p0; EXIT WHEN cur%NOTFOUND; res:=getProperty(p0); PIPE ROW(GRAPH_getProperty(p0,res)); END LOOP; CLOSE cur; RETURN; END TO_TABLE_getProperty; END JPUB_PLSQL_WRAPPER; / SHOW ERRORS EXIT;
Because a -user
setting is specified in the JPublisher command line to publish this Web service, JPublisher will load the generated Java code and PL/SQL wrapper into the database. Once everything is loaded, you can use the PL/SQL wrapper to invoke the Web service. The PL/SQL wrapper consists of two functions: getProperty
and TO_TABLE_getProperty
.
The getProperty
function directly wraps the getProperty()
method in the generated client proxy class. For example, the following SQL*Plus command uses getProperty
to determine the operating system where the Web service is running ("SunOS
"):
SQL> select JPUB_PLSQL_WRAPPER.getProperty('os.name') from dual; JPUB_PLSQL_WRAPPER.GETPROPERTY('OS.NAME') ----------------------------------------- SunOS
TO_TABLE_getProperty
is a table function based on the getProperty
function. It takes a REF CURSOR as input and returns a table. The schema of the table returned is defined by GRAPH_getProperty
.
In this example, TO_TABLE_getProperty
is called with a REF CURSOR obtained from a one-column table of VARCHAR2
data, where each data item is the name of a system property (such as "os.version
"). Then TO_TABLE_getProperty
returns a table in which each row contains an item from the input REF CURSOR, and the result of a getProperty
call taking that item as input. Following is a sample usage of TO_TABLE_getProperty
.
SQL> -- Test Table Function SQL> create table props (name varchar2(50)); Table created. SQL> insert into props values('os.version'); 1 row created. SQL> insert into props values('java.version'); 1 row created. SQL> insert into props values('file.separator'); 1 row created. SQL> insert into props values('file.encoding.pkg'); 1 row created. SQL> insert into props values('java.vm.info'); 1 row created. SQL> SELECT * FROM TABLE(JPUB_PLSQL_WRAPPER.TO_TABLE_getProperty(CURSOR(SELECT * FROM props))); P0 RES ------------------------------ os.version 5.8 java.version 1.4.1_03 file.separator / file.encoding.pkg sun.io java.vm.info mixed mode
This example creates a one-column table of VARCHAR2
, populates it with system property names, and uses TO_TABLE_getProperty
to find out the values of those system properties. For example, you see that the operating system is Sun Microsystems Solaris 5.8.
See "Code Generation for Table Functions" for general information about table functions.
This section illustrates PL/SQL utility scripts that JPublisher generates, in addition to the wrapper script, plsql_wrapper.sql
, already shown. There are scripts to grant permission for execution of the PL/SQL wrapper, revoke permission, and drop the PL/SQL package from the database schema.
See "Superuser for Permissions to Run Client Proxies (-sysuser)" for information about the option to specify a superuser name and password for running these scripts.
Here is the script to grant permission to execute JPUB_PLSQL_WRAPPER
.
-- Run this script as SYSDBA to grant permissions for SCOTT to run the PL/SQL -- wrapper procedures. BEGIN dbms_java.grant_permission('SCOTT', 'SYS:java.lang.RuntimePermission', 'accessClassInPackage.sun.util.calendar', '' ); dbms_java.grant_permission('SCOTT', 'SYS:java.lang.RuntimePermission', 'getClassLoader', '' ); dbms_java.grant_permission('SCOTT', 'SYS:java.net.SocketPermission', '*', 'connect,resolve' ); END;/ EXIT
Here is the script to revoke permission to execute JPUB_PLSQL_WRAPPER
.
-- Run this script as SYSDBA to revoke the permissions granted to SCOTT. BEGIN dbms_java.revoke_permission('SCOTT', 'SYS:java.lang.RuntimePermission', 'accessClassInPackage.sun.util.calendar', '' ); dbms_java.revoke_permission('SCOTT', 'SYS:java.lang.RuntimePermission', 'getClassLoader', '' ); dbms_java.revoke_permission('SCOTT', 'SYS:java.net.SocketPermission', '*', 'connect,resolve' ); END;/ EXIT
Here is the script to drop JPUB_PLSQL_WRAPPER
from the database schema:
-- Drop the PL/SQL procedures that invoke Web services. DROP PACKAGE JPUB_PLSQL_WRAPPER; EXIT
This section has code examples for Java and PL/SQL wrappers generated for server-side Java classes, according to -proxyclasses
and -proxyopts
settings. See "Options to Facilitate Web Services Call-Outs" for information about these and related options.
Assume that the Java and PL/SQL wrappers in these examples are for general use, not necessarily associated with Web services.
The following sections show the classes to be wrapped, the wrapper classes and PL/SQL wrappers produced for static methods, and the wrapper classes and PL/SQL wrappers produced for instance methods in the handle scenario.
Also see "Generated Code: Java and PL/SQL Wrappers for Web Services".
This section shows classes for which Java and PL/SQL wrappers, shown in subsequent sections, will be generated. Assume that the following classes, named X
and Y
, are installed in the server:
public class X { public void add(int arg) { tot = tot + arg; } public void add(Y arg) { tot = tot + arg.getTotal(); } public int getTot() { return tot; } public Y cloneTot() { Y y=new Y(); y.setTotal(getTot()); return y; } public static int add(int i, int j) { return i+j; } public static Y add(Y i, Y j) { Y y = new Y(); y.setTotal(i.getTotal()+j.getTotal()); return y; } private int tot; } public class Y { public void setTotal(int total) { this.total = total; } public int getTotal() { return total; } private int total; }
Assume that class X
from the preceding section is processed by JPublisher with the following settings:
% jpub -proxyclasses=X -proxyopts=static
With these settings, JPublisher generates Java (as necessary) and PL/SQL wrappers for static methods only. This always includes a PL/SQL wrapper, and in this example also includes a wrapper class, XJPub
, for the class X
. A wrapper class is necessary, even when there are no instance methods to wrap, because class X
uses the Java type Y
for an argument in a method calling sequence. A wrapper class is required whenever types other than Java primitive types are used in method calls. In this case, the wrapper class has a wrapper method for the following:
add(Y arg) {...}
Note that because Y
is a JavaBean type, it is mapped to the weakly typed oracle.sql.STRUCT
class. See "Code Generation for Method Parameters".
Here is the wrapper class:
import java.util.Hashtable; import java.sql.StructDescriptor; import java.sql.Connection; import java.sql.DriverManager; import oracle.sql.STRUCT; import java.math.BigDecimal; public class XJPub { public static STRUCT add( STRUCT arg0, STRUCT arg1) throws java.sql.SQLException { Y _p1 = new Y(); BigDecimal _p0 = (BigDecimal) arg0.getAttributes()[0]; _p1.setTotal(_p0.intValue()); Y _p3 = new Y(); BigDecimal _p4 = (BigDecimal) arg2.getAttributes()[0]; _p3.setTotal(_p4.intValue()); Y _p5 = X.add(_p0, _p4); Connection conn = _getConnection(); StructDescriptor structdesc = StructDescriptor.createDescriptor("YSQL", conn); STRUCT _r = new STRUCT(structdesc, conn, new Object[]{_p5.getTotal()}); return _r; } Connection _getConnection() throws java.sql.SQLException { return DriverManager.getConnection("jdbc:default:connection:"); } }
Following is the PL/SQL wrapper. The type YSQL
is created to enable the PL/SQL code to access Y
instances.
CREATE OR REPLACE TYPE YSQL AS OBJECT(total number); / CREATE OR REPLACE PACKAGE JPUB_PLSQL_WRAPPER AS FUNCTION add(arg0 NUMBER, arg1 NUMBER) RETURN NUMBER; FUNCTION add(arg0 Y, arg1 Y) RETURN Y; END JPUB_PLSQL_WRAPPER; / CREATE OR REPLACE PACKAGE BODY JPUB_PLSQL_WRAPPER AS FUNCTION add(arg0 NUMBER, arg1 NUMBER) RETURN NUMBER AS LANGUAGE JAVA NAME 'X.add(int,int) return int'; FUNCTION add(arg0 YSQL, arg1 YSQL) RETURN NUMBER AS LANGUAGE JAVA NAME 'XJPub.add(oracle.sql.STRUCT, Oracle.sql.STRUCT) return oracle.sql.STRUCT'; END JPUB_PLSQL_WRAPPER; /
Assume that classes X
and Y
from "Classes to Be Wrapped" are processed by JPublisher with the following settings:
% jpub -proxyclasses=X,Y -proxyopts=multiple
Given these settings, JPublisher generates wrappers for instance methods, including Java wrapper classes and a PL/SQL wrapper. In this example, JPublisher generates the wrapper classes XJPub
and YJPub
for X
and Y
, respectively. Because of the multiple
setting, JPublisher uses the handle mechanism to expose instance methods as static methods to allow access from PL/SQL (which supports only static methods). See "Mechanisms Used in Exposing Java to PL/SQL" and "Wrapper Class Generation with Handles" for related information.
Here is the class XJPub
:
import java.util.Hashtable; public class XJPub { public static void add(long handleX, int arg) { XJPub._getX(handleX).add(arg); } public static void add(long handleX, long handleY) { XJPub._getX(handleX).add(YJPub._getY(handleY)); } public static int getTot(long handleX) { return XJPub._getX(handleX).getTot(); } public static long cloneTot(long handleX) { return YJPub._setY(XJPub._getX(handleX).cloneTot()); } // Generic Code // // This code is generated similarly for all classes. // private static long m_seq; // instance count private static long m_base; // base represents null instance private static Hashtable m_objs = new Hashtable(); private static Hashtable m_tags = new Hashtable(); static { m_base = XJPub.class.hashCode(); m_base = (m_base>0l) ? -m_base : m_base; /* m_base = m_base && 0xFFFFFFFF00000000l */ ; m_seq = m_base; } public static X _getX(long handleX) { if (handleX<=m_base || handleX>m_seq) return null; return (X)m_objs.get(new Long(handleX)); } public static long _setX(X x) { if (x==null) { return m_base; } Long l = (Long)m_tags.get(x); if (l != null) { return l.longValue(); } else { return newX(); } } public static long newX() { m_seq++; Long l = new Long(m_seq); X x = new X(); m_objs.put(l,x); m_tags.put(x,l); return m_seq; } public static void releaseX(long handleX) { if (handleX<=m_base || handleX>m_seq) { /* wrong type - should we issue an error? */ return; } Long l = new Long(handleX); m_objs.remove(l); Object x = m_objs.get(l); if (x!=null) m_tags.remove(x); } public static void releaseAllX() { m_objs.clear(); m_tags.clear(); m_seq=m_base; } }
Here is the class YJPub
:
import java.util.Hashtable; public class YJPub { public static void setTotal(long handleY, int total) { YJPub._getY(handleY).setTotal(total); } public static int getTotal(long handleY) { return YJPub._getY(handleY).getTotal(); } // Generic Code // // This code is generated similarly for all classes. // private static long m_seq; // instance count private static long m_base; // base represents null instance private static Hashtable m_objs = new Hashtable(); private static Hashtable m_tags = new Hashtable(); static { m_base = YJPub.class.hashCode(); m_base = (m_base>0l) ? -m_base : m_base; /* m_base = m_base && 0yFFFFFFFF00000000l */ ; m_seq = m_base; } public static Y _getY(long handleY) { if (handleY<=m_base || handleY>m_seq) return null; return (Y)m_objs.get(new Long(handleY)); } public static long _setY(Y y) { if (y==null) { return m_base; } Long l = (Long)m_tags.get(y); if (l != null) { return l.longValue(); } else { return newY(); } } public static long newY() { m_seq++; Long l = new Long(m_seq); Y y = new Y(); m_objs.put(l,y); m_tags.put(y,l); return m_seq; } public static void releaseY(long handleY) { if (handleY<=m_base || handleY>m_seq) { /* wrong type - should we issue an error? */ return; } Long l = new Long(handleY); m_objs.remove(l); Object y = m_objs.get(l); if (y!=null) m_tags.remove(y); } public static void releaseAllY() { m_objs.clear(); m_tags.clear(); m_seq=m_base; } }
Here is the PL/SQL wrapper:
CREATE OR REPLACE PACKAGE JPUB_PLSQL_WRAPPER AS FUNCTION NEW_X() RETURN NUMBER; PROCEDURE ADD(handle_X NUMBER, arg0 NUMBER); PROCEDURE ADD2(handle_X NUMBER, handle_Y NUMBER); FUNCTION GET_TOT(handle_X NUMBER) RETURN NUMBER; FUNCTION CLONE_TOT(handle_X NUMBER) RETURN NUMBER; FUNCTION NEW_Y() RETURN NUMBER; PROCEDURE SET_TOTAL(handle_Y NUMBER, arg0 NUMBER); FUNCTION GET_TOTAL(handle_Y NUMBER) RETURN NUMBER; END JPUB_PLSQL_WRAPPER; / CREATE OR REPLACE PACKAGE BODY JPUB_PLSQL_WRAPPER AS FUNCTION NEW_X() RETURN NUMBER AS LANGUAGE JAVA NAME 'XJPub.newX() return long'; PROCEDURE RELEASE_X(handle_X NUMBER) AS LANGUAGE JAVA NAME 'XJPub.releaseX(long)'; PROCEDURE RELEASE_ALL_X() AS LANGUAGE JAVA NAME 'XJPub.releaseAllX()'; PROCEDURE ADD(handle_X NUMBER, arg0 NUMBER) AS LANGUAGE JAVA NAME 'XJPub.add(long,int)'; PROCEDURE ADD2(handle_X NUMBER, handle_Y NUMBER) AS LANGUAGE JAVA NAME 'XJPub.add(long,long)'; FUNCTION GET_TOT(handle_X NUMBER) RETURN NUMBER AS LANGUAGE JAVA NAME 'XJPub.getTot(long) return int'; FUNCTION CLONE_TOT(handle_X NUMBER) RETURN NUMBER AS LANGUAGE JAVA NAME 'XJPub.cloneTot(long) return long'; FUNCTION NEW_Y() RETURN NUMBER AS LANGUAGE JAVA NAME 'YJPub.newY() return long'; PROCEDURE RELEASE_Y(handle_Y NUMBER) AS LANGUAGE JAVA NAME 'YJPub.releaseY(long)'; PROCEDURE RELEASE_ALL_Y() AS LANGUAGE JAVA NAME 'YJPub.releaseAllY()'; PROCEDURE SET_TOTAL(handle_Y NUMBER, arg0 NUMBER) AS LANGUAGE JAVA NAME 'YJPub.setTotal(long,int)'; FUNCTION GET_TOTAL(handle_Y NUMBER, arg0 NUMBER) RETURN NUMBER AS LANGUAGE JAVA NAME 'YJPub.getTotal(long) return int'; END JPUB_PLSQL_WRAPPER;