Thursday, October 01, 2009

An Overview of Spring

Spring is a very popular framework in the Java space and quickly becoming an alternative to JEE. Spring started of as an implementation of the ideas in the book "Expert One-on-One J2EE Design and Development" in 2002 by Rob Johnson. Today the project has grown into to a large framework with multiple modules to assist with different areas of serverside programming. Spring provides a lightweight container and uses POJOs. This makes code much simpler to reason about and also test. No starting a mega EJB container anymore with remoting when you don't really need it.

Inversion Of Control (IoC)
At its core, Spring is an IoC container. Generally at some point in code you use 'new' instances. If you are coding against an interface you end up with code like:

class Bar {
Foo foo;
void Bar() {
foo = new FooImpl();
}
}

Now the class Bar has a dependency on Foo and its implementation FooImpl. Now you could remove this dependency by using the ServiceLocator pattern but then you end up with a dependency to the ServiceLocator class and your code is not that testable anymore.
In Spring you instead inject the actual implementations at runtime and rules about which instances are to be returned are written in an XML configuration file (or via Annotations). So code becomes like:

class Bar {
Foo foo;
void Bar(Foo foo) {
this.foo = foo;
}
}

with an instance of FooImpl being returned where Foo is expected. Now Bar depends only on the interface Foo but not the implementation of Foo which is simply passed to it. Hence the name Inversion of Control as Bar does not depend on FooImpl but gets it.

More importantly the code can be tested very easily. If I wanted to test the Bar class I can very easily provide a mock implementation of the Foo instance. Writing testable code is difficult and a major part of the problem is breaking dependencies. You should probably never need to new objects again but just get them injected.

In the above example Foo is set in the constructor. This is an example of a Constructor based injection. Another way to inject dependencies is via setter methods. However I prefer Constructor based injection as it allows for final fields which should be the default to help with immutability.

Another important idea is how instances are created. This is known as scopes. By default instances are created only once and that reference will be passed everywhere similar to a Singleton. So one FooImpl instance is created and passed wherever a Foo is needed. A lot of code can be written in a style where there is no local state allowing for Singletons. Again since the Singleton pattern is not explicitly needed, code remains testable. Another scope is prototype in which a new instance of FooImpl will be created whenever a Foo needs to be injected. For web programming other scopes like Request, Session and Application also exist.

The complete lifetime of instances can be managed and there are many other features but thats another post. If you just need an IoC container then there are alternatives like Google Guice.

Aspect Oriented Programming

AOP allows for crosscutting code to be written external to the main business logic. This allows cleaner code in areas like logging. The implementation of AOP in Spring is based on Proxy based interceptors which happen at runtime. AspectJ integration is also provided in some form.
One of the major uses of AOP is defining transactions which will be covered soon.

Data Access and Transaction management

Most serverside code needs to talk to a database. Spring provides neat abstractions over JDBC and other frameworks to simplify code to a great extent.

A DataSource is usually configured and injected.
JDBC code is wrapped with classes like the SimpleJdbcTemplate. Queries become like:

String daString = getSimpleJdbcTemplate().queryForObject(
"SELECT daString FROM DaStringTable WHERE daStringId = ?",
String.class, daStringId);

Thats one line of code for what would have been multiple lines of JDBC like getting a connection, then statement, then query and result parsing. And there are no SQLExceptions. All of those are wrapped into a DataAccessException instance which is a RuntimeException. Create a generic handler in your code for exceptions because thats what you'll mostly be interested in. You can easily provide mapper classes to map from db values to object instances for custom types. Also variations exist for returning mutiple rows and other SQL CRUD operations.
And I almost forgot to mention that there are also named parameters for queries.

Using Hibernate is even easier. Use HibernateTemplate instead and get access to a hibernate API. Or JPATemplate if you want to use JPA. All of this code is obviously going to be tucked under a DAO tier!

Transaction management is also dead simple with usage of Java annotations. You declare the Transaction rules for a method invocation like Isolation level (Read uncommitted, Read committed, Repeatable Read, Serializable), Propagation (Required, New), timeout and exceptions for rollback. An AOP proxy is created over the method which enforces the Transaction rules over the underlying datastore.

Web MVC

Built on the core IoC functionality Spring has a Web MVC framework as well. Like Struts it is a request or action based framework. The DispatcherServlet class is a FrontController and acts as the entry point to the MVC framework. Typically request URIs are mapped to Controller classes. Controllers compute the Model and then render a View based on the Model for the request. A general multi tier architecture for applications is another topic.

Even more

There are quite a few other projects under the Spring banner. WebFlow extends Web MVC for richer work flows in webapps. Spring WebServices for WebService (duh). Spring IDE is a bunch of Eclipse plugins to help with Spring development.

Spring Framework 3 is going to be released. It adds better Java 5 support across various APIs. There is also a lot of annotation usage.

The company and future

Spring started off as a simple open source project and has now morphed into a complete stack framework backed by a company.
The core framework helps building applications. Further they added Groovy language and Grails. Mostly spring apps need a web container like Tomcat or Jetty to run. SpringSource also provides a custom Tomcat build known as tcServer with additional capabilities. Another environment is the dmServer which adds OSGi capabilities. For management and diagnostics they have additional tools. All of these play together to provide a really strong stack against the usual JEE standard running in an application container.

VMWare bought SpringSource which means that soon Cloud-deployed apps based on Spring are going to be dead simple to make. This means that VMWare will now compete with the likes of Google App Engine and Microsoft Azure as well by providing virtualized application frameworks.

Links

No comments: