JPOX
JPOX
 Project  |  Ver 1.1  |  Ver 1.2  |  JDO  |  JPA  |  Guides  |  Tools
1.2 | Persistence | JDO ORM | JPA ORM | Runtime | JDO Runtime | JPA Runtime | Extensions | Developer
JDO Runtime
JDO Queries
JPOX - Usage within a J2EE environment

The J2EE framework has become popular in some places in the last 3 years. It provides a container within which java processes operate and it provides mechanisms for, amongst other things, transactions (JTA), and for connecting to other (3rd party) utilities (using Java Connector Architecture, JCA). JPOX can be utilised within a J2EE environment via this JCA system, and we provide a Resource Adaptor (RAR file) containing this JCA adaptor allowing JPOX to be used with the likes of WebLogic and JBoss. You can find the JPOX JCA adapter in the download "jpox-jca". Instructions are provided for the following J2EE servers

The provided JPOX JCA rar provides default resource adapter descriptors, one general, and the other for the WebLogic J2EE server. These resource adapter descriptors can be configured to meet your needs, for example allowing XA transactions instead of the default Local transactions.



Requirements

To use JPOX with JCA the first thing that you will require is the jpox-jca-{version}.rar file (available from the download section).



JPOX Resource Adaptor and transactions

A great advantage of JPOX implementing the ManagedConnection interface is that the J2EE container manages transactions for you (no need to call the begin/commit/rollback-methods). Currently, local transactions and distributed (XA) transactions are supported. Within a J2EE environment, JDO transactions are nested in J2EE transactions. All you have to do is to declare that a method needs transaction management. This is done in the EJB meta data. Here you will see, how a SessionBean implementation could look like.

The EJB meta data is defined in a file called ejb-jar.xml and can be found in the META-INF directory of the jar you deploy. Suppose you deploy a bean called JPOXBean, your ejb-jar.xml should contain the following configuration elements:

<session>
	<ejb-name>JPOXBean</ejb-name>
	...
	<transaction-type>Container</transaction-type>
	...
<session>

Imagine your bean defines a method called testJPOXTrans():

<container-transaction>
    <method >
        <ejb-name>JPOXBean</ejb-name>
        ...
        <method-name>testJPOXTrans</method-name>
    </method>
    <trans-attribute>Required</trans-attribute>
</container-transaction>

You hereby define that transaction management is required for this method. The container will automatically begin a transaction for this method. It will be commited if no error occurs or rolled back otherwise. A potential SessionBean implementation containing methods to retrieve a PersistenceManager then could look like this:

public abstract class JPOXBean implements SessionBean 
{
    // EJB methods	
    public void ejbCreate() 
    throws CreateException
    {
    }

    public void ejbRemove() 
    throws EJBException, RemoteException 
    { 
    }

    // convenience methods to get
    // a PersistenceManager

    /**
     * static final for the JNDI name of the PersistenceManagerFactory
     */
    private static final String PMF_JNDI_NAME = "java:/jpox1";
	
    /**
     * Method to get the current InitialContext
     */
    private InitialContext getInitialContext() throws NamingException 
    {
        InitialContext initialContext = new InitialContext();
        // or other code to create the InitialContext eg. new InitialContext(myProperies);
        return initialContext;
    }

    /**
     * Method to lookup the PersistenceManagerFactory
     */
    private PersistenceManagerFactory getPersitenceManagerFactory(InitialContext context) 
    throws NamingException 
    {
        return (PersistenceManagerFactory) context.lookup(PMF_JNDI_NAME);
    }
	
    /**
     * Method to get a PersistenceManager
     */
    public PersistenceManager getPersistenceManager() 
    throws NamingException 
    {
        return getPersitenceManagerFactory(getInitialContext()).getPersistenceManager();
    }

    // Now finally the bean method within a transaction

