Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "EclipseLink/Development/DBWS/MetadataSupport"

(Simple Stored Procedure DDL)
(Metadata Generation Examples)
Line 430: Line 430:
 
     <property name="wsdlLocationURI">http://localhost:7001/simplesp/simplesp?wsdl</property>
 
     <property name="wsdlLocationURI">http://localhost:7001/simplesp/simplesp?wsdl</property>
 
   </properties>
 
   </properties>
   <procedure name="InOutArgsTest" procedurePattern="INOUTARGSSP" isSimpleXMLFormat="true"/>  
+
   <procedure name="InOutArgsTest" procedurePattern="INOUTARGSSP"/>  
 
</dbws-builder>
 
</dbws-builder>
 
</source>
 
</source>
Line 473: Line 473:
  
 
==== Simple PL/SQL Stored Procedure DDL ====
 
==== Simple PL/SQL Stored Procedure DDL ====
Given the following PL/SQL Package DDL:
+
Following is the XML passed to the Builder (assume the target platform is WebLogic, packaged as a .war):
 +
<source lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<dbws-builder xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 +
  <properties>
 +
    <property name="projectName">simpleplsqlsp</property>
 +
    <property name="logLevel">off</property>
 +
    <property name="username">SCOTT</property>
 +
    <property name="password">TIGER</property>
 +
    <property name="url">jdbc:oracle:thin:@localhost:1521:TOPLINK</property>
 +
    <property name="driver">oracle.jdbc.OracleDriver</property>
 +
    <property name="platformClassname">org.eclipse.persistence.platform.database.oracle.Oracle11Platform</property>
 +
    <property name="dataSource">jdbc/EclipseLinkDS</property>
 +
    <property name="wsdlLocationURI">http://localhost:7001/simpleplsqlsp/simpleplsqlsp?wsdl</property>
 +
  </properties>
 +
  <plsql-procedure name="InOutArgsTest" catalogPattern="SIMPLEPACKAGE" procedurePattern="INOUTARGSPLSQLSP"/>
 +
</dbws-builder>
 +
</source>
 +
 
 +
Based on the provided Builder XML, the DDL for SCOTT.INOUTARGSSP would be extracted as follows:
 
<source lang="text">
 
<source lang="text">
CREATE OR REPLACE PACKAGE SIMPLEPACKAGE1 AS
+
SQL> SELECT DBMS_METADATA.GET_DDL('PACKAGE', AO.OBJECT_NAME) AS RESULT FROM ALL_OBJECTS AO WHERE (REGEXP_LIKE(OWNER,?)  
    PROCEDURE INOUTARGSPLSQLSP(T IN VARCHAR, U OUT VARCHAR, V OUT NUMERIC);
+
AND AO.STATUS = 'VALID' AND AO.OBJECT_TYPE = ? AND AO.OBJECT_NAME LIKE ?)
END SIMPLEPACKAGE1;
+
 
</source>
 
</source>
 +
 +
<source lang="text">
 +
CREATE OR REPLACE PACKAGE "SCOTT"."SIMPLEPACKAGE" AS
 +
  PROCEDURE INOUTARGSPLSQLSP(T IN VARCHAR, U OUT VARCHAR, V OUT NUMERIC);
 +
END SIMPLEPACKAGE;
 +
</source>
 +
 +
Once the DDL is obtained, the DDLParser can be used to generate the meta-model objects based on the DDL string:
 +
<source lang="java">
 +
String ddlString;
 +
// set ddlString ...
 +
 +
DDLParser parser = new DDLParser(new StringReader(ddlString));
 +
PLSQLPackageType packageType = parser.parsePLSQLPackage();
 +
List<ProcedureType> procedures = packageType.getProcedures();
 +
// iterate through list and locate the proc by name
 +
</source>
 +
 
<code>XmlEntityMappingsGenerator</code> will generate the following <code><named-plsql-stored-procedure-query></code> metadata as follows:
 
<code>XmlEntityMappingsGenerator</code> will generate the following <code><named-plsql-stored-procedure-query></code> metadata as follows:
 
