users@javaee-spec.java.net

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

From: David Blevins <dblevins_at_tomitribe.com>
Date: Wed, 18 Feb 2015 16:36:07 -0800

Late to the game, but wanted to voice my strong support for this concept. No surprise as someone who was an instigator of the EJBContainer API and vocal supporter of this when we talked about it in EE 7.

I'd caution against lumping the concept of an Embedded Container in with Modularity.

I see how one could be tempted by the promise, but I'm personally not a fan of the concept in practice. Geronimo was written as a strictly modular system first using its own design for v1 and v2, then again using OSGi for v3. By sheer brute force we got everything integrated in a way that was considered "pluggable", but in practice there was very little true modularity and things were now twice as hard to integrate having to be continuously abstracted from each other and their inherently coupled nature hidden behind an explosion of false interfaces and overly generic "package neutral" data objects.

Meanwhile, the reality of our industry is that there are on average only two implementations of all the major components. Nearly all of them can be used in some sort of plain Java SE mode. To allow people to use them all at once in a plain Java SE VM, we don't need Modularity, we just need to keep increasing the requirements and vendors will make progress.

To me, the bottom line is that; progress. While I would love for us to have everything be embeddable, I'd settle for just a stack of EJB, CDI, JPA and JAX-RS.

The opportunity in front of us as an EG at this moment in time is that things like "microservices" are quite hot. These are just Embedded Containers with better marketing. In fact there are handfuls of people using embedded Glassfish, Wildfy, TomEE, etc for the task. We are capable, just none of that is standard. More often I hear people say "I can't use Java EE because I need Microservices".

To be clear I'm not saying we should do this because its trendy. I'm saying we've always needed to do this, and now its trendy. It's good for Java EE and good for Java EE adoption.

If we could get an API like the EJBContainer API, but for "Container", we could require just a couple things in it and add more later. We could start with EJB, CDI, JPA and JAX-RS and keep it open to more in the future.

We successfully made a huge step in Java EE 6 with Embedded EJBContainer, paused for Java EE 7, now it's time to take another step in Java EE 8.

I'm less confident, given where we are at, we could ever get 100% Embedded a single specification round. I think we just need another foot forward.



-David

On Dec 22, 2014, at 12:28 PM, Antonio Goncalves <antonio.goncalves_at_GMAIL.COM> wrote:

> 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 | Twitter | LinkedIn | Pluralsight | Paris JUG | Devoxx France