    public viod testJPOXTrans() 
    throws Exception
    {
        PersistenceManager pm = getPersistenceManager()
        try {
            // Do something with your PersistenceManager
        } finally {
            // close the PersistenceManager
            pm.close();
        }
    }
}

Make sure, you close the PersistenceManager in your bean methods. If you don't, the J2EE server will usually close it for you (one of the advantages), but of course not without a warning or error message.

To avoid the need of editing multiple files, you could use XDoclet to generate your classes and control the metadata by xdoclet tags. The method declaration then would look like this:

    /**
     * @ejb.interface-method
     * @ejb.transaction type="Required"
     */
    public viod testJPOXTrans() 
    throws Exception
    {
        //...
    }

These instructions were adapted from a contribution by a JPOX user Alexander Bieber.



Persistence Properties

When creating a PMF using the JCA adaptor, you should specify your persistence properties using a persistence.xml or jdoconfig.xml. This is because JPOX JCA adapter from version 1.2.2 does not support Java bean setters/getters for all properties - since it is an inefficient and inflexible mechanism for property specification. The more recent persistence.xml and jdoconfig.xml methods lead to more extensible code.



General configuration

A resource adapter has one central configuration file /META-INF/ra.xml which is located within the rar file and which defines the default values for all instances of the resource adapter (i.e. all instances of PersistenceManagerFactory). Additionally, it uses one or more deployment descriptor files (in JBoss, for example, they are named *-ds.xml) to set up the instances. In these files you can override the default values from the ra.xml.

Since it is bad practice (and inconvenient) to edit a library's archive (in this case the jpox-jca-${version}.rar) for changing the configuration (it makes updates more complicated, for example), it is recommended, not to edit the ra.xml within JPOX' rar file, but instead put all your configuration into your deployment descriptors. This way, you have a clean separation of which files you maintain (your deployment descriptors) and which files are maintained by others (the libraries you use and which you simply replace in case of an update).

Nevertheless, you might prefer to declare default values in the ra.xml in certain circumstances, so here's an example:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE connector PUBLIC "-//Sun Microsystems, Inc.//DTD Connector 1.0//EN" 
    "http://java.sun.com/dtd/connector_1_0.dtd">
<connector>
    <display-name>JPOX Connector</display-name>
    <description></description>
    <vendor-name>JPOX Team</vendor-name>
    <spec-version>1.0</spec-version>
    <eis-type>JDO Adaptor</eis-type>
    <version>1.0</version>
    <resourceadapter>
        <managedconnectionfactory-class>org.jpox.resource.ManagedConnectionFactoryImpl</managedconnectionfactory-class>
        <connectionfactory-interface>javax.resource.cci.ConnectionFactory</connectionfactory-interface>
        <connectionfactory-impl-class>org.jpox.resource.PersistenceManagerFactoryImpl</connectionfactory-impl-class>
        <connection-interface>javax.resource.cci.Connection</connection-interface>
        <connection-impl-class>org.jpox.resource.PersistenceManagerImpl</connection-impl-class>
        <transaction-support>LocalTransaction</transaction-support>
        <config-property>
          <config-property-name>ConnectionFactoryName</config-property-name>
          <config-property-type>java.lang.String</config-property-type>
          <config-property-value>jdbc/ds</config-property-value>
        </config-property>
        <config-property>
          <config-property-name>AutoCreateSchema</config-property-name>
          <config-property-type>boolean</config-property-type>
          <config-property-value>true</config-property-value>
        </config-property>
        <authentication-mechanism>
          <authentication-mechanism-type>BasicPassword</authentication-mechanism-type>
          <credential-interface>javax.resource.security.PasswordCredential</credential-interface>
        </authentication-mechanism>
        <reauthentication-support>false</reauthentication-support>
    </resourceadapter>
</connector>
                

The file shown above has a section for configuration properties. JPOX provides many, as described in the PMF Guide. You can specify these via JCA. The table below shows a selection of the config property names and types. Please refer to the list defined for the PersistenceManagerFactory for a complete list.

