Skip to end of metadata
Go to start of metadata

Using Trails with JBoss and the Hibernate MBean

by Gert Jan Verhoog
Func. Internet Integration

Not Up To Date

2005-12-30 Solved latest issues - story will be updated next week. For now: don't try this at home yet (smile)

Introduction

This article sketches a possible way in which Trails can be deployed in JBoss using a shared Hibernate session factory. Both the implementation and this article may have some rough edges. Please regard this as a proof of concept, not necessarily production quality code.

The problem

Trails uses Hibernate as its persistence framework; see a VeryShortOverviewOfTrails for more info. One of Trails' strong proints is that it automatically detects which of your java beans are mapped with Hibernate to persistent storage. Trails gets the necessary information from a Hibernate Configuration object, retrieved from the sessionFactory bean, configured like this:

But what if the sessionFactory bean is of a different type? When using JBoss and a shared Hibernate session factory, the sessionFactory bean is configured like this:

The type of this bean is more generic than the LocalSessionFactoryBean defined above. Specifically, the method getConfiguration() is not available. This method is used by the HibernateDescriptorDecorator to build descriptors for mapped beans. This short article tries to provide a solution to this problem.

Using Trails with JBoss

We use JBoss 4.0.3RC1 with a shared Hibernate session factory and datasource. The datasource and session factory are available through jndi. For more information, consult the JBoss documentation.

In the following sections, 'JBOSS' is used in paths to denote the directory where JBoss is installed. JBoss' default server configuration is used.

Jars and class loader issues

In JBOSS/server/default/lib, the following jars should be present:

  • your jdbc driver (e.g. jtds, postgresql or another driver)
  • all hibernate jars

Important: class loading troubles

It is very important that the Hibernate jars are NOT present in war archives that use the shared session factory. This would result in your war not seeing the shared session factory.

Another issue is with trails, more specifically Hivemind (used by Tapestry, used by Trails): if trails.jar is present in both the lib directory and your war, Hivemind throws an exception because some services are defined multiple times. If trails is only present in the lib directory, your Trails application doesn't see the trails classes and bails. After some trial and error, the only combination that seemed to work for me was: trails.jar not in lib, only in the war archive.

The data source

in JBOSS/server/default/deploy, place a file my-ds.xml (the name is not important). Contents should look like this (consult the documentation for your jdbc driver for details):

The Hibernate MBean

As per chapter 13 of the JBoss documentation, we create a .har archive (a Hibernate Archive), with the following directory structure:

  • my-sessionfactory.har
    • my-domainclasses.jar
    • my-mapping1.hbm.xml
    • my-mapping2.hbm.xml
    • META-INF
      • jboss-service.xml

The my-domainclasses.jar should contain your hibernate mapped domain beans. The hbm.xml mapping files are found automatically by the MBean, provided they are not inside a jar. The jboss-service.xml looks like this:

this concludes the necessary JBoss setup. Now let's look at the trails application side.

Your Trails application in JBoss

include/exclude from your war.

Make sure your war archive does NOT contain the hibernate jars and jdbc driver, since they will already be present in JBoss (see above). your trails application could contain the jar holding your domain classes and must contain the hbm.xml mapping files.

The Spring configuration

The sessionFactory and dataSource beans should be configured differently, since we're using the objects provided by JBoss:

Patching Trails

You would think that the configuration above is all we need, after all, this is what makes Spring so cool: swap out your LocalSessionFactoryBean for a JndiFactoryBean in the config and everything just works. Unfortunately, Trails uses a method that is specific to =LocalSessionFactoryBean=, which we don't use here. The code that uses this method is located in a single class: HibernateDescriptorDecorator. This class uses LocalSessionFactoryBean's getConfiguration() method to access the mapping objects (java representations of the .hbm.xml files).

By modifying this class, we add the possibility of providing .hbm.xml files in the Spring configuration while maintaining backwards compatibility. The spring configuration now looks like this:

The mapping files should be present in your application, in the root of your classpath in the example above. The new implementation of HibernateDescriptorDecorator, based on trails 0.8 code, is listed at the end of this article.

One last thing

Unfortunately, our changes still don't produce a working application. There is a problem with the trails class TrailsDescriptorService. The trailsDescriptorService holds a Map from (mapped) classes to descriptors. The keys for this map are Class objects. The descriptor map is initialized with all mapped classes found in the hibernate mapping files. The getClassDescriptor method does a map lookup with a Class object.

So, for example, a descriptor is placed in the map with Class object class my.example.Foo as the key and a IClassDescriptor as its value. When you call getClassDescriptor with a Class object class my.example.Foo, you would think that you'd get your class descriptor, right? wrong! Probably due to class loader issues, both Class objects are not equal. I have changed the TrailsDescriptorService code to use someClass.getName() as the key for the descriptor map. Code is provided below.

Concluding remarks

This concludes our efforts to get Trails working with JBoss. Please note that this code isn't really thoroughly tested yet, and some issues remain: Trails adds some event listeners to the hibernate sessionfactory that are not present in our shared hibernate mbean. We're still looking into this problem.

Listing: HibernateJbossDescriptorDecorator

This is our new HibernateDescriptorDecorator. It is backwards compatible with trails 0.8 code (a localSessionFactoryBean property will still be used if present in the applicationContext.xml) but adds the possibility of providing mapping files in a list.

Listing: TrailsDescriptorService

Labels
  • None