users@glassfish.java.net

Re: OSGi Java EE hybrid example split into modules best practices

From: Ancoron Luciferis <ancoron.luciferis_at_googlemail.com>
Date: Wed, 29 Feb 2012 23:47:35 +0100

Hi Kirk,

I think we have a bit of a different understanding in the terms we use
here. When talking about "containers", we usually mean "JavaEE
container" or "EJB container", whereas you seem to mean "OSGi
container", which in our wording is the "OSGi framework" or "OSGi
runtime". Could we agree on this? It should make further arguments a bit
simpler to understand.

However, about your concerns:

When I get it right then what you want is the JPA plug'n'play magic to
happen in pure OSGi, rather than the JavaEE container. The main problem
here is, that the OSGi enterprise specs just hit their first official
release with the 4.2 specs. With every specification or "standard" you
will concentrate on a most reasonable subset of functionality and wait
for the feedback before going any further. In some areas even initial
specifications tend to get too complex (like e.g. the D-OSGi stuff and
the RemoteServiceAdmin infrastructure).

Also, "OSGi enterprise" does not strictly depend on "JavaEE" for being
implemented. This puts in some additional constraints to be aware of.
E.g. in a JavaEE environment you usually use JTA managed transactions
and also benefit from managed JPA EntityManagers which fit together
quite nicely because the EntityManagers have a more-or-less pre-defined
lifecycle here, from creation to destroy. In a non-JavaEE environment
you usually do transaction demarcation and all that stuff yourself or
using some other framework, e.g. Spring. For the pure OSGi layer, Apache
Aries has been built exactly for that purpose by reusing Spring
look-a-like configuration files. Hence, you also have to control the
lifecycle of the EntityManager yourself, as the framework does not know
before-hand what you're going to do.

I use Aries as well directly inside GlassFish and configured it to use
the GlassFish JTA manager to get distributed transactions between my own
services (which most commonly use JPA) and the ones from third-party
services that may use any other technology (e.g. one uses MyBatis
configured with a GlassFish managed DataSource).

So basically you don't have to choose once and for all between one
approach or the other. But you should first know where your things might
be running, or which kind of runtime environments you want to support.
The result of this defines the constraints and may render some
approaches as being inappropriate or simply impossible.

So, if you want to be runtime-agnostic you really should stick to the
standard that there is and Apache Aries is one of your best options. If
you can assume GlassFish, then you're free to use at least
JavaEE-specific stuff. Also you have to make some tests which approach
is more reliable or faster than the other. Also (hot-)deployment is a
clear test case for anything within the OSGi space.

See further comments inline...