<source lang="xml">
 
<source lang="xml">
<orm:named-plsql-stored-procedure-query name="InOutArgsTest" procedure-name="SIMPLEPACKAGE1.INOUTARGSPLSQLSP">
+
<orm:named-plsql-stored-procedure-query name="InOutArgsTest" procedure-name="SIMPLEPACKAGE.INOUTARGSPLSQLSP">
 
   <orm:parameter direction="IN" name="T" database-type="VARCHAR_TYPE"/>
 
   <orm:parameter direction="IN" name="T" database-type="VARCHAR_TYPE"/>
 
   <orm:parameter direction="OUT" name="U" database-type="VARCHAR_TYPE"/>
 
   <orm:parameter direction="OUT" name="U" database-type="VARCHAR_TYPE"/>

Revision as of 12:19, 19 June 2013

Design document for adding JPA/JAXB metadata support to DBWS

The purpose of this document is to outline what changes are to be made to the DBWS codebase to allow support for reading/writing JPA/JAXB metadata in place of EclipseLink deployment XML. This feature is required to resolve EclipseLink Bug 332227.

Overview

The DBWS builder constructs OR/OX projects, which are marshalled to a given output stream by the builder and placed in a generated .war archive for use by the DBWS runtime. The builder currently utilizes the legacy EclipseLink deployment XML format for this purpose, but is required to move to the modern JPA/JAXB metadata format.

Requirements

  • Support generation and marshal of JPA and JAXB metadata files in the DBWS builder
  • Support unmarshal of JPA and JAXB metadata files in the DBWS runtime
  • Support unmarshal of legacy OR/OX deployment XML for backward compatibility

JAXB Metadata support

The existing DBWS builder code utilizes the ObjectPersistenceWorkbenchXMLProject class to marshal the OX project at design time and unmarshal it at runtime. The code will be changed to instead use JAXB metadata for these operations. The following pages contain information pertaining to EclipseLink's support for JAXB annotations via XML metadata:

The DBWS builder creates an OX project; this project's descriptors - and each descriptor's mappings - will be used to generate one or more <xml-bindings> elements (one per package) that make up the JAXB metadata file. Three classes are needed to accomplish this task:

  • XmlBindingsModel - used to create a JAXB context that can be used to marshal/unmarshal the metadata file.
  • XmlBindingsGenerator - generates one or more <xml-bindings> elements (one per package) based on a list of Descriptor instances
  • DBWSMetadataSource - implementation of org.eclipse.persistence.jaxb.metadata.MetadataSource to allow passing org.eclipse.persistence.jaxb.xmlmodel.XmlBindings to a org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory instance
The generated metadata file will have the format:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xml-bindings-list xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm">
  <xml-bindings package-name="simpletable">
    ...
  </xml-bindings>
  <xml-bindings package-name="complextable">
    ...
  </xml-bindings>
  ...
</xml-bindings-list>

org.eclipse.persistence.internal.xr.XmlBindingsModel

The XmlBindingsModel class will be used to create a JAXBContext instance that is able to marshal and unmarshal the generated JAXB metadata file.
/**
 * This class is responsible for holding a list of XmlBindings.
 *
 */
@XmlAccessorType(javax.xml.bind.annotation.XmlAccessType.FIELD)
@XmlRootElement(name="xml-bindings-list", namespace="http://www.eclipse.org/eclipselink/xsds/persistence/oxm")
public class XmlBindingsModel {
    @XmlElement(name="xml-bindings", namespace="http://www.eclipse.org/eclipselink/xsds/persistence/oxm")
    public List<XmlBindings> bindingsList;
 
    /**
     * Return the list of XmlBindings
     */
    public List<XmlBindings> getBindingsList() {
        return bindingsList;
    }
 
    /**
     * Set the list of XmlBindings.
     */
    public void setBindingsList(List<XmlBindings> bindingsList) {
        this.bindingsList = bindingsList;
    }
}

org.eclipse.persistence.tools.dbws.XmlBindingsGenerator

