users@glassfish.java.net

Re: JackRabbit JCA Classloading issues

From: Sahoo <sanjeeb.sahoo_at_oracle.com>
Date: Fri, 23 Dec 2011 06:40:51 +0530

Have you tried changing jackrabbit to not use Thread's context class
loader? If not, try that first. If you have,
I suggest you do the following:

File an issue.
Attach your test cases.
Attach jackrabbit rar (after and before modification).
Add instructions to reproduce what you are observing.

Sahoo

On Friday 23 December 2011 01:31 AM, Gustavo Henrique Orair wrote:
> Dear all,
>
> I tried to write both glassfish-application.xml and
> glassfish-resources.xml to make jackrabbit-jca work together to
> derived classloading policy.
> But, these files didn't change the classloader behaviour.
>
> I am senting attached the Sample Maven Project I've used to test these
> concerns.
> I've attached again the examples EAR generated. Notice my use case is
> EAR3 module (ear with only jackrabbit-jcr-commons dependency)... The
> JndiRepositoryFactory class inside jackrabbit-jcr-commons performed
> an explicit JNDI lookup. It found the JNDI resource, got the
> connection pool parameters and tried to create the Repository, but the
> creation failed because the provider's classes inside jackrabbit-jca
> were not found (you can see in stacktrace the unique provider found
> was JndiRepositoryFactory from jackrabbit-jcr-commons module installed
> inside the ear's lib directory).
>
> These are the content of glassfish-application.xml and
> glassfish-resources.xml files:
> glassfish-application.xml:
> <!DOCTYPE glassfish-application PUBLIC "-//GlassFish.org//DTD
> GlassFish Application Server 3.1 Java EE Application 6.0//EN"
> "http://glassfish.org/dtds/glassfish-application_6_0-1.dtd">
> <glassfish-application>
> <resource-ref>
> <res-ref-name>jcr/Repository</res-ref-name>
> <jndi-name>jcr/Repository</jndi-name>
> </resource-ref>
> </glassfish-application>
>
> glassfish-resources.xml:
> <?xml version="1.0" encoding="UTF-8"?>
> <!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish
> Application Server 3.1 Resource Definitions//EN"
> "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
> <resources>
> <connector-connection-pool name="cp_jcr_repository"
> resource-adapter-name="jackrabbit-jca"
> connection-definition-name="javax.jcr.Repository">
> <property name="HomeDir" value="/tmp/jcr_repository"></property>
> </connector-connection-pool>
> <connector-resource pool-name="cp_jcr_repository"
> jndi-name="jcr/Repository"></connector-resource>
> </resources>
>
>
> Stack trace:
> Caused by: javax.jcr.RepositoryException: Unable to access a
> repository with the following settings:
> org.apache.jackrabbit.repository.home: /tmp/jcr_repository
> The following RepositoryFactory classes were consulted:
> org.apache.jackrabbit.commons.JndiRepositoryFactory: declined
> Perhaps the repository you are trying to access is not available at
> the moment.
> at
> org.apache.jackrabbit.commons.JcrUtils.getRepository(JcrUtils.java:215)
> at
> org.apache.jackrabbit.jca.JCARepositoryManager.createRepository(JCARepositoryManager.java:71)
> at
> org.apache.jackrabbit.jca.JCAManagedConnectionFactory.getRepository(JCAManagedConnectionFactory.java:195)
> at
> org.apache.jackrabbit.jca.JCAManagedConnection.openSession(JCAManagedConnection.java:100)
> ... 82 more
>
>
> Best regards,
> ---------------------------------------------------------------------------------------------------------------------
> Gustavo Henrique Orair
> ------------------------------------------------------------------------------------------------------------------
>
>
> 2011/12/21 Gustavo Henrique Orair <gustavo.orair_at_gmail.com
> <mailto:gustavo.orair_at_gmail.com>>
>
> 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
> <mailto: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#gjjyy
> and 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
> <mailto: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
> <mailto: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?
> >
> >
> >
>
>
>
>
>