In the last few month we've went through this decision making process: which technology stack to choose for enterprise development on the Java platform? There are various alternatives. However, the ones we've discussed intensively were: Pure Java EE 6 Stack vs. Spring with Java EE. The following blog article summarizes key issues I found interesting when you consider one of those technology stack options. I will not try to convince somebody to choose either of the two. It's the decision making process and the key arguments that are important to me and that I want to share.
What is a "standard"?
The word "standard" was a very important one in our discussions, especially for executive management. I think it gives decision makers a warm feeling with regards to protection of investment. But what is a standard and what can we consider as standard in the Java ecosystem? Mirko Novakovic, founder and board member of codecentric AG, wrote a very interesting blog article called: "Java EE vs Spring. Or: What is a standard?" Mirko states the following:
- for him a standard is something that is established, accepted and dominant
- following this definition only some of the Java EE APIs like the Servlet specification can be considered as a standard, because they are widely applied in the Java production technology landscape
- he looks in the past saying that there was little investment protection in some of the Java EE Standard APIs, like for example the EJB specification (massive API changes over the last decade)
- he also claims that JPA and JSF in their 1.0 Versions weren't sufficient to fulfill the technical requirements in large scale enterprise development projects
- he looks at CDI as another young standard that needs to proove a long term stability before it can be considered as a standard IOC mechanism in Java enterprise applications
- consequently, his conclusion for the moment is: Sping and Hibernate are still "the de-facto" standards for Java enterprise development
Mirko describes a valid perspective. Another valid perspective is the following: all (and only) APIs specified and released in a Java Specification Request (JSR) can be considered as standard. Application server vendors build their products according to these JSRs. Therefore, Java developers can build web applications that run on any application server plattform if they use these standard APIs. In Java EE 6 they can build enterprise scale web applications without any further dependency to a third library. The result is a very light weight web application (WAR or EAR file) that only contains the code that you have developed. That's the Java EE case and that's also valid and conclusive.
When you have to decide which APIs to use in your programming model, what would be the most important thing to you? There are lots of decision parameters like simplicity, completeness of the API, prooved production stability and many more. We have made a long list of parameters in our study. Some of them were more important then others, those were: maturity level of the API, supplier independence, production readiness, investment protection and shared judgement.
Life cycle of Standard APIs
Our assumption is that every API walks through an idealized life cycle when it enters the Java EE Standard (we observed that in the past). Those phases are: Newby, Storm, Stabalize, Mature, Dead. The first (Newby) Version 1.0 of the Standard API has little functionality. Typically it is not sufficient to fullfill the technical requirements for functionality and performance of large scale development projects. This is Mirko's argument against CDI or JPA 1.0. Some use these APIs, but they also have to program many work arounds to get the full functionality they need (e.g. for 2nd level caching in JPA 1.0). The lessons of these phase make their way into the subsequent API versions and therefore - for a while - the API gets instable. Functionality is added, APIs are reduced adopted, simplified and so on. This turbulent and uncertain storming phase leads to increasing migration costs if customers want to follow the standard. Even if the 2.0 Version is downwoards compatible, using the nice new features instead of the many workarounds means refactoring efforts. If the API is not downwoards compatible API changes enforce migration effort, there is no choice. After a while however the API gets mature and these refactoring costs decrease, the API entered the phase of stabalization. A mature API has constantly low costs of migration and refactoring because no fundamental changes are applied. After a while a technology is not used anymore, because it's replaced by other innovative APIs. The technology is dead - there is no investment anymore in these APIs, the community
stopped the project. Image 1 shows the idealized API life cycle.
|Image 1: Idealized life cycle of Java EE APIs
The key assumption of the life cycle model is: the earlier you decide to use an API standard the more refactoring cost you may probably pay when the API is enhanced in subsequent releases. So the advice is: you have to judge the state of the (Java EE) API in the life cycle. Then you decide whether you want to use mature APIs and lower refecatoring costs. Or whether you want to be one of the pioneers using the technology strait away. One advantage of early adoption may be early achievement of higher development efficiencies or higher integration with other standard APIs or developing consulting knowledge.
We have decided to use mature APIs only, we do not want to have the migration costs associated with "Newby" state APIs. Our level of trust is rather low, because we have suffered a lot in the EJB era. If we look at the history of some Java EE standards, the changes associated with stabilization of the API were enormous. Therefore we prefer to wait until the API is mature and is a prooven technology for large application systems in production. If we believe the Java EE API is mature we consider to use it.
Independence (development, operations and OE supplier)
Another important factor in architectural decision making to us: we want to maximize flexibility for subsequent architecural, design or implementation decisons. What do I mean by that? If, for instance, you choose a technology stack that is part of your application server then your application development department, your infrastructure people and your original equipment (OE) vendor will have a very close relationship. Why? Because new application server releases consist of new API versions that you use in your business application. The consequence is that you may have to change your exisiting code when you decide to use a new version of your application server. All this reduces flexibility.
Also, the OE vendor may rush you to migrate because "if you want to have this unique monitoring or integration feature of our application server you will have to use the very latest release of our XY Java EE server". OE suppliers often have an inherent interest in that they want you to use their latest releases. For them it's simply cheaper to support fewer production releases. It generates less maintenance costs and higher consultancy revenue for them.
We run over 50 Java EE applications in production. For the described reasons it is very important to us to stay independent of the runtime infrastructure. Therefore we often prefer a "layer between" our business applications and the application server. In other words: we usualy do not use Newby APIs directly, we usually have a wrapper API hiding them (see Image 2). This wrapper is used as API to build the business applications. The wrapper API could be the Spring Framework, or your own set of custom framework APIs. This way it's easier and more efficient to make required changes when we moove to new application server releases or Java EE versions respectively. The wrapper absorbes Java EE API changes and saves us from the burden to change 50 applications. Instead, we do the changes once in a central place. Our development groups are not affected by application server upgrades. OE suppliers and the Java Communication Process (JCP) do not influence our decisions and efforts.
Production-readiness of infrastructure (or: now or later?)
Is there a production ready release of your application server that implements the new Java EE 6 standard? In our case (IBM WebSphere) we do not have any Java EE 6 Version available on Z Series. So there is only little sense in thinking about Java EE 6 if we can't run our applications in production yet. You have to decide whether you want to use a technology now or later when it is available. CDI (JSR 299/330) as IOC mechanism for example is not mature enough for large applications. Therefore you may have to choose alternatives like the Spring Framework or Google Guice to do the job, if you want to have the (effeciency) value brought to your clients now.
Investment Protection (or: downwoards compatability)
I already mentioned it earlier: using the Java EE API directly for many production applications, may be 50 or 100, will probably create lower flexibility in design and implementation decisions. The same arguments apply when we look at investment protection. To me investment protection is a lot about low technical (refactoring) costs over a specific period of time. You want to spend money to achieve business value, you want to concentrate on implementing business functions. You do not want to spend to much effort in technical necessities (e.g. release upgrades, platform migrations, develop custom APIs). To achieve this choosing the right development API is critical. According to our life cycle model a good option is to choose APIs at the beginning of a long maturity phase in the life cycle. This lowers refactoring cost, thus increases investment protection.
We have already explained that Java EE does not only provide mature APIs. CDI, for example, is not mature in its JSR 299/330 version. A possible solution to that dilemma is to combine APIs from different sources, you could configure your own set of APIs for your business applications. If you use your own set of real standard APIs, then you protect your investment. I am saying your own set because you may use a mixed technology stack (Image 2): some mature Java EE APIs (e.g. Servlets, JPA 2.0), some de-facto standards (e.g. Spring IOC) and some proprietary custom APIs that you have developed as wrappers around Newby Java EE APIs. The most important thing is that those APIs support downwoards compatability for your production applications. You have to find a set of APIs that saves you from large migration efforts when you want to move to new Java EE
application server releases.
|Image 2: Mixed technology stack for Java enterprise development
Something I do when I make decisions is shared judgement. What do other experts think? What ideology do they have? What interest do they have to make the one or the other recomendation? If you look at the large Java enterprise development framewors like Spring Framework you can observe that they use standard Java EE APIs, but only those that they consider as being mature. That's a good hint for me whether or not to use a specific API. It does not metter whether you look at Spring, or whether you observe other frameworks. The point is that you can validate your opinion against the opinions of other prooved (preferably independent) experts.
There is a long list of parameters when you decide what technology stack to use. Those I have described in this article were very imprtant ones in our decision making process. Our conclusion is that the best way forward for now is to use a mixed technology stack. Some APIs are de-facto standards, some are Java EE standards, others are custom APIs that we have developed. Our main objective is to stay flexible at a constantly low level of refactoring costs over time.
A last thought on standards: Have you ever asked yourself whether it's really important to follow the standard? Sometimes I have the impression that - to some people - using a standard is something that is close to absolute truth, something that is a universally right thing to do. Water is wet, the sky is blue and using a standard is right. You know what I am trying to say? How did all those de-facto standards like Spring and Hibernate became standards? The answer is: because someone had the courage to use it and others (including Java EE) followed. A "standard" is what a large part of the community uses to run large applications in production. A standard is not necessarily a Java EE standard. In the past Java EE standards followed the de-facto standard frameworks (e.g. Hibernate, Spring). There is a high probability that any new technologies first reach a certain level of maturity in open source frameworks. Then they will become Java EE standards. That's because the vast majority of Java technology innovation has its source in the community - at least for the last decade.