users@glassfish.java.net

Re: JackRabbit JCA Classloading issues

From: Gustavo Henrique Orair <gustavo.orair_at_gmail.com>
Date: Wed, 21 Dec 2011 19:50:42 -0200

Hi Jagadish and Sahoo,

I changed the class loading policy to global.
It resulted in many conflicts because the classes and resources inside the
resource-adapter were "preferred" against my own libraries and
implementations. These are some of the conflicts:
1- Derby dependence conflict
  Jackrabbit-jca has a derby library, I had to remove the derby library
dependency from jackrabbit-jca that was conflicting.
2 - commons-io conflict
My code uses new commons-io version 2 API. The code failed because
JackRabbit JCA is shipped with commons-io version 1.4. I replaced
commons-io 1.4 by the commons-io 2.0.1 inside jackrabbit-jca.

After solving these conflicts, there were unsolved issues with Logging
because jackrabbit-jca uses slf4j and logback and it broke my Logging also
based on slf4j and logback but I am ignoring this problems for a while.

But the client was able to get the Jcr Repository correctly and the
Crawlers were executed ok.

So, using classloader global policy did the trick, but I really would like
to solve the problem and keep the derived classloading policy.

I would really prefer a workaround such as inserting some xml inside ear
to inform to glassfish to make jackrabbit-jca resource adapter should be
available just to this specific application.

Best regards,
---------------------------------------------------------------------------------------------------------------------
                               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
------------------------------------------------------------------------------------------------------------------


2011/12/21 Gustavo Henrique Orair <gustavo.orair_at_gmail.com>