This class is responsible for generating one or more <xml-bindings> elements (one per package) based on a given list of Descriptor instances - these elements will make up the JAXB metadata file. The following OX mappings must be supported:

  • XMLBinaryDataMapping
  • XMLCompositeCollectionMapping
  • XMLCompositeDirectCollectionMapping
  • XMLCompositeObjectMapping
  • XMLDirectMapping
The following public API is required:
/**
 * Generate one or more XmlBindings based on a given list of
 * ClassDescriptor instances.
 * 
 */
public static List<XmlBindings> generateXmlBindings(List<ClassDescriptor> descriptors)
/**
 * Generate an XmlBindings instance based on a list of XML descriptors.
 *
 * OXM metadata files are processed on a per package basis, hence it is assumed that 
 * the given list of descriptors are from the same package.
 * 
 */
public static XmlBindings generateXmlBindings(String packageName, List<XMLDescriptor> descriptors)

org.eclipse.persistence.internal.xr.XRServiceFactory$OXMMetadataSource

This inner class holds on to an org.eclipse.persistence.jaxb.xmlmodel.XmlBindings instance, allowing it to be passed to the DynamicJAXBContextFactory.
/**
 * <p>INTERNAL:
 * 
 * Implementation of MetadataSource to allow passing XmlBindings
 * to the DynamicJAXBContextFactory
 *
 */
public class OXMMetadataSource implements MetadataSource {
    XmlBindings xmlbindings;
 
    public OXMMetadataSource(XmlBindings bindings) {
        xmlbindings = bindings;
    }
 
    @Override
    public XmlBindings getXmlBindings(Map<String, ?> properties, ClassLoader classLoader) {
        return xmlbindings;
    }
}

Example: XmlBindings list generation and marshal operation

The following example illustrates how the XmlBindingsGenerator can be used to generate a list of org.eclipse.persistence.jaxb.xmlmodel.XmlBindings instances, and how this list can be marshalled to a given output stream:
List<XmlBindings> xmlBindingsList = XmlBindingsGenerator.generateXmlBindings(oxProject.getOrderedDescriptors());
if (xmlBindingsList.size() > 0) {
    XmlBindingsModel model = new XmlBindingsModel();
    model.setBindingsList(xmlBindingsList);
    try {
        JAXBContext jc = JAXBContext.newInstance(XmlBindingsModel.class);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(model, dbwsOxStream);
    } catch (JAXBException jaxbEx) {
        throw new DBWSException(OXM_MARSHAL_EX_MSG, jaxbEx);
    }
}
Note that the existing marshal code in BaseDBWSBuilderHelper.writeOrOxProjects should be removed and the above code (or similar) should be used.

Example: Unmarshal a JAXB metadata file and use DynamicJAXBContext to retrieve the resulting OXM Project

The following example illustrates how DBWS generated JAXB metadata can be unmarshalled to an XmlBindingsModel, and how this can be used with DynamicJAXBContext to retrieve the OX Project.
Map<String, DBWSMetadataSource> metadataMap = new HashMap<String, DBWSMetadataSource>();
StreamSource xml = new StreamSource(inStream);
try {
    JAXBContext jc = JAXBContext.newInstance(XmlBindingsModel.class);
    Unmarshaller unmarshaller = jc.createUnmarshaller();
 
    JAXBElement<XmlBindingsModel> jaxbElt = unmarshaller.unmarshal(xml, XmlBindingsModel.class);
    XmlBindingsModel model = jaxbElt.getValue();
    for (XmlBindings xmlBindings : model.getBindingsList()) {
        metadataMap.put(xmlBindings.getPackageName(), new DBWSMetadataSource(xmlBindings));
    }
} catch (JAXBException jaxbex) {
    throw new DBWSException(OXM_PROCESSING_EX, jaxbex);
}
 
Map<String, Map<String, DBWSMetadataSource>> properties = new HashMap<String, Map<String, DBWSMetadataSource>>();
properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, metadataMap);
try {
    DynamicJAXBContext jCtx = DynamicJAXBContextFactory.createContextFromOXM(xrdecl, properties);
    oxProject = jCtx.getXMLContext().getSession(0).getProject();
 
} catch (JAXBException e) {
    throw new DBWSException(OXM_PROCESSING_EX, e);
}
Note that the existing unmarshal code in XRServiceFactory.buildSessions should be removed and the above code (or similar) should be used.

