You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomee.apache.org by Borislav Kapukaranov <b....@gmail.com> on 2012/02/27 11:39:18 UTC

injection of one EJB in another in OSGi

Hey folks,

I'm trying to get OpenEJB running on Equinox and it is going fairly well so
far. :-)
Until I got stucked in the following issue - I have a WebApp that has two
local EJBs (*X* and *Y*) and a Servlet. *X* has annotated field with type *Y
*. The Servlet has annotated fields for both EJBs.
My web container is GeminiWeb and with the help of my own ObjectFactory it
handles the Servlet binding and the injection of the EJB's in the Servlet
just fine.
However there is one more injection that is needed - *Y* proxy into *X*.
This is where I got trouble.

I'm using a bundle that triggers the deployment of the WebApp as an OpenEJB
module by plugging into Tomcat's mechanics. My bundle calls
*org.apache.openejb.assembler.DeployerEjb.deploy(String
location)* - this method does the heavy lifting for me by processing the
annotations and binds all EJB's in OpenEjb's internal JNDI so all is fine
here.
When a bean is injected somewhere, a proxy is created for this bean.
In this code snippet from *LocalBeanProxyGeneratorImpl* we can see how a
proxy is generated:

private Class createProxy(*Class<?> clsToProxy*, String proxyName, *ClassLoader
cl*) {
    String clsName = proxyName.replaceAll("\\.", "/");
    try {
        return *cl.loadClass(proxyName);*
    } catch (Exception e) {}
    try {
        byte[] proxyBytes = generateProxy(clsToProxy, clsName);
        return (Class<?>) defineClass.invoke(unsafe, proxyName, proxyBytes,
0, proxyBytes.length, *clsToProxy.getClassLoader()*,
clsToProxy.getProtectionDomain());
    } catch (Exception e) {
        throw new InternalError(e.toString());
    }
}

I've highlighted what is important for the OSGi case
*- clsToProxy* is the bean's class - this is loaded and defined by the
WebApp's bundle loader (*clsToProxy.getClassLoader()*).
*- cl* is an UrlClassLoader which is internally created by OpenEjb for its
own purposes and contains as resources the WebApp's WEB-INF/classes.

What happens here is that the first time this proxy is created OpenEjb
actually defines it with the WebApp's bundle loader - *
defineClass.invoke(..,clsToProxy.getClassLoader(),...)*. Later when this
bean is injected again we end up in the same place to create a proxy,
expecting to load it with OpenEjb's internal classloader - *
cl.loadClass(proxyName)* - and since it knows nothing about this proxy we
try to define it again with the WebApp's class loader which results in a
LinkageError.

Do you know how is this expected to work in OSGi? And would it be better if
OpenEjb both tried to load and define with the same loader? I admit this
should work outside OSGi, but in OSGi the two loaders are
potentially(almost certainly) different.

Any help is much appreciated! :-)

Best Regards
Borislav

Re: injection of one EJB in another in OSGi

Posted by Romain Manni-Bucau <rm...@gmail.com>.
doing so directly in the deployer can do the trick i think.

- Romain


2012/2/27 Borislav Kapukaranov <b....@gmail.com>