config-property-nameconfig-property-typeconfig-property-value
ConnectionURLjava.lang.String
ConnectionDriverNamejava.lang.String
ConnectionUserNamejava.lang.String
ConnectionPasswordjava.lang.String
ConnectionFactoryNamejava.lang.String
ConnectionFactory2Namejava.lang.String
Multithreadedbooleantrue | false
Optimisticbooleantrue | false
RetainValuesbooleantrue | false
RestoreValuesbooleantrue | false
NontransactionalReadbooleantrue | false
NontransactionalWritebooleantrue | false
IgnoreCachebooleantrue | false
Catalogjava.lang.String
Schemajava.lang.String
StoreManagerTypejava.lang.Stringrdbms
AutoCreateSchemabooleantrue | false
AutoCreateTablesbooleantrue | false
AutoCreateColumnsbooleantrue | false
AutoCreateConstraintsbooleantrue | false
CheckExistTablesOrViewsbooleantrue | false
ValidateTablesbooleantrue | false
ValidateConstraintsbooleantrue | false
AutoStartMechanismjava.lang.StringSchemaTable | None
AutoStartMechanismModejava.lang.StringQuiet | Ignored | Checked
TransactionIsolationint
UseUpdateLockbooleantrue | false
IdentifierCasejava.lang.String
FullyQualifiedNamesbooleantrue | false
MetadataFileExtensionjava.lang.Stringjdo
DatastoreTransactionDelayOperationsbooleantrue | false
UniqueConstraintsMapInversebooleantrue | false
PersistentIdGeneratorjava.lang.String
PoidTransactionIsolationLevelint
PoidTransactionAttributejava.lang.String
JdoCacheLevel1Typejava.lang.Stringweak
JdoCacheLevel2booleantrue | false
JdoCacheLevel2Typejava.lang.StringDefault
JdoCacheLevel2CacheNamejava.lang.String
JdoCacheCollectionsbooleantrue | false


WebLogic

To use JPOX on Weblogic the first thing that you will require is the jpox-{version}.rar file. You then may need to edit the /META-INF/weblogic-ra.xml file to suit the exact version of your WebLogic server (the included file is for WebLogic 8.1).

You then deploy the RAR file on your WebLogic server.

JBoss 3.0/3.2

To use JPOX on JBoss (Ver 3.2) the first thing that you will require is the jpox-{version}.rar file. You should put this in the deploy ("${JBOSS}/server/default/deploy/") directory of your JBoss installation.

You then create a file, also in the deploy directory with name jpox-ds.xml. To give a guide on what this file will typically include, see the following

<?xml version="1.0" encoding="UTF-8"?>
<connection-factories>
    <tx-connection-factory>
        <jndi-name>jpox</jndi-name>
        <adapter-display-name>JPOX Connector</adapter-display-name>
        <config-property name="ConnectionDriverName" 
            type="java.lang.String">com.mysql.jdbc.Driver</config-property>
        <config-property name="ConnectionURL"
            type="java.lang.String">jdbc:mysql://localhost/yourdbname</config-property>
        <config-property name="UserName"
            type="java.lang.String">yourusername</config-property>
        <config-property name="Password"
            type="java.lang.String">yourpassword</config-property>
        <config-property name="AutoCreateSchema"
            type="boolean">true</config-property>
    </tx-connection-factory>
  
    <tx-connection-factory>
        <jndi-name>jpox1</jndi-name>
        <adapter-display-name>JPOX Connector</adapter-display-name>
        <config-property name="ConnectionDriverName"
            type="java.lang.String">com.mysql.jdbc.Driver</config-property>
        <config-property name="ConnectionURL"
            type="java.lang.String">jdbc:mysql://localhost/yourdbname1</config-property>
        <config-property name="UserName"
            type="java.lang.String">yourusername</config-property>
        <config-property name="Password"
            type="java.lang.String">yourpassword</config-property>
        <config-property name="AutoCreateSchema"
            type="boolean">true</config-property>
    </tx-connection-factory>
  
    <tx-connection-factory>
        <jndi-name>jpox2</jndi-name>
        <adapter-display-name>JPOX Connector</adapter-display-name>
        <config-property name="ConnectionDriverName"
            type="java.lang.String">com.mysql.jdbc.Driver</config-property>
        <config-property name="ConnectionURL"
            type="java.lang.String">jdbc:mysql://localhost/yourdbname2</config-property>
        <config-property name="UserName"
            type="java.lang.String">yourusername</config-property>
        <config-property name="Password"
            type="java.lang.String">yourpassword</config-property>
        <config-property name="AutoCreateSchema"
            type="boolean">true</config-property>
    </tx-connection-factory>
