OpenSubsystems

Business Components for Java Applications

Open Core

Implementing Support for a New J2EE Application Server

Last modified

$Author: bastafidli $
$Date: 2006/08/27 07:51:40 $
$Revision: 1.4 $
$RCSfile: implementation_newj2ee.html,v $

Open Core supports out of the box several J2EE application servers: JBoss, JOnAS, Weblogic, Websphere. If the J2EE Application server you are interested in is not yet supported by Open Core it is a straigh forward process to implement such support. This document describes in detail steps required to add support for a new application server into Open Core.

Adding New Libraries

Open Core is Java based framework and as such it easily integrates with any project developed in Java assuming it provides its deliverable in the form of jar files. In general you may not need any additional libraries to support your application server. In reality though, many application servers often provide tools to automate generation of various support classes such as stubs and skeletons and you may want to integrate these with your Ant-based build process. In such case it might be helpful to include these libraries in your build environment

If the libraries you have decided to use for your implementation are freely redistributable, we recommend to make them part of OpenSubsystems Externals and place them into

OpenSubsystems/external/[new application server name]

directory. It is also recommended that you rename all required files so that the filename doesn't contain version number of the particular release. This will make future upgrades easier since only the files will need to be updated and no other references will have to be modified.

Once the directory is created and all files are located inside, compress this directory into a single package

[new application server name].zip

and commit this package into OpenSubsystems CVS. Do not commit the uncompressed directory into CVS to prevent issues related to maintaining many individual externaly supplied files. Add this directory into .cvsignore file located in OpenSubsystems/external directory and commit this file into CVS.

For more information about adding new libraries read the following article.

The last step when adding new libraries is to modify the build-external.xml View source build file and create section that will include all the files required by the new application server when Open Core is built and distributed. These files might be required to rebuild the distribution from sources and therefore they need to be propertly installed.

Implementation

org.opensubsystems.core.util.J2EEUtils

Open Core attempts to automatically use the transaction manager and connection pool provided by J2EE application server once it detects that the application it is part of is running inside of such server. It also attempts to access the controllers as stateless session EJBs (to allow developer use container managed transactions if desired) rather than POJOs in this scenario. Open Core must be able to detect it is running inside of J2EE application server to support this behaviour.

The detection mechanism is specific to each application server. Open Core is trying to detect a feature to which it has access inside of J2EE application and which is unique to the new application server. This can be for example JNDI lookup of some value specific to a given server or detection of a class loader hierarchy unique to a particular server. The default implementation uses classloader detection to distinguish between different servers. If you want to use the same mechanism, you will need to know what is the class hierarchy for the new application server. When this ClassLoader is known, the J2EE server identification is quite easy to implements.

Modify class

org.opensubsystems.core.util.J2EEUtils View source

which is the class responsible for application server detection. Add here new constant identifying the new J2EE server. For example:

   /**
    * Constant defining NEWLY_ADDED j2ee server.
    */
   public static final int NEW_ADDED_J2EE_SERVER = [unique integer in this class];
               

Add new constant identifying newly added J2EE server. This is basically part of the ClassLoader class hierarchy that unambiguously identifies particular J2EE server. For example:

   /**
    * Constant identifying NEWLY_ADDED j2ee server.  
    * ClassLoader parent for NEWLY_ADDED server version x.y and x.z: 
    */
   public static final String NEWLY_ADDED_IDENTIFIER = "[j2ee_server_identifier]";
               

Modify method getJ2EEServerType() and add here condition for newly added J2EE server. For example:

   ...
   else if (strClassLoader.indexOf(NEWLY_ADDED_IDENTIFIER) > -1)
   {
      iRetValue = J2EE_SERVER_NEWLY_ADDED;
   }
               
org.opensubsystems.core.persist.db.transaction.J2EETransactionFactoryImpl

As mentioned before, Open Core allows application to use the transaction manager provided by the J2EE application server to manage its transactions. This is the default behaviour unless you specify different transaction manager in the configuration file View source. In order for this integration to work, Open Core has to have access to two objects specified by JTA, the TransactionManager and UserTransaction.

Modify class

org.opensubsystems.core.persist.db.transaction.J2EETransactionFactoryImpl View source