> I've noticed that some kind of chained class loader would fix the issue and
> I already have such mechanism in place - I set it as a thread context class
> loader (TCCL). The problem here is OpenEjb sets its internal UrlClassLoader
> as TCCL for some reason so multiloader also won't work in this case.
>
> Is there a way to stop OpenEjb from changing the TCCL? Also going back to
> my first post isn't it a safer bet to define the class with the internal
> loader, after all later it will always be loaded with it?
>
> Thanks for your quick replies!
>
> Best Regards
> Borislav
>
> On Mon, Feb 27, 2012 at 2:27 PM, Jean-Baptiste Onofré <jb@nanthrax.net
> >wrote:
>
> > Hi guys,
> >
> > A ThreadContextClassLoader could also fix the issue, but it requires some
> > change in the code.
> >
> > Regards
> > JB
> >
> >
> > On 02/27/2012 01:24 PM, Romain Manni-Bucau wrote:
> >
> >> Hi,
> >>
> >> in tomcat we use this classloader as paretn of the webapp classloader so
> >> everything is fine.
> >>
> >> In OSGi i think a kind of multipleclassloader can fix this issue: try to
> >> load the class in openejb application classloader before the bundle
> >> classloader itself.
> >>
> >> - Romain
> >>
> >>
> >> 2012/2/27 Borislav Kapukaranov<b.kapukaranov@**gmail.com<
> b.kapukaranov@gmail.com>
> >> >
> >>
> >>  Hey folks,
> >>>
> >>> I'm trying to get OpenEJB running on Equinox and it is going fairly
> well
> >>> so
> >>> far. :-)
> >>> Until I got stucked in the following issue - I have a WebApp that has
> two
> >>> local EJBs (*X* and *Y*) and a Servlet. *X* has annotated field with
> type
> >>> *Y
> >>> *. The Servlet has annotated fields for both EJBs.
> >>> My web container is GeminiWeb and with the help of my own ObjectFactory
> >>> it
> >>> handles the Servlet binding and the injection of the EJB's in the
> Servlet
> >>> just fine.
> >>> However there is one more injection that is needed - *Y* proxy into
> *X*.
> >>> This is where I got trouble.
> >>>
> >>> I'm using a bundle that triggers the deployment of the WebApp as an
> >>> OpenEJB
> >>> module by plugging into Tomcat's mechanics. My bundle calls
> >>> *org.apache.openejb.assembler.**DeployerEjb.deploy(String
> >>> location)* - this method does the heavy lifting for me by processing
> the
> >>> annotations and binds all EJB's in OpenEjb's internal JNDI so all is
> fine
> >>> here.
> >>> When a bean is injected somewhere, a proxy is created for this bean.
> >>> In this code snippet from *LocalBeanProxyGeneratorImpl* we can see how
> a
> >>> proxy is generated:
> >>>
> >>> private Class createProxy(*Class<?>  clsToProxy*, String proxyName,
> >>> *ClassLoader
> >>> cl*) {
> >>>    String clsName = proxyName.replaceAll("\\.", "/");
> >>>    try {
> >>>        return *cl.loadClass(proxyName);*
> >>>    } catch (Exception e) {}
> >>>    try {
> >>>        byte[] proxyBytes = generateProxy(clsToProxy, clsName);
> >>>        return (Class<?>) defineClass.invoke(unsafe, proxyName,
> >>> proxyBytes,
> >>> 0, proxyBytes.length, *clsToProxy.getClassLoader()*,
> >>> clsToProxy.**getProtectionDomain());
> >>>    } catch (Exception e) {
> >>>        throw new InternalError(e.toString());
> >>>    }
> >>> }
> >>>
> >>> I've highlighted what is important for the OSGi case
> >>> *- clsToProxy* is the bean's class - this is loaded and defined by the
> >>> WebApp's bundle loader (*clsToProxy.getClassLoader()***).
> >>> *- cl* is an UrlClassLoader which is internally created by OpenEjb for
> >>> its
> >>> own purposes and contains as resources the WebApp's WEB-INF/classes.
> >>>
> >>> What happens here is that the first time this proxy is created OpenEjb
> >>> actually defines it with the WebApp's bundle loader - *
> >>> defineClass.invoke(..,**clsToProxy.getClassLoader(),..**.)*. Later when
> >>> this
> >>> bean is injected again we end up in the same place to create a proxy,
> >>> expecting to load it with OpenEjb's internal classloader - *
> >>> cl.loadClass(proxyName)* - and since it knows nothing about this proxy
> we
> >>> try to define it again with the WebApp's class loader which results in
> a
> >>> LinkageError.
> >>>
> >>> Do you know how is this expected to work in OSGi? And would it be
> better
> >>> if
> >>> OpenEjb both tried to load and define with the same loader? I admit
> this
> >>> should work outside OSGi, but in OSGi the two loaders are
> >>> potentially(almost certainly) different.
> >>>
> >>> Any help is much appreciated! :-)
> >>>
> >>> Best Regards
> >>> Borislav
> >>>
> >>>
> >>
> > --
> > Jean-Baptiste Onofré
> > jbonofre@apache.org
> > http://blog.nanthrax.net
> > Talend - http://www.talend.com
> >
>

