Skip to main content

Service calls to OSGI WAB Hybrid applications have wrong context

10 replies [Last post]
chejavara
Offline
Joined: 2012-11-27
Points: 0

I have a question about how service calls are supposed to work with OSGI Web Application Bundles

Lets say I have WAB1 that tracks and calls an OSGI service, that WAB2 registered.

When the actual service is called from WAB1, I can see that there is a 'Context' associated that is only for WAB1.

(More precisely, this is a ComponentInvocation (WebComponentInvocation) that is stored as a inheritable thread local as 'frames' variable of InvocationManagerImpl.)

But when WAB1 calls a service that is implemented in WAB2, then we are still under the context of WAB1, it has not been switched. Even if a new thread is started in service implementation in WAB2, it will still 'inherit' the context of WAB1.

So that means we will not be able to see the JNDI context of WAB2, and we will not be able to get any persistence units defined in WAB2 even though we are executing inside WAB2. Basically anything that would need to be aware of the fact that WAB2 has its own context.

The Thread Context Class Loader will also be wrong since it is still belonging to WAB1.

I would appreciate if Sahoo or someone can shed some light on this matter?

Any way to be able to switch this context with some API? I only know about setting the current thread context classloader.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
ss141213
Offline
Joined: 2005-03-30
Points: 0

When WAB1 calls WAB2's service and the service is actually a Java EE
component like a local EJB, then the Java EE context will be switched to
EJB's context during the call of the EJB. If the service is a pure OSGi
service, then it has no JavaEE context associated with it, so it
inherits whatever is in the caller's thread. However since it is a pure
OSGi component, it does not care about JavaEE context. It has its own
BundleContext to interact with its universe.

Thread's context class loader switch happens for remote components only.

Sahoo
On Wednesday 28 November 2012 12:56 AM, forums@java.net wrote:
> I have a question about how service calls are supposed to work with
> OSGI Web
> Application Bundles Lets say I have WAB1 that tracks and calls an OSGI
> service, that WAB2 registered. When the actual service is called from
> WAB1, I
> can see that there is a 'Context' associated that is only for WAB1. (More
> precisely, this is a ComponentInvocation (WebComponentInvocation) that is
> stored as a inheritable thread local as 'frames' variable of
> InvocationManagerImpl.) But when WAB1 calls a service that is
> implemented in
> WAB2, then we are still under the context of WAB1, it has not been
> switched.
> Even if a new thread is started in service implementation in WAB2, it
> will
> still 'inherit' the context of WAB1. So that means we will not be able
> to see
> the JNDI context of WAB2, and we will not be able to get any persistence
> units defined in WAB2 even though we are executing inside WAB2. Basically
> anything that would need to be aware of the fact that WAB2 has its own
> context. The Thread Context Class Loader will also be wrong since it
> is still
> belonging to WAB1. I would appreciate if Sahoo or someone can shed
> some light
> on this matter?
>
> --
>
> [Message sent by forum member 'chejavara']
>
> View Post: http://forums.java.net/node/892749
>
>

chejavara
Offline
Joined: 2012-11-27
Points: 0

I have another question, the JPA Extender, does not as far as I know register the entityManagerFactory of a JPA Bundle as an OSGI service. Therefore, if any OSGi service call comes to the WAB that owns the persistence unit, it will not be able to persist to database in any way (not even by attempting to find the emf with the bundle context).

Is the role of the JPA extender supposed to be only to enhance entities?

ss141213
Offline
Joined: 2005-03-30
Points: 0

That's correct, the role of JPA extender is to facilitate enhancement at
this point. It is trivial to add an activator in the entity bundle to
register the emf as a service. Our samples take this approach.

Sahoo
On Tuesday 04 December 2012 12:52 AM, forums@java.net wrote:
> I have another question, the JPA Extender, does not as far as I know
> register
> the entityManagerFactory of a JPA Bundle as an OSGI service.
> Therefore, if
> any OSGi service call comes to the WAB that owns the persistence unit, it
> will not be able to persist to database in any way (not even by
> attempting to
> find the emf with the bundle context). Is the role of the JPA extender
> supposed to be only to enhance entities?
>
> --
>
> [Message sent by forum member 'chejavara']
>
> View Post: http://forums.java.net/node/892749
>
>

chejavara
Offline
Joined: 2012-11-27
Points: 0

You have a point about manually registering the entityManagerFactory in a separate bundle, but this is far from ideal. The entire point of Blueprint or Spring is to avoid having to use OSGI APIs directly and registering/unregistering services through Trackers.
What if I want to have the persistance unit in the same WAB, configured in the same applcationContext or blueprint.xml?

It also goes somewhat against the Enterprise OSGI JPA spec. The Aries JPA extender for example will look for the Meta-Persistance manifest header and automatically export the emf or EntityManager proxy as an OSGI service. Another point of the Enterprise OSGI JPA spec was to avoid you having to use Java SE bootstrapping like Persistence.createEntityManagerFactory which is exactly what we need to do.

The name of the Glassfish one as Extender may be confusing for these reasons.

ss141213
Offline
Joined: 2005-03-30
Points: 0

I didn't actually ask you to register EMF as a service in a separate bundle. One should use the activator of the bundle containing JPA entities to register the EMF as a service. Yes, it does introduce a harder dependency on OSGi than using various OSGi headers to achieve the same, but I didn't think it was a big issue. Extender is a very generic OSGi term, so one should not care for what each extender does. Due to lack of time, I have not implemented complete support for OSGi/JPA. If one strongly feels that OSGi/JPA solves their key programming/architectural issues, there is nothing stopping one from using Aries-JPA or eclipselink-osgi in GlassFish.