JPA Metadata support

The existing DBWS builder code utilizes the ObjectPersistenceWorkbenchXMLProject class to marshal the OR project at design time and unmarshal it at runtime. The code will be changed to instead use JPA metadata for these operations. The following page contains information pertaining to EclipseLink's support for JPA annotations via XML metadata:

The DBWS builder creates an OR project; this project's queries and descriptors - and each descriptor's mappings - will be used to generate the JPA metadata <entity-mappings> element and each of its sub-elements. The following classes are needed to accomplish this task:

  • XmlEntityMappingsGenerator - generates an <entity-mappings> element and each of it's sub-elements based on lists of Query and Descriptor instances
  • XRPersistenceUnitInfo - implementation of javax.persistence.spi.PersistenceUnitInfo
  • JPAMetadataSource - implementation of org.eclipse.persistence.jpa.metadata.MetadataSource

org.eclipse.persistence.tools.dbws.XmlEntityMappingsGenerator

This class is responsible for generating the JPA metadata <entity-mappings> element and each of its sub-elements based on given lists of Query and Descriptor instances. The following OR mappings must be supported:

  • AggregateMapping
  • ArrayMapping
  • DirectToFieldMapping
  • ObjectArrayMapping
  • StructureMapping
The following public API is required:
/**
 * Generate an XMLEntityMappings instance based on a given OR Project's Queries and Descriptors.
 * 
 * @param orProject the ORM Project instance containing Queries and Descriptors to be used to generate an XMLEntityMappings
 * @param complexTypes list of composite database types used to generate metadata for advanced Oracle and PL/SQL types
 * @param crudOperations map of maps keyed on table name - the second map are operation name to SQL string entries
 */
