Sunday, January 15, 2012

A Maven Based Solution Towards J2EE Standardization

http://maven.apache.org/
By reading this post, you should already know that "WORA - Write Once Run Anywhere" motto of Java has today become "WODE - Write Once Debug Everywhere"

You all know J2EE has to be based on standards and unless you have the option to push or use the application server of your choice, you will always run into portability issues.

Recently I have been asked to port a currently-running-on-websphere application to JBoss. An guess what, had to spend considerable amount of time in every detail. This is thanks to a non-standard JNDI approach of J2EE, which still appears to be an issue with J2EE 6.

Due to fact that putting convention over configurationmaven has already run into hundreds of problems, which thanks to its highly modular design somehow survived with a solution. This time the solution came from resources plugin.


My first headache started with persistence of JBoss datasource JNDI to be in the form of java:jboss/datasources/myds. However although weblogic allowed any form of JNDI name for the datasource, somehow it didn't like the same JNDI name. A similar problem was passing the correct transaction manager lookup class to hibernate.

The solution was to replace the datasource name with a variable like ${datasource.jndi} in the persistence.xml. Now persistence.xml looked like this:

<persistence>
  <persistence-unit name="gui">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>${jta.datasource.jndi}</jta-data-source>

    <properties>
      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
      <property name="hibernate.show_sql" value="false" />
      <property name="hibernate.format_sql" value="true" />
      <property name="hibernate.generate_statistics" value="true" />
      <property name="hibernate.jdbc.batch_size" value="50" />
      <property name="hibernate.max_fetch_depth" value="3" />
      <property name="hibernate.cache.use_query_cache" value="false" />
      <property name="hibernate.cache.use_second_level_cache" value="false" />
      <property name="hibernate.connection.release_mode" value="on_close" />
      <property name="hibernate.hbm2ddl.auto" value="update" />
      <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory" />
      <property name="hibernate.transaction.manager_lookup_class" value="${transaction.manager.lookup.class}" />
    </properties>
  </persistence-unit>
</persistence>

${jta.datasource.jndi} and ${transaction.manager.lookup.class} variables were the pointers to create a build for the environment.

Now to pass the correct values - by being a true open source programmer - I picked JBoss as the default environment, and added the following properties to the pom.xml:


<project>
  ...
  <properties>
    <jta.datasource.jndi>java:jboss/datasources/pims</jta.datasource.jndi>
    <transaction.manager.lookup.class>org.hibernate.transaction.JBossTransactionManagerLookup</transaction.manager.lookup.class>
  </properties>
  ...
</project>

Now, being in favor of JBoss, I needed to create a profile to pass values that will make Weblogic happy.

<project>
  ...
  <profiles>
    <profile>
      <id>Weblogic</id>
      <properties>
        <jta.datasource.jndi>pims</jta.datasource.jndi>
        <transaction.manager.lookup.class>org.hibernate.transaction.WeblogicTransactionManagerLookup</transaction.manager.lookup.class>
      </properties>
    </profile>
  </profiles>
  ...
</project>

One last thing is to tell maven to do resource filtering.

<project>
  ...
  <build>
    ...
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>
  </build>
  ...
</project>

Well, I am aware that this is not 100% compliant with the maven design. The problem here is I cannot deploy my artifact to a repository. For now this will be another thing to research and solve, but for now, as the project is built for the environment selected at the time of the build, my solution sufficed.

Happy mavening...

No comments:

Post a Comment

Enter your comment...