Thanks,
Sahoo

chejavara
Offline
Joined: 2012-11-27
Points: 0

Thanks again Sahoo,
While it would be ideal that Glassfish registered an EntityManagerFactory as an OSGI service as per the OSGI spec and avoid having another JPA extender like Aries(which currently does not work for hibernate) and having the two running simultaneously, I have more of an issue with the original point of this thread.

More precisely, its the presence of the JavaEE context in thread locals. If I'm using blueprint there won't be such a context during application initialization and we won't be able to use any JavaEE (like JNDI lookups) during init (or later on if not executing from servlet/webservice ect..). Thats why we would need everything available as an OSGI service including the EntityManagerFactory.

However I am still wondering is there any APIs that Glassfish would offer, even as a workaround to be able to set the right JavaEE context for a given Thread?

ss141213
Offline
Joined: 2005-03-30
Points: 0

Yes, I know it would be ideal for GlassFish to provide support for OSGi/JPA spec, but I haven't found time to implement it yet.

Coming to the question of JavaEE context, let me see if I understand your scenario correctly:
WAB2 has registered some pure OSGi service.
WAB2 is invoking these services.
The services are operating under WAB1's Java EE context.
If this is what you are seeing, then I confirm that's the correct behavior. Web applications were not designed by JavaEE to operate as a replacement for local method calls. They are expected to provide services which are called over a protocol. Since you are exposing some OSGi services out of WAB2 which is directly called by WAB1, web container does not get a chance to intercept to switch context. There is no API available to switch the context. Even if there were an API, I would advise against it. Instead, you should implement the services as EJBs. That way, even when WAB1 calls it via OSGi service reference, the method is still invoked with EJB's context.

Thanks,
Sahoo

chejavara
Offline
Joined: 2012-11-27
Points: 0

Thats not quite it (I think it was most likely a typo).
WAB2 has registered pure OSGI service
WAB1 is invoking that service
The services are operating under WAB1's JavaEE context.

That makes it clear, thanks. For me EJB are off the table since we are using Spring. However, I have found a solution which is to run a Thread created during Spring initialization which will have the right JavaEE context and then dispatch everything that needs that context (like EntityManagerFactory JNDI lookups) as a Runnable to run asynchronously.

However, further, I have found a way to wire up Spring so that the EntityManagerFactory and Transactions are all registered as OSGI services. In that case we wouldn't need the JavaEE context. Like you said though, I had to register the EntityManagerFactory manually since neither Glassfish nor Aries provides this currently.

Thanks

mgainty
Offline
Joined: 2004-05-21
Points: 0

consult the BND spec and make EntityManagerFactory visible thru Export-Package attributehttp://www.aqute.biz/Bnd/Format from what i see there is no way for a maven pom.xml which is building an OSGI distro to conditionally export both packages unless you're willing to setup a profile and have OSGI Enable different EntityManagerFactory packages
(depending on the characteristics of the matched profile)
Martin
______________________________________________
Verzicht und Vertraulichkeitanmerkung
Diese Nachricht ist vertraulich. Sollten Sie nicht der vorgesehene Empfaenger sein, so bitten wir hoeflich um eine Mitteilung. Jede unbefugte Weiterleitung oder Fertigung einer Kopie ist unzulaessig. Diese Nachricht dient lediglich dem Austausch von Informationen und entfaltet keine rechtliche Bindungswirkung. Aufgrund der leichten Manipulierbarkeit von E-Mails koennen wir keine Haftung fuer den Inhalt uebernehmen.
> To: users@glassfish.java.net
> Subject: Re: Service calls from/to OSGI WAB Hybrid applications have wron
> From: forums@java.net
> Date: Fri, 7 Dec 2012 08:55:52 -0600
>
> Thanks again Sahoo, While it would be ideal that Glassfish registered an
> EntityManagerFactory as an OSGI service as per the OSGI spec and avoid having
> another JPA extender like Aries(which currently does not work for hibernate)
> and having the two running simultaneously, I have more of an issue with the
> original point of this thread. More precisely, its the presence of the JavaEE
> context in thread locals. If I'm using blueprint there won't be such a
> context during application initialization and we won't be able to use any
> JavaEE during init (or later on if not executing from servlet/webservice
> ect..). Thats why we would need everything available as an OSGI service
> including the EntityManagerFactory. However I am still wondering is there any
> APIs that Glassfish would offer, even as a workaround to be able to set the
> right JavaEE context for a given Thread?
>
> --
>
> [Message sent by forum member 'chejavara']
>
> View Post: http://forums.java.net/node/892749
>
>

chejavara
Offline
Joined: 2012-11-27
Points: 0

Thanks for the info, Sahoo.

I can see now what you mean, but let me explain my setup. I'm not using any EJB technology, but instead the Spring framework to provide transactions, dependency injection, ect.

So here the assumption that some service class will not be interacting with JavaEE no longer holds true. The service implementation that implements the OSGI service can be a Spring bean, and it can be wired with other services or DAOs.

Spring knows about entityManagerFactories, ect by wiring them up from applicationContext.xml through JNDI lookups. Also Spring will create transactions if you specify so, so it will also be making lookups to the UserTransaction as apart of its AOP interceptor. And therefore we will definitely need a JavaEE context.

What would be the proper way to use Spring in a Web Application Bundle, is it not feasible at all?
Also curious, is there a way to manually switch JavaEE context?