users@glassfish.java.net

Re: JackRabbit JCA Classloading issues

From: Sahoo <sanjeeb.sahoo_at_oracle.com>
Date: Wed, 21 Dec 2011 06:01:29 +0530

Gustavo,

In your case, one jackrabbit class is loading another jackrabbit class.
I don't see any reason to load using thread's context class loader.
Could you try changing
    Class<?> repositoryFactoryClass =
Class.forName("org.apache.jackrabbit.core.RepositoryFactoryImpl",
true,Thread.currentThread().getContextClassLoader());
to
    Class<?> repositoryFactoryClass =
Class.forName("org.apache.jackrabbit.core.RepositoryFactoryImpl");

Sahoo

On Tuesday 20 December 2011 01:13 AM, Gustavo Henrique Orair wrote:
> I have some issues with Glassfish ClassLoader.
>
> I am using JackRabbit JCA (Resource Adapter for JCR Repositories) to
> provide JCR repositories (JSR-283).
>
> I have many problems and all looks like related to classloading.
>
> It looks like that Glassfish ClassLoader do not find the libraries
> inside the jackrabbit JCA rar.
> JackRabbit JCA is shipped with JackRabbit Core inside that provides
> the "server implementation". But the class with this implementation is
> not found by the classloader.
>
> I will try to explain what I found trying to solve this problem and
> the workarounds I've used and see if someone may help me to understand
> better the problems and how to solve them (or file a bug).
>
> JackRabbit JCA is a Resource Adapter. You may create connection pool
> for a specific JCR Repository providing some parameters such as
> HomeDir (the directory where the repository is found).
> JackRabbit JCA based on these parameters specified uses
> org.apache.jackrabbit.client.RepositoryFactoryImpl class. This
> RepositoryFactoryImpl class just get the parameters specified and
> check the existence of the HomeDir parameter. When this HomeDir
> parameter is found, it try to load the class
> org.apache.jackrabbit.core.RepositoryFactoryImpl dynamically (provided
> in jackrabbit-core inside the jackrabbit-jca). The code used to load
> org.apache.jackrabbit.core.RepositoryFactoryImpl is similar to:
> Class<?> repositoryFactoryClass =
> Class.forName("org.apache.jackrabbit.core.RepositoryFactoryImpl",
> true,Thread.currentThread().getContextClassLoader());
> repositoryFactory = repositoryFactoryClass.newInstance();
>
> If the clients perform explicit JNDI lookups, the
> org.apache.jackrabbit.client.RepositoryFactoryImpl is not being found.
>
>
> Another very common option for the clients to access the JCR
> repository is to use JcrUtils.getRepository(String uri) provided in
> jackrabbit-jcr-commons (specifying a "jndi:jcr/Repository" uri) . This
> utility basically search using ServiceRegistry.lookupProviders for
> RepositoryFactory providers that accepts the parameters specified. Code:
> Iterator<RepositoryFactory> iterator =
> ServiceRegistry.lookupProviders(RepositoryFactory.class);
>
> Using this utility, the code fails again (it really make an explicit
> JNDI lookup inside JndiRepositoryFactory class).
>
> Since these classes were not being found inside JackRabbit JCA, I
> tried as a workaround to add jackrabbit-core and jackrabbit-commons
> modules inside the EAR.
> I was able to get the repository but I needed another workaround.
> I added JMX methods to a singleton EJB to make the tests easier (and
> study JMX classloader issues).
> If I invoke JCRUtils.getRepository directly from this singleton EJB,
> the RepositoryFactory implementations are not found.
> So, I did a following workaround: Created a Stateless Session bean.
> The Singleton EJB works like a "proxy" and just delegate the methods
> from Singleton ejb to the stateless ejb. Using this workround, finally
> I could successfully get a JCR repository using JNDI. Additional note:
> if the delegation is done to static methods defined in the stateless
> ejb, the workaround doesn't work.
>
>
> To make easier to reproduce these problems,
> I have created a small EJB module with the stateless and the singleton
> ejb as discussed.
> This EJB module has a Singleton JMXServiceActivator. The
> JMXServiceActivator is registered in managed bean server as
> app.JMXServiceActivator and you can use jmx client (such as jconsole)
> to launch the following methos:
> 1 - getRepositoryUsingExplicitJNDI(String jndiName);
> 2 - getRepositoryUsingJCRUtils(String jndiName);
> 3 - getRepositoryUsingExplicitJNDIWithoutProxy(String jndiName);
> 4 - getRepositoryUsingJCRUtilsWithoutProxy(String jndiName);
>
> After, I created 3 different client EARs to check all these issues
> (attached in this e-mail):
> 1 - EAR
> No Jackrabbit dependencies
> (It should be possible to get the jackrabbit repository using
> explicit JNDI)
> 2 - EAR2
> jackrabbit-commons and jackrabbit-core dependences
> (it really can get the JCR repository but a "proxy" using Stateless
> session being is needed to make it work)
> 3 - EAR3
> Just jackrabbit-commons dependency
> (It should be possible to get the JCR repository using
> JCRUtils.getRepository(String uri) but it does not work)
>
> I am doing something wrong?
> Are these really Classloading bugs?
> Is this just an unique bug or there are multiple bugs involved?
>
>
>
> ---------------------------------------------------------------------------------------------------------------------
> Gustavo Henrique Orair
> Mestre em Ciência da Computação - MSc in Computer Science
> Universidade Federal de Minas Gerais
> Celular/Cell phone: 55-31-85157887
> ------------------------------------------------------------------------------------------------------------------