[jboss-as7-dev] Embedded and split packages between modules and sun.boot.class.path

Kabir Khan kabir.khan at jboss.com
Fri Nov 26 13:10:47 EST 2010


I've got most of our demos ported across to use Arquillian, but came across a problem when running the ds example embedded:

org.jboss.util.NestedSQLException: Error checking for a transaction.; - nested throwable: (java.lang.reflect.UndeclaredThrowableException); - nested throwable: (org.jboss.jca.common.JBossResourceException: Error checking for a transaction.; - nested throwable: (java.lang.reflect.UndeclaredThrowableException))
	at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:115)
	at org.jboss.as.test.demos.ds.DsTestCase.testDatasource(DsTestCase.java:61)
         Arquillian in container
    ...
Caused by: org.jboss.jca.common.JBossResourceException: Error checking for a transaction.; - nested throwable: (java.lang.reflect.UndeclaredThrowableException)
	at org.jboss.jca.common.JBossResourceException.rethrowAsResourceException(JBossResourceException.java:60)
	at org.jboss.jca.core.connectionmanager.tx.TxConnectionManagerImpl.getManagedConnection(TxConnectionManagerImpl.java:363)
	at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.allocateConnection(AbstractConnectionManager.java:428)
	at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:109)
	... 81 more
Caused by: java.lang.reflect.UndeclaredThrowableException
	at org.jboss.jca.common.JBossResourceException.process(JBossResourceException.java:216)
	at org.jboss.jca.common.JBossResourceException.<init>(JBossResourceException.java:112)
	... 85 more
Caused by: java.lang.LinkageError: loader constraint violation: loader (instance of org/jboss/modules/ModuleClassLoader) previously initiated loading for a different type with name "javax/transaction/TransactionManager"
	at org.jboss.jca.core.connectionmanager.tx.TxConnectionManagerImpl.getManagedConnection(TxConnectionManagerImpl.java:350)
	... 83 more

This does not occur when running it normally using demos against a normal standalone instance.

In embedded on startup javax.transaction.TransactionManager gets loaded twice on startup
1) module:org.jboss.jts:main
2) org.jboss.jts.integration:main

In both these cases the defining classloader is the system classloader.

Then when running the deployed example it gets loaded using module:org.jboss.ironjacamar.impl:main which in turn gets the class from module:javax.transaction.api:main which has its own resource loader.

When starting up a normal standalone instance, in all cases the defining classloader is the javax.transaction.api module classloader. In both embedded and standalone scenarios, loading this class from the javax.transaction.api module gets two resource loaders. The SystemLocalLoader, and a module local loader for javax.transaction.api. The javax/transaction path is added to SystemLocalLoader since the JDK includes a few classes there (InvalidTransactionException, TransactionRequiredException, TransactionRolledbackException), so it is added from -Dsun.boot.class.path.
-In the standalone case the SystemLocalLoader is not able to load the TM class since it was never on the system classpath, so it loads it from the module loader.
-In the embedded case the SystemLocalLoader is able to load the TM class since it is on the app classpath, so the module loader never gets hit.

Before initializing modules -Djava.class.path is set to null, and org.jboss.modules and org.jboss.logging is added to Module.systemPackages.

I have patched jboss-modules to create a filter for this case here: https://github.com/kabir/jboss-modules/tree/Beta11-patch-filter but David might have a better idea?
If I start the embedded server with this snapshot and the following system properties, the ds testcase works fine

            SecurityActions.setSystemProperty("module.include.path", "javax/transaction/InvalidTransactionException,javax/transaction/TransactionRequiredException,javax/transaction/TransactionRolledbackException");
            SecurityActions.setSystemProperty("module.exclude.path", "javax/transaction/**");

This fix is only required for embedded, and will not have any effect during runtime of the standalone server (apart from an extra == null check).

A simpler way to configure this might be to just specify the names of filtered packages, e.g.
     -Dmodule.filtered.paths=javax.transaction,javax.transaction.xa
and then let the SystemLocalLoader intialization internally build up the excludes/includes depending on what it finds on 
the bootstrap path, so the module.filtered.paths becomes the following filter
{
  excludes={javax/transaction,javax/transaction/},
  includes={javax/transaction/InvalidTransactionException,javax/transaction/TransactionRequiredException,javax/transaction/TransactionRolledbackException}
}

Apart from these packages split between sun.boot.class.path and the modules classpath, embedded modules is exactly the same as standalone modules.

Cheers,

Kabir



More information about the jboss-as7-dev mailing list