Spring is a mature, production-ready solution. However, the Spring team has demonstrated a rapid pace of innovation and is committed to further enhancements. While you can be confident of Spring offering backward compatibility, as it has done to this point, you can also expect many enhancements and new capabilities.
This book covers Spring 1.2, released in early 2005. Spring 1.0 was released in March 2004, Spring 1.1 in September 2004. These two major releases have been close to 100 percent backward compatible, despite adding a significant number of features. Spring continues to evolve and innovate at a rapid rate.
Spring operates on a 4–6 week release schedule. Normally a point release contains bug fixes and minor enhancements. A major release, such as Spring 1.1, contains significant new features (in that case, some IoC container enhancements and the first phase of JMS support). Major releases are normally around6 months apart.
A key proof of the value of a non-invasive framework is how Spring's implementation can evolve significantly, and its capabilities increase greatly, while preserving backward compatibility. This is emphatically different from the experience with APIs such as EJB, where every major version has resulted in a substantial migration exercise, or the maintenance of two separate code bases. As we noted earlier, Spring is different.
This is also an important benefit for third-party products that integrate with Spring — and, of course, users of those products. For example, Acegi Security System, an external project, is able to provide complex value-added functionality spanning multiple layers, without needing any hooks into Spring.
In general, you should work with the latest production release of Spring. Spring's comprehensive test coverage and excellent record on backward compatibility help make this a workable strategy.
J2EE itself is also evolving, so it's natural to ask how Spring will fit into the J2EE ecosystem as J2EE moves forward.
The major changes relevant to Spring development concern the EJB 3.0 specification, currently under development by the JSR-220 Expert Group, and expected to reach final release in early 2006.
EJB 3.0 introduces two major changes relevant to Spring users and Spring's positioning with respect to J2EE:
It introduces a simplification of the session bean programming model, which rests partly on the use of Dependency Injection to provide simpler access to the bean's JNDI environment.
It introduces a new specification for POJO persistence. Strictly speaking, this is separate from the EJB specification itself, as JSR-220 will in fact produce two deliverables: the EJB 3.0 specification and a POJO persistence specification. The JSR-220 persistence specification is likely to be supported by all major O/R mapping products, including TopLink, Hibernate, and leading JDO products. It also effectively relegates the EJB 2.x entity bean model to legacy status, merely formalizing the reality seen among usage trends since 2002.
The introduction of Dependency Injection features in EJB 3.0 is an interesting move from a specification group, indicating that the "lightweight" approach to J2EE popularized by Spring and other projects has become too influential to ignore. (Indeed, the influence of Spring on the EJB 3.0 session bean model is unmistakable.) However, EJB 3.0 offers a very limited form of Dependency Injection, which has different goals, and does not approach the capabilities of Spring or other leading IoC containers. For example, it can inject dependencies only on objects that come from JNDI; it cannot manage objects that are too fine- grained to be placed in JNDI; it cannot easily manage configuration properties such as ints and Strings, which are very important to externalizing configuration from code; and it cannot manage lists, maps, or other complex types that the Spring IoC container can handle. At the time of this writing, it provides no standard way to apply interception or full-fledged AOP capability to injected collaborators, meaning that it misses much of the value-adding possibilities open to a sophisticated IoC container. Finally, it seems capable only of per-class Dependency Injection configuration (due to reliance on Java 5.0 annotations for the recommended configuration style), rather than the per-instance configuration supported by Spring and other sophisticated IoC containers, which is often necessary in large applications.
After the hype dies down and more technical details emerge, it's unlikely that EJB 3.0 session beans will change things much for Spring users. If you want to use Dependency Injection, you will almost certainly end up using Spring behind an EJB 3.0 facade. The Spring team will ensure that this is easy to do.
If you want to keep your options open regarding an eventual migration to EJB 3.0, a Spring-based approach will give you a production-proven basis for you to implement now, while enabling a far easier migration path than the EJB 2.x model, which is effectively deprecated in EJB 3.0. (While you could continue to run EJB 2.x beans in an EJB 3.0 container, this isn't attractive in the long run, amounting to a substantial legacy model.) However, it's hard to see any benefit for Spring users in moving from Spring- managed business objects to EJB 3.0 session beans — this would sacrifice many capabilities, reduce the range of environments in which the relevant code could execute, and add little or no functionality.
The core benefit of EJB 3.0 Dependency Injection — the ability to inject objects obtained from JNDI such as DataSources, has been offered by Spring, in the form of the JndiObjectFactoryBean, since Spring's inception.
JSR-220 persistence has more significant implications than the EJB 3.0 session bean model (which is essentially playing catch-up with features long offered by lightweight frameworks). JSR-220 persistence adds significantly to the already compelling case for Spring's unique data access abstraction. As we've seen, there is real value in being able to implement a DAO interface using, say, Hibernate or JDO, or JDBC (if it doesn't imply transparent persistence). Today, there is a range of competing O/R mapping products. With the release of the JSR-220 specification for POJO persistence ahead, this value proposition becomes still more compelling. We know that persistence is likely to change. Thus it is logical to try to abstract away from the details of your chosen persistence API, and isolate dependence on it behind a layer of interfaces.
Spring's sophisticated persistence infrastructure, and its DAO interface approach, is a perfect candidate to do this — indeed, the only candidate at present, the alternative being in-house coding.
Finally, Java is itself evolving. With the release of J2SE 5.0 in September 2004, Java has seen arguably the most significant enhancements in its history. While backward compatibility is essential internally for a widely used framework such as Spring, Spring 1.2 offers additional functionality for J2SE 5.0 users: for example, leveraging J2SE 5.0 annotations where appropriate (in particular, for declarative transaction management).
While the J2EE specifications continue to evolve, they are not evolving fast enough. The Java specification process faces twin dangers: premature standardization, before a technology is well enough understood to choose the correct path; and glacial progress, where standards lag far behind common practice. (For example, although EJB 3.0 is a major overhaul of the session bean model, it will offer in 2006 a subset of Dependency Injection capabilities available in a production release in Spring and other products in early 2004.)
As new paradigms such as AOP and IoC gain further momentum, and experience around their use accumulates, an agile framework such as Spring is far better placed than a specification committee to offer a solid implementation to its user community.
Spring is also well placed to support other emerging areas, such as:
Scripting: Java is not the be all and end all of the JVM. Scripting languages — especially Groovy — are enjoying growing popularity. We expect this trend to continue. Spring can provide the same comprehensive IoC and AOP services to objects written in any scripting language as to Java objects, within a consistent programming model. The language in which an object is written — like the particular implementation of an interface — can be concealed from callers. This raises the possibility of writing objects in the most appropriate language. In some cases, language features such as closures offer a much more succinct option than Java.
A cross-platform programming model: The Spring programming model is now available for .NET, with the release of Spring.NET. This is particularly interesting for organizations that have an investment in both platforms, and architects and developers who need to work on both platforms.
Of course this touches on another challenge to J2EE orthodoxy, and the belief that Sun "standards" are always the best way forward for the industry.
Chapter 4 of J2EE without EJB discusses this issue in more detail. There is a strong argument that while standards have produced real benefit in the case of low level services, such as JNDI and JTA, they have largely failed where (like EJB) they have entered the domain of the application programming model. Specification committees are not best placed to deal with issues in the application programming domain; responsive open source projects with a capable development community and thousands of users are.
The consequences of failed standards, like entity beans, are far worse than the consequences of using good, non-standard, solutions. It's more important to have a working application, delivered on time and budget, than an application that uses only largely unproven standards.
Currently there doesn't seem much likelihood that the JCP will produce anything in the application programming space that equals the value of what Spring and other lightweight frameworks provide.
The emergence of non-invasive frameworks such as Spring has also cut against the old assumptions regarding standardization. Framework lock-in can be minimized. Where application code depends largely on standard Java constructs (as in the case of Setter and Constructor Injection), there isn't much that needs to be standardized.
Furthermore, it's significant that Spring and other leading lightweight containers are open source. There's an argument that open source reduces the danger of proprietary solutions, as does a non-invasive framework. There's no risk of a greedy vendor cornering the market and fleecing users; the source code is available in any event; and in the case of successful products such as Spring there are many people who understand not just how to use the framework but how it works internally.
Partly for this reason, it seems that infrastructure is inexorably moving toward open source. It's becoming increasingly difficult for commercial products to compete in this space. Spring is a key part of the brave new world of J2EE infrastructure, and application developers are the main beneficiaries.