Re: injection of one EJB in another in OSGi

Posted by Borislav Kapukaranov <b....@gmail.com>.
I've noticed that some kind of chained class loader would fix the issue and
I already have such mechanism in place - I set it as a thread context class
loader (TCCL). The problem here is OpenEjb sets its internal UrlClassLoader
as TCCL for some reason so multiloader also won't work in this case.

Is there a way to stop OpenEjb from changing the TCCL? Also going back to
my first post isn't it a safer bet to define the class with the internal
loader, after all later it will always be loaded with it?

Thanks for your quick replies!

Best Regards
Borislav

On Mon, Feb 27, 2012 at 2:27 PM, Jean-Baptiste Onofré <jb...@nanthrax.net>wrote:

> Hi guys,
>
> A ThreadContextClassLoader could also fix the issue, but it requires some
> change in the code.
>
> Regards
> JB
>
>
> On 02/27/2012 01:24 PM, Romain Manni-Bucau wrote:
>
>> Hi,
>>
>> in tomcat we use this classloader as paretn of the webapp classloader so
>> everything is fine.
>>
>> In OSGi i think a kind of multipleclassloader can fix this issue: try to
>> load the class in openejb application classloader before the bundle
>> classloader itself.
>>
>> - Romain
>>
>>
>> 2012/2/27 Borislav Kapukaranov<b....@gmail.com>
>> >
>>
>>  Hey folks,
>>>
>>> I'm trying to get OpenEJB running on Equinox and it is going fairly well
>>> so
>>> far. :-)
>>> Until I got stucked in the following issue - I have a WebApp that has two
>>> local EJBs (*X* and *Y*) and a Servlet. *X* has annotated field with type
>>> *Y
>>> *. The Servlet has annotated fields for both EJBs.
>>> My web container is GeminiWeb and with the help of my own ObjectFactory
>>> it
>>> handles the Servlet binding and the injection of the EJB's in the Servlet
>>> just fine.
>>> However there is one more injection that is needed - *Y* proxy into *X*.
>>> This is where I got trouble.
>>>
>>> I'm using a bundle that triggers the deployment of the WebApp as an
>>> OpenEJB
>>> module by plugging into Tomcat's mechanics. My bundle calls
>>> *org.apache.openejb.assembler.**DeployerEjb.deploy(String
>>> location)* - this method does the heavy lifting for me by processing the
>>> annotations and binds all EJB's in OpenEjb's internal JNDI so all is fine
>>> here.
>>> When a bean is injected somewhere, a proxy is created for this bean.
>>> In this code snippet from *LocalBeanProxyGeneratorImpl* we can see how a
>>> proxy is generated:
>>>
>>> private Class createProxy(*Class<?>  clsToProxy*, String proxyName,
>>> *ClassLoader
>>> cl*) {
>>>    String clsName = proxyName.replaceAll("\\.", "/");
>>>    try {
>>>        return *cl.loadClass(proxyName);*
>>>    } catch (Exception e) {}
>>>    try {
>>>        byte[] proxyBytes = generateProxy(clsToProxy, clsName);
>>>        return (Class<?>) defineClass.invoke(unsafe, proxyName,
>>> proxyBytes,
>>> 0, proxyBytes.length, *clsToProxy.getClassLoader()*,
>>> clsToProxy.**getProtectionDomain());
>>>    } catch (Exception e) {
>>>        throw new InternalError(e.toString());
>>>    }
>>> }
>>>
>>> I've highlighted what is important for the OSGi case
>>> *- clsToProxy* is the bean's class - this is loaded and defined by the
>>> WebApp's bundle loader (*clsToProxy.getClassLoader()***).
>>> *- cl* is an UrlClassLoader which is internally created by OpenEjb for
>>> its
>>> own purposes and contains as resources the WebApp's WEB-INF/classes.
>>>
>>> What happens here is that the first time this proxy is created OpenEjb
>>> actually defines it with the WebApp's bundle loader - *
>>> defineClass.invoke(..,**clsToProxy.getClassLoader(),..**.)*. Later when
>>> this
>>> bean is injected again we end up in the same place to create a proxy,
>>> expecting to load it with OpenEjb's internal classloader - *
>>> cl.loadClass(proxyName)* - and since it knows nothing about this proxy we
>>> try to define it again with the WebApp's class loader which results in a
>>> LinkageError.
>>>
>>> Do you know how is this expected to work in OSGi? And would it be better
>>> if
>>> OpenEjb both tried to load and define with the same loader? I admit this
>>> should work outside OSGi, but in OSGi the two loaders are
>>> potentially(almost certainly) different.
>>>
>>> Any help is much appreciated! :-)
>>>
>>> Best Regards
>>> Borislav
>>>
>>>
>>
> --
> Jean-Baptiste Onofré
> jbonofre@apache.org
> http://blog.nanthrax.net
> Talend - http://www.talend.com
>