On 02/29/2012 05:05 PM, Kirk Rasmussen wrote:
>
> See comments below
>
>> On Tuesday 28 February 2012 09:35 PM, Kirk Rasmussen wrote:
>>> Sahoo suggested using an interceptor as follows:
>>>
>>> @AroundInvoke
>>> Object setEM(InvocationContext ctx) throws Exception {
>>> log("entering setEM()");
>>> utx.begin();
>>> em = emf.createEntityManager();
>>> em.joinTransaction();
>>> try {
>>> Object result = ctx.proceed();
>>> utx.commit();
>>> return result;
>>> } catch (Exception e) {
>>> utx.rollback();
>>> throw e;
>>> }
>>> finally {
>>> em.close();
>>> log("exiting setEM()");
>>> }
>>>
>>> This a nice work around but its container specific code that I
>>> wouldn't need in Aries for example making my code non-portable which
>>> makes me sad. IMHO for Enterprise OSGi to take off mainstream issues
>>> like this need to be resolved. OSGi applications need to support
>>> managed JPA, declarative transactions and security as transparently
>>> and as portably as EJB3.
>>>
>> I don't understand what is container specific here? Interceptor is a
> supported technology in EE platform - nothing specific to GlassFish.
>> That code will work exactly same way in JBoss, WebLogic and WebSphere.
>> Aries required you to write some XML instead of this code - that's the
> way I like to see things.
>
> I meant that the code above would be unnecessary on Aries (i.e.
> container specific albeit portable). From my understanding on Aries the
> EntityManager is managed for me already without the need for the
> interceptor, on Glassfish it is not.

Yes, but you still have to write and maintain that XML which is almost
completely detached from any build time validation or static code
analysis. As many others, I prefer code over configuration, which I can
debug much better, which has a much clearer visibility to other
developers, keeps stacktraces shorter and hence, provides better
maintainability. Also if I face a problem or a strange runtime behavior
- e.g. some race condition - I already have a place to workaround it.
But that's only my point of view.

>
> Our goal as software developers is to REDUCE the amount of code we write
> and maintain. I'm not saying I prefer XML over CDI because I don't but I
> also don't like the idea of needing to write extra code to make it work
> like Aries does already. It's error prone.

Agree, so why don't you just use Apache Aries then?

>
> For example the other "fighterfish" samples don't include the call to
> "em.joinTransaction()" as the interceptor above which from my
> understanding is required ("Enterprise JavaBeans 3.1: 6th Edition", pg
> 138). IMHO It's too easy to make a mistake (no call to
> em.joinTransaction() below).
>
> glassfish-samples/sample/uas/ejbservice2/src/main/java/org/glassfish/fig
> hterfish/sample/uas/ejbservice2/UserAuthServiceEJB2.java:
>
> @Override
> public boolean register(String name, String password) {
> log("Registering (" + name + ", " + password + ")");
> EntityManager em = emf.createEntityManager();
> try {
> UserCredential uc = em.find(UserCredential.class, name);
> if (uc != null) return false;
> uc = new UserCredential();
> uc.setName(name);
> uc.setPassword(password);
> em.persist(uc);
> return true;
> } finally {
> em.close();
> }
> }
>
> If I had to pick between using XML with managed EntityManager vs
> relaying on all the other developers in my organization to write the
> proper interceptor/API calls I would probably stick with the XML
> approach. That's what I meant by fragmenting in the OSGi Enterprise
> world. There should be a standard across all containers for obtaining
> *managed* EntityManagers.

There just can't be a standard across all containers for this because
JavaEE container environments differ a lot from non-JavaEE ones. The
JPA/TX stuff from the Aries project tries to abstract from that fact and
does quite a decent job here but in the end it does not matter if you
write code or XML - you always have to configure the "managed" part somehow.

Furthermore you seriously don't have all your other developers to write
the interceptor stuff. You just write it once and then re-use it. E.g.
you could provide multiple interceptor implementations handling
different needs. I could think of one interceptor that enforces nested
transactions and one that just sets the transactional boundaries in case
there is no transaction and in the other case just reuses the existing one.

Package that interceptor inside a common bundle that is shared across
your implementations and you're all set up. In the Aries case you would
have to configure each and every service with the additional XML stuff.

E.g. for EJB implementations of services I usually use the classic
JavaEE @javax.interceptor.Interceptors annotation. That annotation is
packaged inside a shared bundle and hence, ready for use by everyone. No
code writing is required for a new service implementation on that part.
This is the principle of "write ones - use everywhere", so I have a
single class to maintain, nothing else.

With CDI this would basically be the same, whereas you would provide
your own interceptor annotation in addition for this. An example
(although without the OSGi part) is here:

https://blogs.oracle.com/arungupta/entry/totd_151_transactional_interceptors_using

On the other side, to support your other developers using the OSGi
blueprints approach you then have to check their projects in case of
problems instead of limiting your scope of visibility and responsibility
to the least possible.

So, in the end this proves your point of writing less code when using
Aries completely wrong because XML is some sort of code as well.

Sorry. ;)

>
> This situation is analogous to choosing "@Inject @OSGiSErvice" over
> using OSGi APIs directly because it is hard to manage services
> correctly. @OSGiService is superior because I write less code and it is
> reliable every time.

>
> In the ideal world, for OSGi, I should have a choice between injecting
> EntityMangerFactory or EntityManager just like I do in a pure JavaEE
> world.
>

Well, then you should probably raise your voice as well on the OSGi
developers list to get some more feedback on this topic.

I really encourage you to do that because I would like to see an
official solution to this as well. But I still think there is no really
generic way to do it as will always have something that needs to be
configured and hence, maintained on your side.

Cheers,

        Ancoron