Java EE vs. Spring: The two are not quite equivalent

Java EE has certainly improved since the days of J2EE, but a look at Spring and Java EE today shows Java still has some catching up to do.

While Java EE is a powerful platform that has been simplified and optimized over the past few years, to say that Java EE can do everything that the Spring framework does would be a gross misstatement. Let's take a look at Java EE vs. Spring and check some things Java EE can do, and see how Spring can be used alongside of or as a replacement for some of these APIs to make development better.

Updated inversion of control (IoC) tutorials and dependency injection examples

TheServerSide has been updating its resources in terms of the Spring framework, Java EE contexts and various different approaches to inversion of control (IoC) and dependency injection (DI). Check out these newer resources on the topic:

JDBC 4.1 and Spring's JdbcTemplate

The Java Database Connectivity (JDBC) API, which I first taught back in 1999 as adjunct material to the Sun JDK 1.0.2 course, has been the underpinning of many frameworks, including Hibernate and the JPA Service Specification, iBATIS/MyBatis and many others.

The original JDBC querying API was written with two expectations:

  1. The developer must obtain a connection, create a statement and then process a result set.
  2. The developer must close these properly and handle checked exceptions to avoid creating resource leaks.

Here is a typical block of (pre-Java 7) JDBC code:

Connection conn = null;
Statement statement = null;
ResultSet rs = null;

try {
   conn = // let's assume we ask a connection pool for the connection
   statement = conn.prepareStatement(“select a, b from foo f where f.c = ?”);
   statement.setInt(1, 234);
   rs = statement.executeQuery();
   while (rs.next()) {
      // process each row
   }
} catch (SqlExceptoin se) {
   se.printStackTrace();
} finally {
   try {
      // this isn't quite right- you should close each one in a try/catch for safety
      rs.close();
      stmt.close();
      conn.close();
   } catch (Exception e) { ... ? }

Here are the main issues with this code:

  1. The developer must handle exceptions properly.
  2. The finally block is tricky to write well.
  3. The developer has to deal with a checked exception (SqlException) and re-throw it as a runtime exception, or throw it up the stack (ick).

That is a lot of boilerplate code. So much, in fact, that we left out the while loop that fetches each row, and replaced it with a tidy comment.

The Spring way

One of the first APIs the Spring team created was the JdbcTemplate API. Based on the template method design pattern, where a method provides both setup and teardown code for processes and provides a way to insert logic to handle the processing within a safe block of code, this API simplified several things:

  • Developers no longer had to try/catch exceptions to handle errors.
  • Errors were thrown up the stack as runtime exceptions, not checked exceptions.
  • Resources were allocated outside of the business logic, so connection leaks were made impossible.
  • Any code that was repetitive was pulled into the template method itself.

The same code in JdbcTemplate could take several forms. Here is the simplest form:

JdbcTemplate template = new JdbcTemplate(connection);
List
  
    template.query(“select a, b from foo f where f.c = ?”, 234,
              new RowMapper {
                    public MyAbc mapRow(ResultSet rs, int rowNum) 
                          throws SQLexception {
                          return new MyAbc(rs.getString(1), rs.getString(2));
                    }
              }
}

  

The JdbcTemplate's query method provides an API called the RowMapper, which is implemented to process each row. The opening and closing of connections, creation and preparation of statements, even the mechanics of creating and returning a list are all handled within the query method.

We even have room to show the full method, since we don't have so much teardown code anymore.

Ken Rimple's Spring summary

This is part two of a five-part series. Check out the other parts below.

Part one: Why the Spring framework is still relevant

Part two: Compare and contrast Java EE and Spring

Part three: JDBC chases Spring

Part four: The case for Spring

Part five: Refuting the case against Spring

Next Steps

Here are some other helpful tips, tricks, tutorials and examples by Cameron McKenzie (@cameronmcnz):

  1. Getting started with Git: The 5 basic Git commands everyone needs to know
  2. A RESTful APIs tutorial: The principles of effective web service design
  3. Microservices deployment? How to embed Tomcat in an executable JAR
  4. Continuous integration quickstart: A step-by-step Jenkins tutorial for beginners
  5. Undo bad commits with this git reset hard example tutorial

Dig Deeper on Front-end, back-end and middle-tier frameworks