users@glassfish.java.net

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

From: Kirk Rasmussen <kirk.rasmussen_at_texturacorp.com>
Date: Mon, 27 Feb 2012 09:45:58 -0600

Wow thanks Ancoron for the insight into different solutions. As a newbie
to OSGi I find the JPA stuff the most confusing of all since it involves
lazy loading/class weaving/transactions/etc. and wasn't sure how it
would affect runtime behavior by splitting the bundles.

I haven't really used EJB since the EJB 2 days as I've been using Spring
pretty much exclusively but I find the Java EE 6 hybrid approach very
compelling in the OSGi context. I've been reading Enterprise OSGi in
Action book but they use Blueprint and Apache Aries for the JPA
container.

It seems like the JPA solutions are fragmenting which has me a bit
worried from a standardization perspective.

-----Original Message-----
From: Ancoron Luciferis [mailto:ancoron.luciferis_at_googlemail.com]
Sent: Saturday, February 25, 2012 10:57 AM
To: users_at_glassfish.java.net
Cc: Kirk Rasmussen
Subject: Re: OSGi Java EE hybrid example split into modules best
practices

Hi Kirk,

sorry for hijacking this thread a bit but I wanted to return to your
initial question of separating entities from business services.

I have done exactly that and use it in production already. I already did
it in different ways:

1.) Separate entity classes (by their respective concerns) into several
bundles

2.) Have one or more bundles for "common" entity stuff (e.g. interfaces,
abstract classes = MappedSuperclass, ...)

Now comes the difference in my approaches:


1st approach: only one EntityManager

3.a) Business Service implemented as a EJB:

4.a) Use a single EntityManager for all entities used by this business
service, regardless of their bundle origin (only works if all can use
the same datasource/persistence-unit), using the standard
@PersistenceContext annotation

5.a) a single persistence.xml inside the business service bundle


2nd approach: one EntityManager per unit

3.b) Business Service implemented as a EJB:

4.b) Use multiple EntityManagers for each entity bundle used by this
business service, respecting their bundle origin using the standard
@PersistenceContext annotation and providing the "unitName" attribute

5.b) a single persistence.xml inside the business service bundle


3rd approach: separate JPA EJBs

3.c) Business Service implementation whatever you like

4.c) Separate persistence EJB inside entity bundles (actually making
them hybrid bundles too), each having its own persistence.xml and their
limited scope of entities to deal with.


However, for each of the approaches you have to keep some things in
mind:

The first approach is the most easy/lightweight one, but involves having
no clear separation of concerns and people tend to cross the borders
between those entity bundles, if they can (direct Java relationship
between entities of different origin, clear build order problems, cyclic
dependencies, QA trouble, ...).

The second approach will involve XA transactions when you implement
business functionality that uses multiple entity managers in one
transaction.

The third approach will provide the best separation of concerns as you
also control with the separate EJB what an outside user can actually do
with your entities.

As a test I also took this one step further and introduced good-old DTOs
implementing the same interfaces for the outside users (so they don't
even see that I'm using JPA or whatever I use internally to manage
persistence). This way I make sure that modification of an object
instance I give to the outer user does not implicitly trigger the entity
manager and also that I don't have unexpected updates/inserts once the
outer transaction (if there is any) commits.

Also this provides the user of my persistence with a guaranteed
reliability, as only I can control the lifecycle of entities, caching,
lazy-loading, ... , including ensuring the load-modify-save principle
(I've lately seen quite some applications not caring about the "load"
part, just creating new entities, set some values and expect the JPA
implementation to do the right thing - in all cases).


This may be a bit overly complex but it solves a lot of problems when
you don't know how others will use your stuff (or how many layers will
be there on top of yours, or which transactional characteristics they
may apply - or not).


I hope this didn't produce confusion.

Cheers,

        Ancoron


On 02/21/2012 07:18 PM, Kirk Rasmussen wrote:
> Hello,
>
> I am very interested in the hybrid Java EE approach to OSGi that
> Glassfish supports to leverage declarative security and transaction
> propagation available in Java EE. I was able to get the EclipseCon
> demo app working fine.
>
> I was wondering if it is possible to split up the EJB and JPA
portions.
> In other words I would like to have a persistence bundle that contains

> the entities with all the goodies (sharable, lazy loaded, 2^nd level
> cache) and a separate EJB service bundle.
>
> A more realistic service API would leverage Entities and not just Java

> primitives like Strings. For example, let's say the 'UserAuthService'
> added a new method:
>
> public interface UserAuthService {
>
> ...
>
> // EJB impl would have @RolesAllowed("admin") applied
>
> public User lookup(String name)
>
> }
>
> So now the common bundle would have a dependency on the Entity User.
> Seems logical to move this to another package / bundle, e.g.
> eclipsecon2011.osgieehol.persistence. From my understanding
> http://glassfish.java.net/public/GF-OSGi-Features.pdf the JPA bundle
> must include both the entities and the META-INF/persistence.xml file
> which I did.
>
> Now the EJB bundle only contains 'UserAuthServiceEJB' which I modified

> to lookup the EntityManager as an OSGi service (@PersistenceContext
> didn't work):
>
> @Stateless
>
> public class UserAuthServiceEJB implements UserAuthService
>
> {
>
> //_at_PersistenceContext
>
> @Inject @OSGiService(dynamic=true)
>
> private EntityManager em;
>
> ....
>
> }
>
> But it's not able to locate the JPA EntityManager
>
> [#|2012-02-21T12:06:21.679-0600|WARNING|glassfish3.1.2|javax.enterpris
> e.system.container.ejb.com.sun.ejb.containers|_ThreadID=26;_ThreadName
> =Thread-4;|EJB5184:A system exception occurred during an invocation on

> EJB UserAuthServiceEJB, method: public boolean
> eclipsecon2011.osgieehol.ejb_service.impl.UserAuthServiceEJB.login(jav
> a.lang.String,java.lang.String)|#]
>
> Caused by: java.lang.NullPointerException
>
> at
> eclipsecon2011.osgieehol.ejb_service.impl.UserAuthServiceEJB.login(Use
> rAuthServiceEJB.java:27)
>
> What is the proper way to accomplish this?
>
> Thanks!
>
> "Do the right thing. It will gratify some people and astonish the
rest."
> - Mark Twain
>