On Thu, May 5, 2011 at 10:05 PM, Emmanuel Bernard
<emmanuel(a)hibernate.org> wrote:
Quick question.
In case of 2.a (ie setting the TCCL), this is a requirement for frameworks and libraries
using Infinispan, right? Not / never for a user application using Infinispan (in this case
it seems that the application class loader will do the right thing and is set as the TCCL
by the AS environment)?
My understanding is that we only need to worry about the TCCL if a
library is creating threads and is sharing those threads between
applications - when you create a new thread it inherits the TCCL from
it's parent thread. I'm not sure if we should expect the library to
set the TCCL around user callbacks in this case though, because the
TCCL is only necessary + guaranteed to work in a JEE environment: in a
standalone application you have basically one classloader, in an OSGi
application the TCCL is not guaranteed to be set properly anyway.
It's also possible that an application will want to store in the cache
an object whose class is not accessible through the application's
classloader.
E.g. if another module has an interface A and a factory for A objects
in an exported package that's accessible from the application's
classloader but the actual implementation class is not exported and so
it's not accessible.
For option 2.b we already have the InvocationContext, we only need to
add the classloader to it. Even if we would go the 2.a route, for
async calls I think we can unmarshal the object on a different thread
(which I also think could be shared between apps), so we may need to
save the TCCL at the time of the get() call in the InvocationContext
and use that for unmarshalling.
So I'd choose 2.b with TCCL as the default classloader. The only
catch, as Galder said, is we have to be very careful not to forget
invocation contexts lying around or we will leak classloaders.
Dan
On 5 mai 2011, at 10:55, Pete Muir wrote:
> I talked about this with Emmanuel last night, and we were
>
> a) concerned about the pollution of the API that this implies
> b) not sure why we need to do this
>
> So I also spoke to Jason to understand his initial motivation, and from this chat I
think it's clear that things have gone off course here.
>
> Jason raised two issues with modularity/classloading in Infinispan:
>
> 1) Using the TCCL as the classloader to load Infinispan classes is a bad idea.
Instead we should use org.infinispan.foo.Bar.getClass().getClassLoader().
>
> 2) When we need to load application classes we need a different approach to that used
today. Most of the time the TCCL is perfect for this. However *sometimes* Infinispan may
be invoked outside of the application, when the TCCL may not be set in AS7. Jason and I
discussed three options:
>
> a) require (through a platform integration documentation contract) that the TCCL must
always be set when Infinispan is invoked.
> b) Have some sort of InvocationContext which knows what the correct classloader to
use is (aka Hibernate/Seam/Weld design where there is a per-application construct based on
a ThreadLocal). Given this hasn't been designed into the core, it seems like a large
retrofit
> c) Make users specify the CL (directly or indirectly) via the API (as we discussed).
>
> Personally I think that (a) is the best approach right now, and is not that onerous a
requirement.
>
> We might want to make the TCCL usage pluggable for OSGI envs. Cc'd David to get
his feedback.
>
> On 4 May 2011, at 10:46, Dan Berindei wrote:
>
>> On Wed, May 4, 2011 at 5:09 PM, Pete Muir <pmuir(a)redhat.com> wrote:
>>>
>>> On 4 May 2011, at 05:34, Dan Berindei wrote:
>>>
>>>> On Wed, May 4, 2011 at 10:14 AM, Galder Zamarreño
<galder(a)redhat.com> wrote:
>>>>>
>>>>> On May 3, 2011, at 2:33 PM, Sanne Grinovero wrote:
>>>>>
>>>>>> 2011/5/3 "이희승 (Trustin Lee)"
<trustin(a)gmail.com>:
>>>>>>> On 05/03/2011 05:08 AM, Sanne Grinovero wrote:
>>>>>>>> 2011/5/2 Manik Surtani <manik(a)jboss.org>:
>>>>>>>>>
>>>>>>>>> On 1 May 2011, at 13:38, Pete Muir wrote:
>>>>>>>>>
>>>>>>>>>>>> As in, user API? That's a little
intrusive... e.g., put(K, V, cl) ?
>>>>>>>>>>>
>>>>>>>>>>> Not for put, since you have the class, just
get, and I was thinking
>>>>>>>>>>> something more like:
>>>>>>>>>>>
>>>>>>>>>>> Foo foo = getUsing(key, Foo.class)
>>>>>>>>>>
>>>>>>>>>> This would be a pretty useful addition to the API
anyway to avoid user casts.
>>>>>>>>>
>>>>>>>>> Maybe as an "advanced" API, so as not to
pollute the basic API? A bit like:
>>>>>>>>>
>>>>>>>>> Foo f =
cache.getAdvancedCache().asClass(Foo.class).get(key);
>>>>>>>>
>>>>>>>> doesn't look much better than a cast, but is more
cryptical :)
>>>>>>>>
>>>>>>>> getting back to the classloader issue, what about:
>>>>>>>>
>>>>>>>> Cache c = cacheManager.getCache( cacheName, classLoader
);
>>>>>>>>
>>>>>>>> or
>>>>>>>> Cache c = cacheManager.getCache( cacheName
).usingClassLoader(classLoader );
>>>>>>>>
>>>>>>>> BTW if that's an issue on the API, maybe you should
propose it to
>>>>>>>> JSR-107 as well ?
>>>>>>>
>>>>>>> We have a configurable Marshaller, right? Then why don't
we just use
>>>>>>> the class loader that the current Marshaller uses?
>>>>>>
>>>>>> +1
>>>>>> I like the clean approach, not sure how you configure the
"current
>>>>>> Marshaller" to use the correct CL ?
>>>>>> Likely hard to do via configuration file :)
>>>>>
>>>>> Well, the marshaller is a global component and so it's a cache
manager level. You can't make any assumptions about it's classloader, particularly
when lazy deserialization is configured and you want to make sure that the data of the
cache is deserialized with the correct classloader when the user reads the data from the
cache. This is gonna become even more important when we for example move to having a
single cache for all 2LC entities or all EJB3 SFSBs where we'll definitely need
multiple classloaders to access a single cache.
>>>>>
>>>>
>>>> The current unmarshaller uses the TCCL, which is a great idea for
>>>> non-modular environments and will still work in AS7 for application
>>>> classes (so it's still a good default). It probably won't work
if
>>>> Hibernate wants to store its own classes in the cache, because
>>>> Hibernate's internal classes may not be reachable from the
>>>> application's classloader.
>>>>
>>>> It gets even trickier if Hibernate wants to store a
>>>> PrivateHibernateCollection class in the cache containing instances of
>>>> application classes inside. Then I don't think there will be any
>>>> single classloader that could reach both the Hibernate classes and the
>>>> application classes so it can properly unmarshal both. Perhaps
that's
>>>> just something for the Hibernate folks to worry about? Or maybe we
>>>> should allow the users to register more than one classloader with a
>>>> cache?
>>>
>>> You need to use a bridge classloader in this case.
>>
>> You're right of course, Hibernate must have received/guessed the
>> application's classloader and so it is able to create a bridge
>> classloader that "includes" both.
>>
>> And if the application classes include references to classes from
>> another module(s), the application has to provide a bridge classloader
>> to Hibernate anyway.
>>
>> _______________________________________________
>> infinispan-dev mailing list
>> infinispan-dev(a)lists.jboss.org
>>
https://lists.jboss.org/mailman/listinfo/infinispan-dev
>
>
> _______________________________________________
> infinispan-dev mailing list
> infinispan-dev(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/infinispan-dev
_______________________________________________
infinispan-dev mailing list
infinispan-dev(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/infinispan-dev