[infinispan-dev] On ParserRegistry and classloaders

Sanne Grinovero sanne at infinispan.org
Sat Oct 11 12:54:57 EDT 2014


Hi all,
sorry it took me quite some time to return on this, but it's still
troublesome and quite critical to allow using Infinispan as a module.

I'm again trying to use Infinispan's JBoss Modules as a (library) for
deployed application, and it fails because of:

 Caused by: java.lang.ClassNotFoundException:
org.infinispan.remoting.transport.jgroups.JGroupsTransport from
[Module \"deployment.ModuleMemberRegistrationIT.war:main\" from
Service Module Loader]"}}

Debugging the application server, the stack is pointing to this method :

  public TransportConfigurationBuilder defaultTransport() {
      Transport transport = Util.getInstance(DEFAULT_TRANSPORT,
this.getGlobalConfig().getClassLoader());    <------- Failure here
      transport(transport);
      return this;
   }

The getClassLoader() function returns a reference to the application
deployment (as you can see in the error above).
This code makes sense I think, but then inspecting in the
"Util.getInstance" method we see that it's not strictly using the
classloaders we pass, but it's going to look in a specific sequence as
defined by this function:

 public static ClassLoader[] getClassLoaders(ClassLoader appClassLoader) {
      return new ClassLoader[] {
            appClassLoader,  // User defined classes
            OsgiClassLoader.getInstance(), // OSGi bundle context
needs to be on top of TCCL, system CL, etc.
            Util.class.getClassLoader(), // Infinispan classes (not
always on TCCL [modular env])
            ClassLoader.getSystemClassLoader(), // Used when load time
instrumentation is in effect
            Thread.currentThread().getContextClassLoader() //Used by
jboss-as stuff
            };
   }


Now to clarify one thing: the deployment does NOT have direct
visibility to the Infinispan modules. The application is depending on
Hibernate Search, and I can't allow Infinispan to leak visibility to
the application.
So going through the list, none of the classloaders actually have the
class from Infinispan Core because:

  appClassLoader -> doesn't have access to any Infinispan jar

  OsgiClassLoader.getInstance() -> OSGi only (right? I'm not too clear
on this one.. BTW the OsgiClassLoader.getInstance() is clearly not
threadsafe)

  Util.class.getClassLoader(), // Infinispan classes (not always on
TCCL [modular env]) <- (That's the comment in the code)

Well NO, this comment was probably correct when Util.class was
included into infinispan-core.. but now this function just returns the
modular classloader of Infinispan Commons ! It doesn't expose the
JGroupsTransport.

I hoped I could configure the ClassLoader, but I've already done that:

1  ClassLoader ispnClassLoadr = ParserRegistry.class.getClassLoader();
2  configurationParser = new ParserRegistry( ispnClassLoadr ); // Make
sure the Parser is using the module having access to Infinispan Core
3  ConfigurationBuilderHolder builderHolder =
configurationParser.parse( is ); // I have to pass a stream so that I
can load the resource from the user module
4  patchInfinispanClassLoader( builderHolder ); // AFTER I have the
builderHolder, I can use an utility method to correct the classloaders

But the above exception is triggered at line *3* so I have no
opportunity to amend any classloader.


In summary: the defaultTransport() is triggered during XML parsing and
it's going to ignore any programmatically set classloader.

A patch proposal would be to change the following line from the
GlobalConfigurationBuilder() constructor:

 ClassLoader defaultCL = Util.isOSGiContext() ?
GlobalConfigurationBuilder.class.getClassLoader() :
Thread.currentThread().getContextClassLoader();

to a simple:

 ClassLoader defaultCL = GlobalConfigurationBuilder.class.getClassLoader();

But the function generating the chain of classloaders should probably
also need to be fixed..
I suspect it would be much easier if we could agree to:
  A) accept classloaders on the methods which need it
  B) Stick to the given classloaders without applying unrequested and
