users@glassfish.java.net

Re: Glassfish classloaders

From: Sahoo <Sahoo_at_Sun.COM>
Date: Fri, 22 Feb 2008 23:07:35 +0530

Sahoo wrote:
>
>
> glassfish_at_javadesktop.org wrote:
>>> delegate = false must always be used with extreme caution, as it can
>>> lead to nasty ClassCastException.
>>>
>>
>> What would be a scenario where a class cast exception would occur?
>>
>>
>>
> Let's say your war bundles EJB local interface Foo.class. Foo.class is
> also bundled as part of ejb.jar. Since delegation is off, when a
> servlet refers to Foo.class, it resolves to the one loaded by war's
> class loader. Now, the actual EJB instance would refer to Foo.class
> that's loaded by EJB class loader. When servlet tries to inject Foo
> type bean, a CCE would occur.
>>> When you specify delegate = false, that means the WebAppClassloader
>>> prefers classes defined in the war to classes defined outside the
>>> war. But, if a class is not defined in the war, then it eventually
>>> delegates up the hierarchy.
>>>
>>
>> Right, that is what we are also gathering from the app deployment
>> guide documentation.
>>
>>
>>
>>> So, I don't quite agree that with what is documented there.
>>>
>>
>> Do you mean to say that you do not agree with the statement in the
>> app deployment guide stating that you "must" have delegate set to try
>> for a web app to access an ejb?
>>
>>
>>
> You are right. I was *not* in agreement with the document, but looks
> like I am wrong. I just wrote a small program where my ear has a war
> and ejb-jar. When I set delegation = false, it does not work. So I am
> missing something.
My understanding was basically correct, my test case was wrong. I used
NetBeans to create the app, and by default it puts EJB interfaces as
part of the war to make it a portable archive. That was a direct
violation of use of delegation = false. When I removed the EJB interface
classes from the war, my app works with delegation = false.
>>> If you know you are not duplicating local EJB interface classes in
>>> your ejb-jar and war, then you should still be able to use delegate
>>> = false. The key here is that you must *not* have classes that are
>>> used in the local EJB interfaces packaged as part of the war. May be
>>> someone can correct me here.
>>>
>>
>> I think that makes sense. Do you mean to say that it should be safe
>> to use delegate=false in the webapp as long as the local interfaces
>> are not included in the webapp?
>>
> Wait for further comments from EJB container folks. They should be
> able to clarify why it does not work.
Yes, delegate = false should work as long as you don't package EJB
interface classes in the war.
>> I think our confusion stems from the documentation. The app
>> deployment guide uses the term "must" in the first paragraph of the
>> delegate attribute description, but then uses the term "safe" in the
>> second paragraph, suggesting that it IS possible to use
>> delegate=false in the web app and still use ejbs from a separate ejb
>> component, but doing so opens up some possible problems.
>>
>> In my own testing, I've found that setting delegate=false still
>> allows webapps to use the ejbs in just the same way as when
>> delegate=true is set, or the class loader element is omitted
>> altogether. At the same time, a singleton class is actually shared
>> by two web app modules if the class loader element is ommited or set
>> to delegate=true... whereas each webapp has it's own instance of the
>> singleton when delegate=false is set.
>>
> Did you use GlassFish to test this? As I mentioned earlier, I ran a
> small test case and it fails with following error in server.log:
> Caused by: com.sun.enterprise.InjectionException: Exception attempting
> to inject Resolved Ejb-Ref bar.NewServlet/newSessionBean_at_jndi: - > NewS
> essionBean into class bar.NewServlet
> at
> com.sun.enterprise.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:387)
>
> at
> com.sun.enterprise.util.InjectionManagerImpl.inject(InjectionManagerImpl.java:206)
>
> at
> com.sun.enterprise.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:117)
>
> at
> com.sun.web.server.J2EEInstanceListener.handleBeforeEvent(J2EEInstanceListener.java:259)
>
> ... 29 more
> Caused by: java.lang.IllegalArgumentException
> at
> sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63)
>
> at java.lang.reflect.Field.set(Field.java:656)
> at
> com.sun.enterprise.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:338)
>
> ... 32 more
>
Ignore the above crap - it was a fault in my test case.
>> In the case of whartung's use of frameworks that utilize singletons
>> in multiple webapps packaged in the same ear, non-delegated
>> classloading is the only way to have it work properly. But
>> sacrificing the use of EJBs is a poor penalty to pay :(
>>
>
> Please wait for some EJB container folks to comment on the behavior.
We should still wait for the EJB container folks to confirm if the
document is too restrictive than it needs to be.

Thanks,
Sahoo