Re: injection of one EJB in another in OSGi

Posted by Jean-Baptiste Onofré <jb...@nanthrax.net>.
Hi guys,

A ThreadContextClassLoader could also fix the issue, but it requires 
some change in the code.

Regards
JB

On 02/27/2012 01:24 PM, Romain Manni-Bucau wrote:
> Hi,
>
> in tomcat we use this classloader as paretn of the webapp classloader so
> everything is fine.
>
> In OSGi i think a kind of multipleclassloader can fix this issue: try to
> load the class in openejb application classloader before the bundle
> classloader itself.
>
> - Romain
>
>
> 2012/2/27 Borislav Kapukaranov<b....@gmail.com>
>
>> Hey folks,
>>
>> I'm trying to get OpenEJB running on Equinox and it is going fairly well so
>> far. :-)
>> Until I got stucked in the following issue - I have a WebApp that has two
>> local EJBs (*X* and *Y*) and a Servlet. *X* has annotated field with type
>> *Y
>> *. The Servlet has annotated fields for both EJBs.
>> My web container is GeminiWeb and with the help of my own ObjectFactory it
>> handles the Servlet binding and the injection of the EJB's in the Servlet
>> just fine.
>> However there is one more injection that is needed - *Y* proxy into *X*.
>> This is where I got trouble.
>>
>> I'm using a bundle that triggers the deployment of the WebApp as an OpenEJB
>> module by plugging into Tomcat's mechanics. My bundle calls
>> *org.apache.openejb.assembler.DeployerEjb.deploy(String
>> location)* - this method does the heavy lifting for me by processing the
>> annotations and binds all EJB's in OpenEjb's internal JNDI so all is fine
>> here.
>> When a bean is injected somewhere, a proxy is created for this bean.
>> In this code snippet from *LocalBeanProxyGeneratorImpl* we can see how a
>> proxy is generated:
>>
>> private Class createProxy(*Class<?>  clsToProxy*, String proxyName,
>> *ClassLoader
>> cl*) {
>>     String clsName = proxyName.replaceAll("\\.", "/");
>>     try {
>>         return *cl.loadClass(proxyName);*
>>     } catch (Exception e) {}
>>     try {
>>         byte[] proxyBytes = generateProxy(clsToProxy, clsName);
>>         return (Class<?>) defineClass.invoke(unsafe, proxyName, proxyBytes,
>> 0, proxyBytes.length, *clsToProxy.getClassLoader()*,
>> clsToProxy.getProtectionDomain());
>>     } catch (Exception e) {
>>         throw new InternalError(e.toString());
>>     }
>> }
>>
>> I've highlighted what is important for the OSGi case
>> *- clsToProxy* is the bean's class - this is loaded and defined by the
>> WebApp's bundle loader (*clsToProxy.getClassLoader()*).
>> *- cl* is an UrlClassLoader which is internally created by OpenEjb for its
>> own purposes and contains as resources the WebApp's WEB-INF/classes.
>>
>> What happens here is that the first time this proxy is created OpenEjb
>> actually defines it with the WebApp's bundle loader - *
>> defineClass.invoke(..,clsToProxy.getClassLoader(),...)*. Later when this
>> bean is injected again we end up in the same place to create a proxy,
>> expecting to load it with OpenEjb's internal classloader - *
>> cl.loadClass(proxyName)* - and since it knows nothing about this proxy we
>> try to define it again with the WebApp's class loader which results in a
>> LinkageError.
>>
>> Do you know how is this expected to work in OSGi? And would it be better if
>> OpenEjb both tried to load and define with the same loader? I admit this
>> should work outside OSGi, but in OSGi the two loaders are
>> potentially(almost certainly) different.
>>
>> Any help is much appreciated! :-)
>>
>> Best Regards
>> Borislav
>>
>