> Hi Jagadish,
>
> I really can't inject these resources in my ejb, this is motivated because
> in fact I am using a StorageFacade that may use a JcrStorage implementation
> or another storage implementation such as FSStorage. This is decided
> dynamically based on properties files. So, I really want to know how to get
> the JCR repository from the JackRabbit JCA using explicit JNDI lookup.
>
> If I really understand the problem, the best workaround from me would be
> insert in EAR's descriptor application.xml (or glassfish-resources.xml ???)
> a "fake" injection just to tell Glassfish that I want to get resources
> using explicit JNDI lookup that references the JackRabbit JCA Resource
> Adapter inside the EAR's modules.
>
> I read http://docs.oracle.com/cd/E18930_01/html/821-2418/bealr.html#gjjyyand searched for this resource-adapter-mid but I couldn't realize how
> exactly could I do that.
> May someone point me how to do that?
>
>
>
>
> Anyway, If you are really concerned why I need to make the explicit JNDI
> lookups, I will try to explain better the problem.
> My code has a Crawler class used to download documents from internet,
> these crawlers instances may be used both in a J2EE and J2SE environment.
> These crawlers just download the documents and storage them using a
> StorageFacade. There are two implementations of the StorageFacade:
> JCRStorage and FSStorage. The crawlers read a properties file to chose
> which implementation to be used. This feature is important for us because I
> do not need to change and compile code if I use different environments, I
> just need to change the properties file.
>
> If the JCRStorage is used, it get from another properties file the URI to
> be accessed and use the JcrUtils.getRepository method to access the JCR
> Repository. Again, this approach make possible to use the same binary
> without changing the code and compiling in both J2EE environment and J2SE
> environment. If I decided to change from a JackRabbit JCA get using
> explicit JNDI lookup to a Jackrabbit WebDav Server, I just need to change
> one properties file. Notice that this code used in the JCRStorage
> implementation uses just code from jackrabbit-jcr-commons module that is
> not tied to the JackRabbit implementation. It makes my framework very easy
> to change the JCR implementation. I would need just the
> jackrabbit-jcr-commons dependency inside my EAR and this would be the
> unique JackRabbit dependency inside the EAR.
>
> Actually, in production environment, I have a CrawlerManager EJB that
> creates, executes and manage the lifecycle of the Crawlers instances. In
> this environment I configure the StorageFacade to use JCRStorage
> implementation and the uri to be accessed:
> # Inform the Storage facade to get the JCR repository by an explicit Jndi
> lookup by the name jcr/Repository
> uri=jndi:jcr/Repository
> It results in an explicit JNDI lookup for the JCR Repository.
> The Jcr Repository is really accessed inside a class that may be used as
> J2SE and I cannot inject the repository.
> I need just make the explicit JNDI lookup works.
>
>
>
> ---------------------------------------------------------------------------------------------------------------------
> Gustavo Henrique Orair
>
> ------------------------------------------------------------------------------------------------------------------
>
>
> 2011/12/21 Jagadish Prasath Ramu <jagadish.ramu_at_oracle.com>
>
>> Hi Gustavo,
>>
>> If you have a <resource-ref> to a connector-resource of JackRabbit-RAR
>> in the application (either via @Resource or via the descriptor as Sahoo
>> stated), the application will be able to see the RAR classes. (Thread
>> context classloader should be application's classloader in this case and
>> it will have RAR's classloader in the parent's chain).
>>
>> Yes, "derived" is the default class-loading policy. You can try setting
>> it to "global" to see whether it works fine. Later, once you have the
>> <resource-ref> defined the application's descriptor (or @Resource), the
>> RAR will be available to the application.
>>
>> Reference:
>> http://docs.oracle.com/cd/E18930_01/html/821-2418/bealr.html#gjjyy
>>
>>
>> Thanks,
>> -Jagadish
>> On Wed, 2011-12-21 at 11:23 -0200, Gustavo Henrique Orair wrote:
>> > Hi Sahoo, thanks for your prompt response!
>> >
>> > Regarding your comment about my ejb seems to be accessing jackrabbit
>> > jca rar classes directly, my ejb uses just the JcrUtils.getRepository
>> > code. This class is provided by the jackrabbit-jcr-commons module.
>> > Inside this jackrabbit-jcr-commons module there is also a
>> > JndiRepositoryFactory class, this class should be found by the
>> > ServiceRegistry.lookupProviders(RepositoryFactory.class) and make an
>> > explicit JNDI lookup (as I used an URI with jndi: scheme). My ejb just
>> > need the jackrabbit-jcr-commons dependency and in fact, using this
>> > approach, I am not tied to JackRabbit implementation and could use any
>> > other JCR implementation (jackrabbit-jcr-commons module just use JCR
>> > API code). This is exactly the EAR3 use case I have provided in my
>> > first e-mail. Based on your concerns, this use case seems to fail
>> > because the explicit JNDI lookup couldn't get the JCR Repository.
>> >
>> > The problem seems to be really concerned (as you said in your first
>> > e-mail) as how org.apache.jackrabbit.client.RepositoryFactoryImpl
>> > class (inside jackrabbit-api module shipped with JackRabbit-JCA) try
>> > to load the org.apache.jackrabbit.core.RepositoryFactoryImpl class
>> > (inside jackrabbit-core module shipped with JackRabbit-JCA) since it
>> > uses Thread.currentThread().getContextClassLoader() instead of the
>> > default classLoader. Notice that the
>> > org.apache.jackrabbit.client.RepositoryFactoryImpl class is used in
>> > multiple different environments, not just J2EE or Glassfish, etc.
>> >
>> > My conclusion is that Glassfish's default class loading policy
>> > (derived) is incompatible with classloading policy expected by the
>> > jackrabbit-api module.
>> >
>> > Anyway, I will give your suggestion a try and change the code from
>> > org.apache.jackrabbit.client.RepositoryFactoryImpl class inside
>> > jackrabbit-api module to use the default classloader instead of
>> > Thread.currentThread().getContextClassLoader() while loading the
>> > org.apache.jackrabbit.core.RepositoryFactoryImpl class. But Apache
>> > Jackrabbit developers will probably argue this would break all other
>> > uses of this class in other environments.
>> >
>> >
>> ---------------------------------------------------------------------------------------------------------------------
>> > 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
>> >
>> ------------------------------------------------------------------------------------------------------------------
>> >
>> >
>> > 2011/12/20 Sahoo <sanjeeb.sahoo_at_oracle.com>
>> > No, it is not a bug. Your ejb modules does not have any
>> > resource references that are satisfied by jackrabbit rar. Your
>> > ejb seems to be accessing jackrabbit jca rar classes directly
>> > using jackrabbit API called JCRUtils and GlassFish has no idea
>> > that this dependency comes from jackrabbit rar. Add @Resource
>> > to your ejb to a jackrabbit rar supplied connection factory
>> > for the class loader to detect the dependency.
>> >
>> > Sahoo
>> >
>> > On Tuesday 20 December 2011 11:39 PM, Gustavo Henrique Orair
>> > wrote:
>> > > I checked the j2EE6 specification for classloading
>> > > behaviour.
>> > > In section 8.3.2 - EJB Container Class Loading Requirements
>> > > it states:
>> > >
>> > > "Components in the EJB container must have access to the
>> > > following classes and resources.
>> > > (...)
>> > > * The contents of all jar files included in each resource
>> > > adapter archive (rar file) deployed separately to the
>> > > application server, if that resource adapter is used to
>> > > satisfy any resource references in the module.
>> > > (...)"
>> > >
>> > > So, the behaviour I found in Glassfish seems like not J2EE6
>> > > compliant.
>> > >
>> > > Should I file a bug?
>> >
>> >
>> >
>>
>>
>>
>