April 12, 2015

Java EE 7 / Java EE 6 Bean types overview





In order to facilitate understanding of the many notions of “JavaBeans” and of the many means of dependency injection Java EE 7 offers, I created a demo web application which compares the results of the five JavaBean specifications in action. See here the results or run the demo on your own server!

TL;DR? Jump into the demo immediately!

Modularity overkill in Java EE 7

Back in 2013, when the Java Community Process (JCP) released the Java Platform, Enterprise Edition (Java EE) 7 specification (Java Specification Request JSR 342), it promised to further ease the development of Java EE applications by providing a standardized, vendor-agnostic, modular, lightweight, straightforward API based on core concepts such as convention over configuration and inversion of control through dependency injection.

Not only were most of these promises kept, but one of them in particular was even surpassed: The framework is arguably too modular. The specification – which actually is an umbrella specification for 30+ JSR specs that deal with specialized aspects of EE development (service interfaces, O/R mapping, persistence, …) – contains some JSRs which for sort of “historical reasons” have overlapping responsibilities, and in some cases even terminology or API naming conflicts.

This is most obvious and most severe in the specification’s core concept of dependency injection: There are now five notions of “JavaBeans”, injectable components, each with its own means of dependency injections:
  • JSR-316 / JSR-250: Managed Beans
  • JSR-330: Dependency Injection for Java
  • JSR-346 (formerly JSR-299): Contexts and Dependency Injection for Java EE (CDI)
  • JSR-344 (formerly JSR-314): JavaServer Faces (JSF)
  • JSR-345 (formerly JSR-318): Enterprise JavaBeans (EJB) Lite
Some of them are based upon each other while others are mutually incompatible. Many of them have overlapping responsibilities, and between some of them, there are even API name clashes. Also the fact that some specifications were actually updates of Java EE 6 specifications and thus the formerly well-known JEE6 JSR number has been increased arbitrarily for the same module didn’t really make things easier.

Judging by the apparent high number of questions on stackoverflow and other platforms, this left many EE developers confused, especially as to when to prefer any given bean type over the other, and how to properly use them in conjunction. It lacked the overall picture, or the specification apparently failed to convey it to the developers.

I was one of those developers, and I decided to grab as much information about this topic as I could and build a demo application which provides an overview and a comparison of the five standards of dependency injection in Java EE in action. Now that I also have my own blog, I decided to post it online.

Comparison of the five standards for Dependency Injection in Java EE 7 / Java EE 6 Web Profile

This Java EE 7 demo web application compares the five standards for Dependency Injection available on the platform. For each module, basic information about the standard is provided; there are tests for JavaBean lookups; and there are tests for injecting each JavaBean type in any other JavaBean type.

The various JavaBean lookup tests are deliberately not implemented as “classic” JUnit tests; instead, they are implemented in JSF backing beans and executed during Bean initialization. This technique ensures that the lookup tests are actually executed by the container, and nothing is mocked away.

This demo application is based on the so-called Java EE 7 Web-Profile which includes a subset of the full Java EE 7 module stack.

Currently, the only officially Java EE 7 Web Profile compatible application servers are Glassfish 4.0+ and Wildfly 8.x.

On Glassfish

Click here to see the results when running on GlassFish Server Open Source Edition 4.1.

Glassfish is the Java EE 7 (JSR 342) reference implementation.

On Payara

Click here to see the results when running on Payara Server Open Source Edition 4.1. It matches the GlassFish output.

Payara is a distribution of GlassFish with commercial support.

On WildFly

Note: When running the original application on WildFly 8.2.0, exceptions will be thrown when trying to inject a JSR-316 / JSR-250 ManagedBean in either a JSR-330 „Guice“ Bean or a JSR-346 CDI Bean. One has to manually remove the respective @Resouce annotation at the injection point.

Click here to see the results when running on WildFly 8.2.0.

Because of the problem described above, those two Bean injections fail. The output thus differs from the Glassfish output.

LIVE on Wildfly

Click here to see a LIVE demo of the application running on WildFly 8.2.0 (hosted on OpenShift).

The same limitations explained in the previous section apply.

On your own server

Please feel free to download this demo application from GitHub and deploy it to your own server instance.

Lessons learnt?

I created this demo application to help myself answering these questions: What are the differences between the various JavaBean types? How do the various Annotations play together? And, most importantly: When should I use which JavaBean type?

I think the demo application does a great job to help finding answers to these questions. I encourage you to study the application and to come to your own conclusions. I will probably post my personal conclusions in a future blog post. Within this post, I’d like to present the facts only.

However, there are already many in-depth articles and discussions available online where Java EE / JavaBeans best practices are explained. You may find that they are also backed by the results of this demo application. Some of the most insightful online resources include the ones listed here.

(Note: Some of these articles contain are based on previous Java EE versions.)

Conclusion

I like Java EE 7. It brings everything Java EE out-of-the-box with a single Maven dependency, its programming model is lean and centered around an annotation-based “convention over configuration” design, and through its standardization, it really promotes “write once, run everywhere” (it’s still up to the server vendors to fulfill this promise).

But here are, in my opinion, serious design flaws in the platform, and studying its inversion of control mechanism reveals several of them. Really, having five standards for dependency injection is just pure overengineering. This is not DRY, this is re-inventing the wheel, and this is bad software design.

On top of that, there are several ambiguities and conflicts evolving from similar names of concepts and components, the most severe of which are probably the two @ManagedBean annotations (which, ironically, are both kind of useless), class name clashes for scope annotations and a confusing split in two similar, but incompatible transaction mechanisms.

As an end user of the API, I’m not interested in the entire Java EE back-story. I want a concise, uniform, lean API. There’s just too much history and politics which leaks through the current state of the Java EE 7 API. I wish that a future version of Java EE will see the JCPs involved gathering together with the big picture in mind. Or at least, please hand out more practical PAI manuals.

Please let me know in the comments section below whether you found this demo application helpful or whether it lacks important information. Even though I worked with great care on this application, inaccurate information may have sneaked in. If you found any error or wrong information, please report them here so I can update the application. Or start a pull request on the GitHub repository. I’ll be also interested to hear if you concur with my opinion on Java EE modularity; if you have other helpful guidelines, please let me know.

No comments:

Post a Comment