</connection-factories>
                

This example creates 3 connection factories to MySQL databases, but you can create as many or as few as you require for your system to whichever databases you prefer (as long as they are supported by JPOX). With the above definition we can then use the JNDI names java:/jpox, java:/jpox1, and java:/jpox2 to refer to our datastores.

Note, that you can use separate deployment descriptor files. That means, you could for example create the three files jpox1-ds.xml, jpox2-ds.xml and jpox3-ds.xml with each declaring one PersistenceManagerFactory instance. This is useful (or even required) if you need a distributed configuration. In this case, you can use JBoss' hot deployment feature and deploy a new PersistenceManagerFactory, while the server is running (and working with the existing PMFs): If you create a new *-ds.xml file (instead of modifying an existing one), the server does not undeploy anything (and thus not interrupt ongoing work), but will only add the new connection factory to the JNDI.

You are now set to work on JPOX-enabling your actual application. As we have said, you can use the above JNDI names to refer to the datastores, so you could do something like the following to access the PersistenceManagerFactory to one of your databases.

import javax.jdo.PersistenceManagerFactory;

InitialContext context=new InitialContext();
PersistenceManagerFactory pmFactory=(PersistenceManagerFactory)context.lookup("java:/jpox1");

These instructions were adapted from a contribution by a JPOX user Marco Schulze.



JBoss 4.0

With JBoss 4.0 there are some changes in configuration relative to JBoss 3.2 in order to allow use some new features of JCA 1.5. Here you will see how to configure JBoss 4.0 to use with JPOX JCA adapter for Apache Derby DBMS.

To use JPOX on JBoss 4.0 the first thing that you will require is the jpox-{version}.rar file. You should put this in the deploy directory ("${JBOSS}/server/default/deploy/") of your JBoss installation. Additionally, you have to remember to put any JDBC driver files to lib directory ("${JBOSS}/server/default/lib/") if JBoss does not have them installed by default. In case of Apache Derby you need to copy db2jcc.jar and db2jcc_license_c.jar.

You then create a file, also in the deploy directory with name jpox-ds.xml. To give a guide on what this file will typically include, see the following

<?xml version="1.0" encoding="UTF-8"?>
<connection-factories>
    <tx-connection-factory>
        <jndi-name>jpox</jndi-name>
        <rar-name>jpox-{version}.rar</rar-name> <!-- the name here must be the same as JCA adapter filename -->
        <connection-definition>javax.resource.cci.ConnectionFactory</connection-definition>
        <config-property name="ConnectionDriverName" 
            type="java.lang.String">com.ibm.db2.jcc.DB2Driver</config-property>
        <config-property name="ConnectionURL"
            type="java.lang.String">jdbc:derby:net://localhost:1527/"directory_of_your_db_files"</config-property>
        <config-property name="UserName"
            type="java.lang.String">app</config-property>
        <config-property name="Password"
            type="java.lang.String">app</config-property>
        <config-property name="StoreManagerType"
            type="java.lang.String">rdbms</config-property>
        <config-property name="AutoCreateSchema"
            type="boolean">true</config-property>
        <config-property name="ValidateTables"
            type="boolean">false</config-property>
        <config-property name="ValidateConstraints"
            type="boolean">false</config-property>
        </tx-connection-factory>