public static XMLEntityMappings generateXmlEntityMappings(Project orProject, List<CompositeDatabaseType> complexTypes, Map<String, Map<String, String>> crudOperations) {

org.eclipse.persistence.internal.xr.XRServiceFactory$JPAMetadataSource

This inner class is responsible for returning an XMLEntityMappings instance built based on given JPA metadata.

/**
 * <p>INTERNAL:
 * 
 * Implementation of MetadataSource to allow passing JPA metadata to the
 * MetadataProcessor.
 *
 */
public class JPAMetadataSource implements org.eclipse.persistence.jpa.metadata.MetadataSource {
    XRDynamicClassLoader xrdecl;
    Reader reader;
 
    public JPAMetadataSource(XRDynamicClassLoader loader, Reader reader) {
        xrdecl = loader;
        this.reader = reader;
    }
 
    @Override
    public Map<String, Object> getPropertyOverrides(Map<String, Object> properties, ClassLoader classLoader, SessionLog log) {
        return null;
    }
 
    @Override
    public XMLEntityMappings getEntityMappings(Map<String, Object> properties, ClassLoader classLoader, SessionLog log) {            
        return XMLEntityMappingsReader.read(ORM_MAPPINGS_STR, reader, xrdecl, null);
    }
}

org.eclipse.persistence.internal.xr.XRServiceFactory$XRPersistenceUnitInfo

This inner class is passed into the constructor of org.eclipse.persistence.internal.jpa.metadata.MetadataProcessor. Other than an XRDynamicClassLoader</code instance, all methods return null, empty lists, etc.


/**
 * <p>INTERNAL:
 * 
 * PersistenceUnitInfo implementation to allow creation of a MetadataProcessor
 * instance.  Other than an XRDynamicClassLoader instance, all methods return
 * null, empty lists, etc.
 *
 */
public class XRPersistenceUnitInfo implements PersistenceUnitInfo {
    XRDynamicClassLoader xrdecl;
    public XRPersistenceUnitInfo(XRDynamicClassLoader loader) {
        xrdecl = loader;
    }
    @Override
    public PersistenceUnitTransactionType getTransactionType() { return null; }
    @Override
    public Properties getProperties() { return new Properties(); }
    @Override
    public URL getPersistenceUnitRootUrl() { return null; }
    @Override
    public String getPersistenceUnitName() { return null; }
    @Override
    public String getPersistenceProviderClassName() { return null; }
    @Override
    public DataSource getNonJtaDataSource() { return null; }
    @Override
    public ClassLoader getNewTempClassLoader() { return xrdecl; }
    @Override
    public List<String> getMappingFileNames() { return new ArrayList<String>(); }
    @Override
    public List<String> getManagedClassNames() { return new ArrayList<String>(); }
    @Override
    public DataSource getJtaDataSource() { return null; }
    @Override
    public List<URL> getJarFileUrls() { return new ArrayList<URL>(); }
    @Override
    public ClassLoader getClassLoader() { return xrdecl; }
    @Override
    public boolean excludeUnlistedClasses() { return false; }
    @Override
    public void addTransformer(ClassTransformer arg0) { }
    @Override
    public SharedCacheMode getSharedCacheMode() { return null; }
    @Override
    public ValidationMode getValidationMode() { return null; }
    @Override
    public String getPersistenceXMLSchemaVersion() { return null; }
}

Example: XMLEntityMappings generation and marshal operation

XMLEntityMappings mappings = XmlEntityMappingsGenerator.generateXmlEntityMappings(orProject, complextypes, crudOps);
if (mappings != null) {
    XMLEntityMappingsWriter writer = new XMLEntityMappingsWriter();
    writer.write(mappings, dbwsOrStream);                
}

Example: Unmarshal a JPA metadata file and retrieve the ORM Project from it

MetadataProcessor processor = new MetadataProcessor(new XRPersistenceUnitInfo(xrdecl), 
        new DatabaseSessionImpl(login), xrdecl, false, true, false, false, false, null, null);
processor.setMetadataSource(new JPAMetadataSource(xrdecl, DBWS_OR_STREAM.toString()));
PersistenceUnitProcessor.processORMetadata(processor, true, PersistenceUnitProcessor.Mode.ALL);
processor.addNamedQueries();
orProject = processor.getProject().getProject();

Backwards Compatibility

If either OXM or ORM project cannot be loaded via metadata, we will try to load the project(s) via sessions XML. This will allow existing deployments (i.e. WAR generated prior to metadata support being released) to be successfully processed at runtime.

Example: Attempt to load OXM project via sessions XML

// at this point we may have a legacy deployment XML project
String oxSessionKey = xrService.name + DASH_STR + DBWS_OX_SESSION_NAME_SUFFIX;
if (sessions.containsKey(oxSessionKey)) {
    xrService.oxSession = (Session)sessions.get(oxSessionKey);
    ((XMLLogin)xrService.oxSession.getDatasourceLogin()).setEqualNamespaceResolvers(false);
    oxProject = xrService.oxSession.getProject(); 
}

Metadata Generation Examples

Simple Table DDL

Following is the XML passed to the Builder (assume the target platform is WebLogic, packaged as a .war):

<?xml version="1.0" encoding="UTF-8"?>
<dbws-builder xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <properties>
    <property name="projectName">tabletype</property>
    <property name="logLevel">off</property>
    <property name="username">SCOTT</property>
    <property name="password">TIGER</property>
    <property name="url">jdbc:oracle:thin:@localhost:1521:TOPLINK</property>
    <property name="driver">oracle.jdbc.OracleDriver</property>
    <property name="platformClassname">org.eclipse.persistence.platform.database.oracle.Oracle11Platform</property>
    <property name="dataSource">jdbc/EclipseLinkDS</property>
    <property name="wsdlLocationURI">http://localhost:7001/tabletype/tabletype?wsdl</property>
  </properties>
  <table tableNamePattern="TABLETYPE"/>
</dbws-builder>

Based on the provided Builder XML, the DDL for SCOTT.TABLETYPE would be extracted as follows:

SQL> SELECT DBMS_METADATA.GET_DDL('TABLE', 'TABLETYPE', SYS_CONTEXT('USERENV', 'CURRENT_USER')) AS RESULT FROM DUAL;
CREATE TABLE "SCOTT"."TABLETYPE"(
    "ID" NUMERIC(4) NOT NULL,
    "NAME" VARCHAR(25),
    "DEPTNO" DECIMAL(2,0),
    "DEPTNAME" VARCHAR2(40),
) 
ALTER TABLE "SCOTT"."TABLETYPE" ADD CONSTRAINT "PK_TABLETYPE" PRIMARY KEY ("ID") ENABLE;

Once the DDL is obtained, the DDLParser can be used to generate the meta-model objects based on the DDL string:

String ddlString;
// set ddlString ...
 
DDLParser parser = new DDLParser(new StringReader(ddlString));
TableType tableType = parser.parseTable();

DBWS will generate <code>CRUD operations for the SCOTT.TABLETYPE table. The naming convention used for the operations is:

operation name + "_" + entity name + "Type".

For example, in this case the following would be generated:

  • findByPrimaryKey_TabletypeType
  • findAll_TabletypeType
  • create_TabletypeType
  • update_TabletypeType
  • delete_TabletypeType

XmlEntityMappingsGenerator will generate the following <entity> metadata, which contains query metadata for each of the generated CRUD operations as follows:

<orm:entity class="tabletype.Tabletype" access="VIRTUAL">
   <orm:table name="TABLETYPE"/>
   <orm:named-native-query name="findByPrimaryKey_TabletypeType" result-class="tabletype.Tabletype">
      <orm:query>SELECT * FROM TABLETYPE WHERE (ID = ?1)</orm:query>
   </orm:named-native-query>
   <orm:named-native-query name="findAll_TabletypeType" result-class="tabletype.Tabletype">
      <orm:query>SELECT * FROM TABLETYPE</orm:query>
   </orm:named-native-query>
   <orm:named-native-query name="update_TabletypeType">
      <orm:query>UPDATE TABLETYPE SET NAME = ?2, DEPTNO = ?3, DEPTNAME = ?4 WHERE (ID = ?1)</orm:query>
   </orm:named-native-query>
   <orm:named-native-query name="create_TabletypeType">
      <orm:query>INSERT INTO TABLETYPE (ID, NAME, DEPTNO, DEPTNAME) VALUES (?1, ?2, ?3, ?4)</orm:query>
   </orm:named-native-query>
   <orm:named-native-query name="delete_TabletypeType">
      <orm:query>DELETE FROM TABLETYPE WHERE (ID = ?1)</orm:query>
   </orm:named-native-query>
   <orm:attributes>
      <orm:id name="id" attribute-type="java.math.BigInteger">
         <orm:column name="ID"/>
      </orm:id>
      <orm:basic name="name" attribute-type="java.lang.String">
         <orm:column name="NAME"/>
      </orm:basic>
      <orm:basic name="deptno" attribute-type="java.math.BigInteger">
         <orm:column name="DEPTNO"/>
      </orm:basic>
      <orm:basic name="deptname" attribute-type="java.lang.String">
         <orm:column name="DEPTNAME"/>
      </orm:basic>
   </orm:attributes>
</orm:entity>

Simple Stored Procedure DDL

Following is the XML passed to the Builder (assume the target platform is WebLogic, packaged as a .war):

<?xml version="1.0" encoding="UTF-8"?>
<dbws-builder xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <properties>
    <property name="projectName">simplesp</property>
    <property name="logLevel">off</property>
    <property name="username">SCOTT</property>
    <property name="password">TIGER</property>
    <property name="url">jdbc:oracle:thin:@localhost:1521:TOPLINK</property>
    <property name="driver">oracle.jdbc.OracleDriver</property>
    <property name="platformClassname">org.eclipse.persistence.platform.database.oracle.Oracle11Platform</property>
    <property name="dataSource">jdbc/EclipseLinkDS</property>
    <property name="wsdlLocationURI">http://localhost:7001/simplesp/simplesp?wsdl</property>
  </properties>
  <procedure name="InOutArgsTest" procedurePattern="INOUTARGSSP"/> 
</dbws-builder>

Based on the provided Builder XML, the DDL for SCOTT.INOUTARGSSP would be extracted as follows:

SQL> SELECT DBMS_METADATA.GET_DDL('PROCEDURE', AO.OBJECT_NAME) AS RESULT FROM ALL_OBJECTS AO WHERE (REGEXP_LIKE(OWNER,?) 
AND AO.STATUS = 'VALID' AND AO.OBJECT_TYPE = ? AND AO.OBJECT_NAME LIKE ?) OR (REGEXP_LIKE(OWNER,?) AND AO.STATUS = 'VALID' 
AND AO.OBJECT_TYPE = ? AND AO.OBJECT_NAME LIKE ?) OR (REGEXP_LIKE(OWNER,?) AND AO.STATUS = 'VALID' AND AO.OBJECT_TYPE = ? 
AND AO.OBJECT_NAME LIKE ?) OR (REGEXP_LIKE(OWNER,?) AND AO.STATUS = 'VALID' AND AO.OBJECT_TYPE = ? AND AO.OBJECT_NAME LIKE ?) 
OR (REGEXP_LIKE(OWNER,?) AND AO.STATUS = 'VALID' AND AO.OBJECT_TYPE = ? AND AO.OBJECT_NAME LIKE ?) OR (REGEXP_LIKE(OWNER,?) 
AND AO.STATUS = 'VALID' AND AO.OBJECT_TYPE = ? AND AO.OBJECT_NAME LIKE ?) OR (REGEXP_LIKE(OWNER,?) AND AO.STATUS = 'VALID' 
AND AO.OBJECT_TYPE = ? AND AO.OBJECT_NAME LIKE ?) OR (REGEXP_LIKE(OWNER,?) AND AO.STATUS = 'VALID' AND AO.OBJECT_TYPE = ? 
AND AO.OBJECT_NAME LIKE ?)
CREATE OR REPLACE PROCEDURE "SCOTT"."INOUTARGSSP" (T IN VARCHAR, U OUT VARCHAR, V OUT NUMERIC) is
BEGIN
  // do something...
END INOUTARGSSP;

Once the DDL is obtained, the DDLParser can be used to generate the meta-model objects based on the DDL string:

String ddlString;
// set ddlString ...
 
DDLParser parser = new DDLParser(new StringReader(ddlString));
ProcedureType procedureType = parser.parseTopLevelProcedure();

XmlEntityMappingsGenerator will generate the following <named-stored-procedure-query> metadata as follows:

<orm:named-stored-procedure-query name="InOutArgsTest" procedure-name="INOUTARGSSP" returns-result-set="false">
    <orm:parameter mode="IN" name="T" jdbc-type="12"/>
    <orm:parameter mode="OUT" name="U" jdbc-type="12"/>
    <orm:parameter mode="OUT" name="V" jdbc-type="2"/>
</orm:named-stored-procedure-query>

Note: the name attribute is configured through the builder on the associated operation model.

Simple PL/SQL Stored Procedure DDL

Following is the XML passed to the Builder (assume the target platform is WebLogic, packaged as a .war):

<?xml version="1.0" encoding="UTF-8"?>
<dbws-builder xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <properties>
    <property name="projectName">simpleplsqlsp</property>
    <property name="logLevel">off</property>
    <property name="username">SCOTT</property>
    <property name="password">TIGER</property>
    <property name="url">jdbc:oracle:thin:@localhost:1521:TOPLINK</property>
    <property name="driver">oracle.jdbc.OracleDriver</property>
    <property name="platformClassname">org.eclipse.persistence.platform.database.oracle.Oracle11Platform</property>
    <property name="dataSource">jdbc/EclipseLinkDS</property>
    <property name="wsdlLocationURI">http://localhost:7001/simpleplsqlsp/simpleplsqlsp?wsdl</property>
  </properties>
  <plsql-procedure name="InOutArgsTest" catalogPattern="SIMPLEPACKAGE" procedurePattern="INOUTARGSPLSQLSP"/> 
</dbws-builder>

Based on the provided Builder XML, the DDL for SCOTT.INOUTARGSSP would be extracted as follows:

SQL> SELECT DBMS_METADATA.GET_DDL('PACKAGE', AO.OBJECT_NAME) AS RESULT FROM ALL_OBJECTS AO WHERE (REGEXP_LIKE(OWNER,?) 
AND AO.STATUS = 'VALID' AND AO.OBJECT_TYPE = ? AND AO.OBJECT_NAME LIKE ?)
CREATE OR REPLACE PACKAGE "SCOTT"."SIMPLEPACKAGE" AS
  PROCEDURE INOUTARGSPLSQLSP(T IN VARCHAR, U OUT VARCHAR, V OUT NUMERIC);
END SIMPLEPACKAGE;

Once the DDL is obtained, the DDLParser can be used to generate the meta-model objects based on the DDL string:

String ddlString;
// set ddlString ...
 
DDLParser parser = new DDLParser(new StringReader(ddlString));
PLSQLPackageType packageType = parser.parsePLSQLPackage();
List<ProcedureType> procedures = packageType.getProcedures();
// iterate through list and locate the proc by name

XmlEntityMappingsGenerator will generate the following <named-plsql-stored-procedure-query> metadata as follows:

<orm:named-plsql-stored-procedure-query name="InOutArgsTest" procedure-name="SIMPLEPACKAGE.INOUTARGSPLSQLSP">
   <orm:parameter direction="IN" name="T" database-type="VARCHAR_TYPE"/>
   <orm:parameter direction="OUT" name="U" database-type="VARCHAR_TYPE"/>
   <orm:parameter direction="OUT" name="V" database-type="NUMERIC_TYPE"/>
</orm:named-plsql-stored-procedure-query>

Note: the name attribute is configured through the builder on the associated operation model.

PL/SQL Record DDL

Given the following PL/SQL Package DDL:

CREATE OR REPLACE PACKAGE EMP_RECORD_PACKAGE AS
    TYPE EmpRec IS RECORD (
        emp_id   NUMERIC(4),
        emp_name VARCHAR(25)
    );
    FUNCTION get_emp_record (pId in number) RETURN EmpRec;
END EMP_RECORD_PACKAGE;

XmlEntityMappingsGenerator will generate the following <named-plsql-stored-function-query> metadata as follows:

<orm:named-plsql-stored-function-query name="TestRecWithPercentTypeField" function-name="EMP_RECORD_PACKAGE.get_emp_record">
   <orm:parameter direction="IN" name="pId" database-type="NUMERIC_TYPE"/>
   <orm:return-parameter name="RESULT" database-type="EMP_RECORD_PACKAGE.EMPREC"/>
</orm:named-plsql-stored-function-query>

Note: the name attribute is configured through the builder on the associated operation model.

XmlEntityMappingsGenerator will generate the following <plsql-record> metadata as follows:

<orm:plsql-record name="EMP_RECORD_PACKAGE.EMPREC" compatible-type="EMP_RECORD_PACKAGE_EMPREC" java-type="emp_record_package.emprec">
   <orm:field name="emp_id" database-type="NUMERIC_TYPE"/>
   <orm:field name="emp_name" database-type="VARCHAR_TYPE"/>
</orm:plsql-record>

XmlEntityMappingsGenerator will generate the following <embeddable> metadata as follows:

<orm:embeddable class="emp_record_package.emprec" access="VIRTUAL">
   <orm:struct name="EMP_RECORD_PACKAGE_EMPREC">
      <orm:field>emp_id</orm:field>
      <orm:field>emp_name</orm:field>
   </orm:struct>
   <orm:attributes>
      <orm:basic name="emp_id" attribute-type="java.math.BigInteger">
         <orm:column name="emp_id"/>
      </orm:basic>
      <orm:basic name="emp_name" attribute-type="java.lang.String">
         <orm:column name="emp_name"/>
      </orm:basic>
   </orm:attributes>
</orm:embeddable>

Back to the top