and lookup constants ARR_TRAN_MANAGER and ARR_USER_TRAN. These both contain known JNDI lookup names for the mentioned objects. If the JNDI lookup name value for your application server's transaction manager is not present in constant ARR_TRAN_MANAGER, add it to this array, for example:

   /**
    * An array of object references to the JNDI location of TransactionManager for:
    * a.) JBoss and JRun4 servers
    * b.) Resin, Orion (Oracle OC4J), JOnAS (JOTM), BEA WebLogic (unofficial) servers.
    * c.) BEA WebLogic Server (official)
    * d.) NEWLY_ADDED_SERVER
    */ 
   public static final String[] ARR_TRAN_MANAGER = {"java:/TransactionManager",
                                                    "java:comp/UserTransaction",
                                                    "javax.transaction.TransactionManager",
                                                    [newly_added_j2ee_server_TransactionManager]
                                                    }; 
               

In a similar fashion, if the JNDI lookup name value for your application server's UserTransaction is not present in constant ARR_USER_TRAN, add it to this array, for example:

   /**
    * An array of object references to the JNDI location of UserTransaction for:
    * a.) JBoss server
    * b.) JOnAS (JOTM), BEA WebLogic IBM WebSphere servers
    * d.) NEW_ADDED_SERVER
    */ 
   public static final String[] ARR_USER_TRAN = {"TransactionManager",
                                                 "java:comp/UserTransaction",
                                                 [new_added_j2ee_server_UserTransaction]
                                                }; 
               
org.opensubsystems.core.persist.db.connectionpool.J2EEDatabaseConnectionFactoryImpl

In a similar fashion as with the transaction manager, Open Core allows application to use the connection pooling capabilities provided by the J2EE application server in the form of a data source. This is the default behaviour unless you specify different connection pool in the configuration file View source.

Various application servers use slightly different location where to find data sources in a JNDI tree. When the data source location and name is known, the connection pool implementation is quite easy. The full datasource name consists of:

  • prefix - identifying location of the data source in the JNDI tree, e.g. "java:/", but it can also be empty.
  • datasource name - name of the data source. Open Core uses by default name "OSSDS" when requesting a connection from a connection pool, unless a different data source name is specified.

Modify class

org.opensubsystems.core.persist.db.connectionpool.J2EEDatabaseConnectionFactoryImpl View source

and add here constant identifying prefix to use when looking up data source specific to the newly added application server, for example:

   /**
    * Prefix of the data source that will be used for all data sources 
    * when running inside of NEWLY_ADDED server.
    */
   public static final String DATASOURCE_NAME_PREFIX_NEWLY_ADDED = "[newly_added_j2ee_server_DS_prefix]";
               

Next modify method createConnectionPool() in this class and add here condition for newly added application server, for example:

   ...					 
   case J2EEUtils.J2EE_SERVER_WEBSPHERE:
   {
      // Add prefix for NEW_ADDED server.
      dataSourceName.append(DATASOURCE_NAME_PREFIX_NEWLY_ADDED);
      break;
   }
               
org.opensubsystems.core.logic.J2EEControllerManager

When Open Core detects the application it is part of is running inside of a J2EE application server, it attempts to access controllers as stateless session EJBs instead of POJOs. This enables the container managed transactions specified using XDoclet attributes on method definitions. This behaviour is managed by class

org.opensubsystems.core.logic.J2EEControllerManager View source

You shouldn't have to modify this class since the JNDI names of the controllers EJBs should follow well defined patterns.

Configuration

oss.properties

OpenSubsystems is by default using oss.properties View source as it's main configuration file when running production applications. In general you do not have to modify this file since Open Core will automatically use the J2EE transaction manager, connection pool and controller manager when it detects it is running inside of J2EE application server.

osstest.properties

OpenSubsystems is by default using osstest.properties View source as it's main configuration file when running JUnit tests. As in the case of the production configuration file, there should not be a need to modify this file.

osstest[dbidentifier].properties

OpenSubsystems is using each of the osstest[dbidentifier].properties files for its configuration information when the tests are run against the specified database. For example configuration file for HSQLDB is in the

\OpenSubsystems\sources\config\osstesthsqldb.properties View source

As in the case of the production configuration file, there should not be a need to modify this file.

JUnit Tests

Open Core comes with about 150 JUnit tests that can be immediately used to test functionality of your new J2EE application server since most of them write to a database within transactions managed by the application server's transaction manager using connection obtained from application server's data sources. Open Core JUnit test suite includes also number of JUnit test cases, which specifically test transactional behaviour of the system such as commits, rollbacks and autocommit behaviour of the database connections as well as connection pooling characteristics of the data sources. To take advantage of these tests you need to execute these tests inside of your application server by invoking the TestServlet from the initial web page after the tests are deployed to the application server.