users@javaee-spec.java.net

[javaee-spec users] [jsr366-experts] One container to rule them all

From: Antonio Goncalves <antonio.goncalves_at_gmail.com>
Date: Mon, 22 Dec 2014 21:28:35 +0100

Hi all,

We've talked about this topic in EE 7... and I'm bringing it back to EE 8.

At the moment, the Java EE spec defines several containers (*EE.2.4 -
Containers*) : Web Container, EJB Container, Application Client Container
and Applet Container. Each having its own set of services (*EE.2.7 - Java
EE Standard Services*) such as JTA, Validation, CDI... The spec also
defines SPIs (*EE.2.12.2 - Java EE Service Provider Interfaces*) as "the
contract between the Java EE platform and service providers that may be
plugged into a Java EE product". But these SPIs are not really mandatory
(only a few specs have SPIs).

Why not go further and say "*There is a single Java EE container, and each
service can then be plugged in through a SPI*" ?

Let me take an example. If we want to persist a Book Entity in Java SE we
go :

*EntityManagerFactory* emf =
Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
*EntityManager* em = emf.createEntityManager();
EntityTransaction tx em.getTransaction();

tx.begin();
Book book = service.createBook(new Book("H2G2"));
tx.commit();

em.close();
emf.close();


That's fine because the JPA service does persistence. But if the Book
Entity has a Listener with a CDI @Inject, this doesn't work anymore : you
need an extra injection services that comes from another spec (CDI in this
case). The idea behind the EJBContainer API was to aggregate several
services (i.e. the services given to an EJB component). So, to have JPA and
CDI working in Java SE we would go :

Map<String, Object> properties = new HashMap<>();
properties.put(EJBContainer.MODULES, new File("target/classes"));
*EJBContainer* ec = EJBContainer.createEJBContainer(properties);
Context ctx = ec.getContext();

BookEJB bookEJB = (BookEJB) ctx.lookup("java:global/classes/BookEJB");

ec.close();


But if the EJB spec is not updated, then the EJBContainer will not include
the new services (such has the new Security spec, and so on).

*So what if the Java EE spec would define a single container API *?
Something like this would trigger a full Java EE container with *all* the
services :

*Container eec = Container.createContainer();*

EntityManagerFactory emf = *eec*
.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = emf.createEntityManager();
EntityTransaction tx em.getTransaction();

tx.begin();
Book book = service.createBook(new Book("H2G2"));
tx.commit();

em.close();
emf.close();

*eec*.close();


Or if we just need the JPA + BeanValidation + CDI providers, we would go :

List<Container.PROVIDER> properties = new ArrayList<>();
properties.put(*PROVIDER.JPA*);
properties.put(*PROVIDER.BEAN_VALIDATION*);
properties.put(*PROVIDER.CDI*);
*Container* eec = Container.createContainer(properties);
//...
*eec*.close();


To have a Web Profile we could go :

List<Container.PROVIDER> properties = new ArrayList<>();
properties.put(*PROVIDER.WEB_PROFILE*);
Container ec = Container.createContainer(properties);
//...
ec.close();


And the Container API would become a facade to create any Java EE provider
:

EntityManagerFactory emf = *Container.createEntityManagerFactory*
(PERSISTENCE_UNIT_NAME);
CacheManager cache = *Container.createCacheManager()*;
WebManager web = *Container.createWebManager()*;
BeanManager bm = *Container.createBeanManager()*;


This would bring real modularity (even before Java EE 9) and, finally,
would ease Java SE execution and testing.

Any thoughts ?

-- 
Antonio Goncalves
Software architect, Java Champion and Pluralsight author
Web site <http://www.antoniogoncalves.org> | Twitter
<http://twitter.com/agoncal> | LinkedIn <http://www.linkedin.com/in/agoncal> |
Pluralsight
<http://pluralsight.com/training/Authors/Details/antonio-goncalves> | Paris
JUG <http://www.parisjug.org> | Devoxx France <http://www.devoxx.fr>