There's an old saying that it's bad manners to talk politics and religion. It's likely true that the same can be said for discussing which enterprise application development framework is the best - Spring or Java EE 6. I thought that this topic had been beaten to death until I recently read an article that prompted me to dig a little deeper. Apparently, the debate is still raging, as is evidenced by the many partisan and aggressive comments posted on this well written blog by Arun Gupta at Oracle.

The debate about whether The Spring Framework or standards-based Java EE is the better platform or framework for building enterprise applications has been raging since Java EE 5 was released by Sun Microsystems in 2006. Let's face it - Spring made things much easier than they were prior to Java EE 5.

However, Java EE 5 took a few pages out of Spring's book and simplified the development of enterprise components with annotation-based dependency injection, standard object/relational mapping (JPA 1.0), transactional beans (EJB 3.0), asynchronous and timer beans, and many other much improved or innovative features. Java EE 6 took things a few steps further with Context and Dependency Injection (CDI), EJB Lite, the Web Profile, and JPA 2.0. Building standards-based enterprise applications has never been easier than it is now, with Java EE 6. But it's still, really, no easier than it has been all along with Spring. The fact, though, is that you can choose Spring, Java EE, or both and likely achieve your desired goal. They are both excellent, efficient platforms for developing enterprise applications.

And although they are usually mutually exclusive, they don't necessarily have to be. But most will make a choice between the two. We chose The Spring Framework when we developed Broadleaf Commerce. Rather than join the "Holy War" regarding which platform is better, I'll simply talk about why we chose and continue to endorse Spring.

The Reasons

Broadleaf Commerce was first released in 2009. Spring was hot at that time. It was easy, there was a great deal more adoption with Spring than with Java EE 5, and we were looking for something that would run on any application server (including Tomcat). Spring also provided a number of features such as excellent support for AOP, property substitution, plug-able caching, more flexible control of JPA configuration, etc.

Broadleaf is an eCommerce .framework.. Broadleaf was designed to provide default functionality right out of the box. But it was also designed to allow users to extend or override entities, services, DAOs, etc. to allow for custom data and functionality. Since Broadleaf relies on dependency injection to wire up internal dependencies (e.g. Order Service relies on Pricing Service, etc.), we needed a way to allow users to override the default dependencies without changing the binaries that we provided. Spring's Application Context made (and continues to make) this possible. My colleague, Jeff Fischer, in his mad genius, extended the Spring Application Context and created a special Merge Application Context that allows us to take Broadleaf's complex default application context XML and configuration files, and merge user defined application context XML files with them.

As long as the bean IDs are the same and the same interfaces are implemented, the end user could override Broadleaf's complex default configuration with one or more new XML files to completely customize any part of the framework. This would have been much more difficult with the default dependency injection mechanisms of Java EE. So there are a number of reasons that we continue to choose Spring as the application development framework for Broadleaf Commerce:

Control

I've generally described the application context merge process that allows the control of Broadleaf components and dependencies. However, there are a few specific items to talk about in more detail:

RuntimeEnvironmentPropertiesConfigurer

Spring provides a handy utility called PropertyPlaceholderConfigurer. This utility allows property substitution in the Spring Application Context. For example:

<bean class="com.mycompany.MyBean">
    <property name="myProperty" value="${myValue}"/>
</bean

This, at runtime, substitutes ${myValue} with an actual value in a properties file. Broadleaf took this concept a step further with the RuntimeEnvironmentPropertiesConfigurer. Broadleaf allows the same thing, but allows multiple properties files, each for a different environment. This allows you to configure all of the environments, build the application, and deploy it to multiple environments without changing the binary war file.

Of course, many QA departments require that the same binary that is certified by them goes to production. No repackaging allowed. This solves that problem. Sensitive information like user names and passwords for the database, or API keys to integrate with a third party, can be accessed via JNDI or the file system. But for properties that are not sensitive, injecting them in an environment-specific way into the application context from properties inside the war file, is an excellent approach.

Broadleaf's RuntimeEnvironmentPropertiesConfigurer will likely become somewhat obsolete with the introduction of Spring 3.1 and Spring's concept of profiles and environment-specific configurations. But Java EE still does not have a comparable solution to this.

JPAPropertiesPersistenceUnitPostProcessor

Normally, and according to the Java EE spec, you require a /META-INF/persistence.xml file for JPA configuration. However, there is no way to control the behavior of the JPA subsystem, on a per-environment basis, without changing this file and/or doing a rebuild. Consider, for example, the following snippet from a persistence.xml file:

<persistence-unit name="blPU" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <non-jta-data-source>jdbc/web</non-jta-data-source>
    <exclude-unlisted-classes/>
    <properties>
        <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
    </properties>
</persistence-unit>

Imagine you want the property hibernate.hbm2ddl.auto to be create-drop in your local environment, but you want it to be validate in production. There is no way to do this with Java EE (not that I know of, anyway). However, Spring provides a nice interface called PersistenceUnitPostProcessor. Making use of the RuntimeEnvironmentPropertiesConfigurer, described above, we can modify persistence unit properties on a per environment basis. This is quite powerful as you do not need to rebuild or repackage your application when the persistence.xml file needs to change.

Instrumentation