</connection-factories>

You are now set to work on JPOX-enabling your actual application. You can use the above JNDI name to refer to the datastores, and so you could do something like the following to access the PersistenceManagerFactory to one of your databases.

import javax.jdo.PersistenceManagerFactory;

InitialContext context=new InitialContext();
PersistenceManagerFactory pmFactory=(PersistenceManagerFactory)context.lookup("java:/jpox");

These instructions were adapted from a contribution by a JPOX user Maciej Wegorkiewicz.



Jonas

To use JPOX on Jonas the first thing that you will require is the jpox-{version}.rar file. You then may need to edit the /META-INF/jonas-ra.xml file to suit the exact version of your Jonas server (the included file is tested for Jonas 4.8).

You then deploy the RAR file on your Jonas server.

Transaction Support

JPOX JCA adapter supports both Local and XA transaction types. Local means that a transaction will not have more than one resource managed by a Transaction Manager and XA means that multiple resources are managed by the Transaction Manager. Use XA transaction, if JPOX is configured to use data sources deployed in application servers, or if other resources such as JMS connections are used in the same transaction, otherwise use Local transaction.

You need to configure the ra.xml file with the appropriate transaction support, which is either XATransaction or LocalTransaction. See the example:

<connector>
    <display-name>JPOX Connector</display-name>
    <description></description>
    <vendor-name>JPOX Team</vendor-name>
    <spec-version>1.0</spec-version>
    <eis-type>JDO Adaptor</eis-type>
    <version>1.0</version>
    <resourceadapter>
        <managedconnectionfactory-class>org.jpox.resource.ManagedConnectionFactoryImpl</managedconnectionfactory-class>
        <connectionfactory-interface>javax.resource.cci.ConnectionFactory</connectionfactory-interface>
        <connectionfactory-impl-class>org.jpox.resource.PersistenceManagerFactoryImpl</connectionfactory-impl-class>
        <connection-interface>javax.resource.cci.Connection</connection-interface>
        <connection-impl-class>org.jpox.resource.PersistenceManagerImpl</connection-impl-class>
        <transaction-support>XATransaction</transaction-support> <!-- change this line -->
    ...
Data Source

To use a data source, you have to configure the connection factory name in ra.xml file. See the example:

<connector>
    <display-name>JPOX Connector</display-name>
    <description></description>
    <vendor-name>JPOX Team</vendor-name>
    <spec-version>1.0</spec-version>
    <eis-type>JDO Adaptor</eis-type>
    <version>1.0</version>
    <resourceadapter>
        <managedconnectionfactory-class>org.jpox.resource.ManagedConnectionFactoryImpl</managedconnectionfactory-class>
        <connectionfactory-interface>javax.resource.cci.ConnectionFactory</connectionfactory-interface>
        <connectionfactory-impl-class>org.jpox.resource.PersistenceManagerFactoryImpl</connectionfactory-impl-class>
        <connection-interface>javax.resource.cci.Connection</connection-interface>
        <connection-impl-class>org.jpox.resource.PersistenceManagerImpl</connection-impl-class>
        <transaction-support>XATransaction</transaction-support>

        <config-property>
            <config-property-name>ConnectionFactoryName</config-property-name>
            <config-property-type>java.lang.String</config-property-type>
            <config-property-value>jndiName_for_datasource_1</config-property-value>
        </config-property>
            <config-property>
            <config-property-name>ConnectionResourceType</config-property-name>
            <config-property-type>java.lang.String</config-property-type>
            <config-property-value>JTA</config-property-value>
        </config-property>
        <config-property>
            <config-property-name>ConnectionFactory2Name</config-property-name>
            <config-property-type>java.lang.String</config-property-type>
            <config-property-value>jndiName_for_datasource_2</config-property-value>
        </config-property>
    ...

See also :