surprising overrides

My workaround in Search is going to be to set the ContextClassloader;
that resolved my problem but it's piling up on other workarounds
related to Infinispan initialization and classloaders. I'm not opening
JIRA's here as I'm not clear on which ones are bugs, and how many of
these are intentional.. please take that judgement task.

Thanks,
Sanne




On 30 July 2014 20:21, Ion Savin <isavin at redhat.com> wrote:
> Hi Sanne,
>
> I don't see any changes in the ParserRegistry which would have removed the
> behavior you describe (at least looking at the OSGi changes). Can you point
> me please to some code which used to work in the past?
>
> I've found two classes which have some reference to Hibernate in comments
> and the factory was removed part of the OSGi changes. Are these perhaps the
> changes which you are missing?
>
> https://github.com/infinispan/infinispan/blob/6.0.x/core/src/main/java/org/infinispan/util/FileLookup.java
>
> https://github.com/infinispan/infinispan/blob/6.0.x/core/src/main/java/org/infinispan/util/FileLookupFactory.java
>
> --
> Ion Savin
>
>
> On 07/30/2014 09:17 PM, Mircea Markus wrote:
>>
>> Ion, Martin - what are your thoughts?
>>
>> On Jul 29, 2014, at 16:34, Sanne Grinovero <sanne at infinispan.org> wrote:
>>
>>> All,
>>> in Search we wrap the Parser in a decorator which workarounds the
>>> classloader limitation.
>>> I still think you should fix this, it doesn't matter how/why it was
>>> changed.
>>>
>>> Sanne
>>>
>>> On 26 May 2014 11:06, Ion Savin <isavin at redhat.com> wrote:
>>>>
>>>> Hi Sanne, Galder,
>>>>
>>>> On 05/23/2014 07:08 PM, Sanne Grinovero wrote:
>>>>>
>>>>> On 23 May 2014 08:03, Galder Zamarreño<galder at redhat.com>  wrote:
>>>>>>>
>>>>>>> Hey Sanne,
>>>>>>>
>>>>>>> I’ve looked at ParserRegistry and not sure I see the changes you are
>>>>>>> referring to…
>>>>>>>
>>>>>>>>  From what I’ve seen, ParserRegistry has taken class loader in the
>>>>>>>> constructor since the start.
>>>>>
>>>>> Yes, and that was good as we've been using it: it might need
>>>>> directions to be pointed at the right modules to load extension
>>>>> points.
>>>>>
>>>>> My problem is not that the constructor takes a ClassLoader, but that
>>>>> other options have been removed; essentially in my scenario the module
>>>>> containing the extension points does not contain the configuration
>>>>> file I want it to load, and the actual classLoader I want the
>>>>> CacheManager to use is yet a different one. As explained below,
>>>>> assembling a single "catch all" ClassLoader to delegate to all doesn't
>>>>> work as some of these actually need to be strictly isolated to prevent
>>>>> ambiguities.
>>>>>
>>>>>>> I suspect you might be referring to classloader related changes as a
>>>>>>> result of OSGI integration?
>>>>>
>>>>> I didn't check but that sounds like a reasonable estimate.
>>>>
>>>>
>>>> I had a look at the OSGi-related changes done for this class and they
>>>> don't alter the class interface in any way. The implementation changes
>>>> related to FileLookup seem to maintain the same behavior for non-OSGi
>>>> contexts also.
>>>>
>>>> Regards,
>>>>   Ion Savin
>>>> _______________________________________________
>>>> infinispan-dev mailing list
>>>> infinispan-dev at lists.jboss.org
>>>> https://lists.jboss.org/mailman/listinfo/infinispan-dev
>>>
>>>
>>> _______________________________________________
>>> infinispan-dev mailing list
>>> infinispan-dev at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/infinispan-dev
>>
>>
>> Cheers,
>>
>



More information about the infinispan-dev mailing list