-- 
Jean-Baptiste Onofré
jbonofre@apache.org
http://blog.nanthrax.net
Talend - http://www.talend.com

Re: injection of one EJB in another in OSGi

Posted by Romain Manni-Bucau <rm...@gmail.com>.
Hi,

in tomcat we use this classloader as paretn of the webapp classloader so
everything is fine.

In OSGi i think a kind of multipleclassloader can fix this issue: try to
load the class in openejb application classloader before the bundle
classloader itself.

- Romain


2012/2/27 Borislav Kapukaranov <b....@gmail.com>

> Hey folks,
>
> I'm trying to get OpenEJB running on Equinox and it is going fairly well so
> far. :-)
> Until I got stucked in the following issue - I have a WebApp that has two
> local EJBs (*X* and *Y*) and a Servlet. *X* has annotated field with type
> *Y
> *. The Servlet has annotated fields for both EJBs.
> My web container is GeminiWeb and with the help of my own ObjectFactory it
> handles the Servlet binding and the injection of the EJB's in the Servlet
> just fine.
> However there is one more injection that is needed - *Y* proxy into *X*.
> This is where I got trouble.
>
> I'm using a bundle that triggers the deployment of the WebApp as an OpenEJB
> module by plugging into Tomcat's mechanics. My bundle calls
> *org.apache.openejb.assembler.DeployerEjb.deploy(String
> location)* - this method does the heavy lifting for me by processing the
> annotations and binds all EJB's in OpenEjb's internal JNDI so all is fine
> here.
> When a bean is injected somewhere, a proxy is created for this bean.
> In this code snippet from *LocalBeanProxyGeneratorImpl* we can see how a
> proxy is generated:
>
> private Class createProxy(*Class<?> clsToProxy*, String proxyName,
> *ClassLoader
> cl*) {
>    String clsName = proxyName.replaceAll("\\.", "/");
>    try {
>        return *cl.loadClass(proxyName);*
>    } catch (Exception e) {}
>    try {
>        byte[] proxyBytes = generateProxy(clsToProxy, clsName);
>        return (Class<?>) defineClass.invoke(unsafe, proxyName, proxyBytes,
> 0, proxyBytes.length, *clsToProxy.getClassLoader()*,
> clsToProxy.getProtectionDomain());
>    } catch (Exception e) {
>        throw new InternalError(e.toString());
>    }
> }
>
> I've highlighted what is important for the OSGi case
> *- clsToProxy* is the bean's class - this is loaded and defined by the
> WebApp's bundle loader (*clsToProxy.getClassLoader()*).
> *- cl* is an UrlClassLoader which is internally created by OpenEjb for its
> own purposes and contains as resources the WebApp's WEB-INF/classes.
>
> What happens here is that the first time this proxy is created OpenEjb
> actually defines it with the WebApp's bundle loader - *
> defineClass.invoke(..,clsToProxy.getClassLoader(),...)*. Later when this
> bean is injected again we end up in the same place to create a proxy,
> expecting to load it with OpenEjb's internal classloader - *
> cl.loadClass(proxyName)* - and since it knows nothing about this proxy we
> try to define it again with the WebApp's class loader which results in a
> LinkageError.
>
> Do you know how is this expected to work in OSGi? And would it be better if
> OpenEjb both tried to load and define with the same loader? I admit this
> should work outside OSGi, but in OSGi the two loaders are
> potentially(almost certainly) different.
>
> Any help is much appreciated! :-)
>
> Best Regards
> Borislav
>