A little history
It took five years after the Java language was born for the enterprise version, J2EE, to arrive. Dubbed “Java Evil Edition” at the time, it was a nightmare to work with, causing a huge demand for optional lightweight solutions to replace it. After three years Rod Johnson came through with his revolutionary book, Expert One-on-One J2EE Development without EJB, describing features of the new Spring framework. It was like a breath of fresh air, and soon Spring’s intuitive Dependency Injection feature became the de-facto standard implementation for Inversion of Control (IoC) design pattern.
Both JEE and Spring have evolved since then, though Spring always seems to be a step ahead. All the best functions introduced in Spring were later adopted by “standard” Enterprise Java, including:
- Spring IoC implemented in JEE as Container Dependency Injection (CDI), and;
- Spring Batch implemented in JEE as JSR 352: Batch Applications for the Java Platform.
To be fair, cool new features in Java like Annotations caused revisions to Spring too. Besides providing annotation-based configuration in its third iteration, Spring also became modular thanks, at least in part, to the tremendous popularity of Maven which had introduced a new way of resolving and managing dependencies to third-party libraries. In fact, JEE and Spring have continued to impact and encourage each other, such as when JEE 7 introduced modularity with Web profile, unburdening developers from JAX and facilitating more lightweight enterprise applications. Similarly, Lambdas from Java 8’s JCP 335, and Date & Time API from JCP 310, spurred new enhancements in Spring .
Advocates of either JEE or Spring tend to perceive them as mutually exclusive. I would argue that they don’t have to be and provide some pro and con comparisons below. Besides, “advocates” often have ulterior motives. For instance, those bent on persuading developers to move from Spring to JEE 6 or 7 tend to reside on Oracle-owned domains. (Oops,J) And given Oracle’s immense influence, it is easy to see them as the evil empire. Remember Arun Gunta’s (of Oracle) seminal article that compared test code from JEE and Spring? I thought the comparison was unfair because JEE dependencies are already deployed to the server, so Spring libraries should have been put into a shared Tom EE folder or deployed as a module in JBoss. But go back and read the comments from evangelists on either side! Emotions were high!
So let’s look at some comparisons in a more balanced environment.
Side-by-side JEE & Spring comparison
Disclaimer: I have used the Spring stack in almost all of my projects, so I am probably biased toward Spring. But I see value in Enterprise Java and like that both options are available. At Coherent Solutions, we always analyze the scope and specifics of a project before determining which product or library will suit its goals best.
Spring’s implementation focus vs. JEE’s standardization and portability
The main difference between the SpringSource community vs. the Java Community Process is in their different motivations. SpringSource innovation comes from the need to resolve real-world issues. Solutions are oriented to fixing a problem so that the next step and the entire project can be implemented as swiftly and smoothly as possible.
JCP is a little more corporate. Innovations and decisions are tied up with how the solution will lead to creating a standard technical specification. Plus, the big players like Oracle, IBM, RedHat and even (surprise!) SpringSource take part in JCP. Most Java Specification Requests take a long path to actual implementation. For instance, JSR-303: Bean Validation took three years to complete. Perhaps speed is not as important in this realm as most big corporate projects do not change very often and have a longer life cycle. They might not even want all the newest cutting-edge, but unproven, technologies.
Another argument for JEE is portability. In a nutshell, JEE is a set of specifications. What you use in your application can be pulled into whatever JEE compatible container you choose. Simply put, you wrap your business logic in some conventional way, provide persistence for CRUD operations and then choose from among 14 JEE vendors. Ideally, you should be able to move your code between different servers. And this works – sometimes. First of all, only three vendors now support JEE 7, so many are becoming irrelevant. Secondly, some implementations are vendor-specific and still require time and resources to make the project run in a different environment. Of course it depends on the complexity of the project. A no-brainer sample app will start on any AS, but not so a complex one.
On the other hand Spring is backed only by VMWare and is considered to be a wrapper for other libraries, coupling them together under one roof and providing easier access and configuration capabilities – if you know how to do this. But a Spring application can be run in a full-fledged JEE server as well as in lightweight JSP containers like Jetty, Tomcat or Netty, avoiding big overhead costs. Spring can even run in standalone mode as the Spring Boot module can wrap a Jetty or Tomcat.
Most comparison tests of JEE to Spring have been flawed. Only good load & stress testing, as well as continuous benchmarking can truly analyze bottlenecks in the application. The fact is, one or another container might be better suited in any particular case. To illustrate my point, I chose three similar, though not identical, applications in:
- Spring Pet Clinic
- Its port to a JEE 6 application
- A JEE 7 application built from scratch to emulate Spring Pet Clinic
(See chart below)
|Timing, ms||Startup mode||Details|
|2320||Pure WF 8.1 startup||Started 184 of 233 services|
|6426||Spring Pet Clinic deployment|
|8696||WF 8.1 startup with deployed Spring Pet Clinic||Started 756 of 810 services|
|7292||JEE 7 Pet Clinic deployment|
|9135||WF 8.1 startup with deployed JEE 7 Pet Clinic||Started 462 of 514 services|
|4034||JEE 6 Pet Clinic deployment|
|6263||WF 8.1 startup with deployed JEE 6 Pet Clinic||Started 339 of 391 services|
Making them run under one container, I didn’t notice any big differences in load time or memory usage. I suppose this could be due to the small sample size, or my high performance laptop. But you might conclude from the chart that JEE 7 is worse than Spring if you don’t take into account that the JEE 7 application is not actually a port from Spring Pet Clinic, and it offers more screens to display and more domain entities to manipulate. The same for JEE 6. It’s not a complete port – you can create visits similar to the Spring version of the Pet Clinic app, but not all functionality was moved onto JEE.
My point is that when JEE and Spring both run under the same JVM, achievement is based on each developer’s skills and experience.
Of course the learning curve is steep for either Spring or JEE. But let’s start at ground-level. Complexity is a matter of perception, experience, knowledge, mood, grit. None of this is easy, but still the same idea lurks on both sides – the opposite technology is the intricate knot that will steal your time while you’re trying to solve a particular task. (Not that there are really such hardline Spring- or JEE-minded people :))
I have found that Spring is logically structured, and while class names like TransactionAwareConnectionFactoryProxy or UserCredentialsConnectionFactoryAdapter can look scary, they describe what is implemented in the class without much digging into the tutorials. JEE, on the other hand, relies on scattered specifications. But by knowing what part of the application you need to understand, you can find it in the appropriate guide. There are tons of examples and how-to’s for both frameworks. In the end, Spring and JEE are built on the same principles to provide tools for Java web application development. If you understand basic software patterns and design, you’ll be able to learn either of them.
In my next blog I will analyze and compare three applications (JEE 6 Pet Clinic, JEE 7 Pet Clinic, and Spring Pet Clinic), forked and adapted for the post. Feel free to explore the links! The prerequisites are running Wild Fly 8.1 and installed Maven 3+. Use ‘mvn wildfly:deploy’ command to deploy any of the projects.