Although instrumentation is certainly possible with Java EE, Spring provides some nice features to instrument JPA entities. Broadleaf's entities, by default, use a joined inheritance type. For example:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name="BLC_PRODUCT")
...
public class ProductImpl implements Product, Status {
...
}

But, if someone wants to use a SINGLE_TABLE or TABLE_PER_CLASS strategy, it's quite easy with Spring to allow us to instrument those classes and manipulate them at runtime. This is a very clever way to allow us to slightly modify the binary classes and alter the JPA behavior driven by the annotations, without actually changing the jar files.

Adoption

In addition to the control that you gain through the configuration options provided by Spring and Broadleaf Commerce, adoption is certainly a consideration with respect to choosing an application development framework. Although Java EE is the "standard", Spring has become more of the de facto standard. I'm not exactly sure what the numbers are with respect to adoption. My experience has been that Spring is more prominent than pure Java EE applications, especially in the United States.

However, many large corporations continue to use Java EE-compliant application servers such as Glassfish, JBoss, WebLogic, and WebSphere. Many of them deploy Spring applications to those servers. Often this is because many infrastructure teams prefer the vendor support, tools, features, etc. that come with a larger application server, while their respective development teams often prefer using Spring. Of course, many companies prefer to use a small Servlet container such as Tomcat. In this case, Spring is really the only way to go unless you want to build all of the plumbing yourself. With Spring you can deploy to all of them.

One interesting thing to point out is that although IBM's WebSphere 7 is EJB 3 / Java EE compliant, WebSphere Commerce is not. WebSphere Commerce still uses the legacy EJB 1 and 2 stack. That's an interesting consideration since WebSphere is one of the top Java EE application servers and EJB 3.x has been around for six years. IBM's flagship eCommerce software continues to use an extremely legacy transactional component model. Broadleaf Commerce upgraded from Spring 3.0 to Spring 3.1 with very little difficulty. It is reasons like these that the adoption of Spring has taken off over the years.

Innovation

Spring has continued to innovate far beyond the Java EE specification. Spring embraces / leverages Java EE to some degree (it certainly doesn't preclude it). However, the Java EE specification evolves slowly, which is to be expected with a committee process like the JCP. Spring has been able to respond quickly to the changes in the Java EE specification. But Spring also spends a great deal of time on developing features beyond what is defined in the spec.

For example, Spring provides strong support for JDBC, JPA, JNDI, JMS, JTA, JAXB, JAX-WS, JAX-RS, and the Servlet specification. However Spring has also developed frameworks such as Spring MVC, Spring Security, Spring Batch, Spring Integration, and Spring Social.

Spring also provides support for NoSQL data sources like MongoDB and CouchDB, Big Data support (Hadoop), and support for AMQP (RabbitMQ). Some say this causes vendor lock-in. But this is vendor lock-in that you can take with you, anywhere you go, which doesn't really sound like "lock-in" at all!

Deployment

As I mentioned when discussing adoption, with Spring, we are able to deploy Broadleaf Commerce to practically any application server or Servlet container (e.g. Tomcat and Jetty). And while we can (and do) make use of features such those that are provided by the container using JNDI, we can also configure things without using JNDI.

The best examples of those resources are DataSources, JMS resources, and resources such as TimerTasks for thread pooling and asynchronous processing. With Spring you can use as much, or as little of the application server features and services as you need. Also, as discussed above, you don't need to worry about rebuilding the application when migrating between environments such as development, QA, staging, and production.

The Down Side

Spring has changed certain APIs and made them private, causing some headaches for us. These are situations where they don't expect someone to be extending their framework per se. We have worked around those situations. I do wish that Spring would entirely avoid using private methods. It allows people to extend The Spring Framework as necessary, in innovative ways that the developers at SpringSource never imagined.

Another down side is that, with Spring, you are packaging the container inside the application, and then deploying to an application server that provides many of the same services. It's a lot like putting your sports car in the back of your pickup truck and driving it around. However, as I mentioned, controlling the container services (e.g. via Broadleaf's merge process) allows a great deal of flexibility for the developer.

But having a container packaged inside the application also causes bloat as war files tend to get pretty large. This is more of a nuisance than a concern. But related to this is the fact that in some cases, with large application servers, there are inevitably open source libraries being used by the container such as Apache Commons Logging, Log4J, antlr, JPA, Hibernate, etc. This can cause some problems with classloading and incompatible versions. However, in all cases, we have been able to work around these issues. So, as I said, these issues are really nuisances more than actual problems. They are typically solved once, documented, and do not need to be solved again.

Conclusion

We certainly could have built a feature-rich, enterprise eCommerce site with Java EE. But it was the Spring Framework that allowed us to build a feature-rich, enterprise eCommerce framework or platform that could easily be extended, customized, controlled by a developer, and deployed on any number of servers.

Regardless of the debate about which application development framework is the best, a huge number of developers prefer to use Spring. Adoption, innovation, simplicity, ability to finely control the container and dependencies, and the ability to deploy to any server continue to support our decision to use Spring as the backbone of Broadleaf Commerce. EJB 3.x and Java EE are great frameworks and specifications. But Spring is still the right choice for Broadleaf Commerce.

Now, regarding the debate about whether Java or PHP is the best platform for eCommerce... :)