Chapter 16

The Spring Framework

The Spring Framework is designed to be a lightweight, non-intrusive framework, providing you with tools and facilities to write standalone, testable components for use in many common applications and scenarios.

Spring enables you to write Plain Old Java Objects, or POJOs, and then connect them together using dependency injection, through a central core component called the application context. POJOs are classes that have no unnecessary restriction, such as implementing an interface for a persistence framework, or extending an abstract class for use in a web application.

The notion of POJOs comes as a reaction from the early approaches to Enterprise Java Beans (EJBs), where your simple domain object needed to follow complicated patterns and implement several interfaces in order to be used within application servers. This code was often brittle and untestable. In turn, this led to a rise in popularity of frameworks such as Spring, which concentrated on simple approaches around application configuration and focused on writing testable code.

This chapter covers several core areas of the Spring Framework: the application context, database programming with the JdbcTemplate, the integration testing classes, and a section on producing web applications using Spring MVC.

Core Spring and the Application Context


How do you use dependency injection with Spring?


Chapter 9 showed a brief example of what dependency injection is, and what advantage it gives. However, the management of the dependencies was completely manual: If you wanted to provide another implementation of a particular dependent interface, you would need to make the changes in the actual code, and recompile and repackage your new built artifact.

Dependency Injection is one of Spring’s core features. It enables you to remove any specific dependencies a class may have on other classes or third party interfaces, and load these dependencies into the class at construction time. The benefit is that you can change the implementation of your dependencies without having to change the code in your class, which allows for easier, isolated testing. You can even rewrite implementations of your dependencies without having to change your class, as long as the interface does not change.

Using the Spring’s mechanism for dependency injection mitigates some of these issues, and can provide a useful framework for writing robust, tested, flexible code. Listing 16-1 is a possible application as a simple spell checker. The checkDocument method returns a list of numbers: the list indices of the misspelled words.

Listing 16-1: A simple spell checker

public class SpellCheckApplication {

    private final Dictionary dictionary;

    public SpellCheckApplication(final Dictionary dictionary) {
        this.dictionary = dictionary;
    }

    public List<Integer> checkDocument(List<String> document) {
        final List<Integer> misspelledWords = new ArrayList<>();

        for (int i = 0; i < document.size(); i++) {
            final String word = document.get(i);
            if (!dictionary.validWord(word)) {
                misspelledWords.add(i);
            }
        }

        return misspelledWords;
    }
}

You should recognize this pattern from Chapter 9: The spell checker depends on the dictionary; it calls the boolean validWord(String) method from the Dictionary interface to check whether a given word is spelled correctly. This spell checker doesn’t know, or even need to care about, the language of the document, or if it should be using a specific dictionary with particularly difficult or technical words, or even if there is a valid difference between a capitalized word and one that is not. This can be configured when the class is actually running.

You should recognize that you don’t even need a concrete Dictionary implementation for testing; the validWord method can be easily mocked to allow all the code paths of the checkDocument method to be tested properly.

But what happens when it comes to running this code for real? Listing 16-2 provides a naïve, but working implementation.

Listing 16-2: A class to run the spell checker

public class SpellCheckRunner {

    public static void main(String[] args) throws IOException {
        if(args.length < 1) {
            System.err.println("Usage java SpellCheckRunner <file_to_check>");
            System.exit(-1);
        }

        final Dictionary dictionary = 
                new FileDictionary("/usr/share/dict/words");
        final SpellCheckApplication checker = 
                new SpellCheckApplication(dictionary);
        final List<String> wordsFromFile = getWordsFromFile(args[0]);

        final List<Integer> indices = checker.checkDocument(wordsFromFile);

        if (indices.isEmpty()) {
            System.out.println("No spelling errors!");
        } else {
            System.out.println("The following words were spelled incorrectly:");
            for (final Integer index : indices) {
                System.out.println(wordsFromFile.get(index));
            }
        }
    }

    static List<String> getWordsFromFile(final String filename) {
        /* omitted */
    }
}

The specifics of the FileDictionary class do not matter; from its use here, you can visualize that the constructor takes a String argument to a location on disk of a list of valid words.

This implementation is completely inflexible. If the location of the dictionary file changes, or perhaps a requirement comes to use a third-party online dictionary, you will need to edit this code, potentially making other mistakes as you update it.

An alternative is to use a dependency injection framework, such as Spring. Rather than constructing the objects and injecting the necessary dependencies, you can let Spring do it for you. Listing 16-3 shows a definition of a Spring application context represented in XML.

Listing 16-3: A Spring context for the spell checker

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation=" http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="dictionary" 
          class="com.wiley.javainterviewsexposed.chapter16.FileDictionary">
        <constructor-arg value="/usr/share/dict/words"/>
    </bean>

    <bean id="spellChecker"
          class="com.wiley.javainterviewsexposed.chapter16.SpellCheckApplication">
        <constructor-arg ref="dictionary"/>
    </bean>

</beans>

This XML file defines two beans, one for the dictionary, and one for the spell checker. Values for the constructors are provided here, too: The FileDictionary class takes a String, and this is defined inside the bean definition with the constructor-arg tag.

As well as providing configuration to Spring beans with the constructor-arg tag, you can also use the property tag. These call setters on that class. For instance, having a property such as <property name="location" value="London"/> will call the method setLocation with the parameter London.

Of course, this will fail if such a method does not exist, and that failure will not happen until run time.

The SpellCheckApplication class uses the constructed dictionary bean in its own constructor. The constructor-arg tag uses the ref attribute to reference another Spring bean.

Now that you have defined the relationship between these classes, you still need a running application to do your spell checking. Listing 16-4 uses the application context defined in Listing 16-3.

Listing 16-4: Using the Spring application context

public class SpringXmlInjectedSpellChecker {

    public static void main(String[] args) {
        if(args.length < 1) {
            System.err.println("Usage java SpellCheckRunner <file_to_check>");
            System.exit(-1);
        }

        final ApplicationContext context = 
                new ClassPathXmlApplicationContext(
                        "com/wiley/javainterviewsexposed/" +
                                "chapter16/applicationContext.xml");
        
        final SpellCheckApplication checker =
                context.getBean(SpellCheckApplication.class);

        final List<String> wordsFromFile = getWordsFromFile(args[0]);

        final List<Integer> indices = checker.checkDocument(wordsFromFile);

        if (indices.isEmpty()) {
            System.out.println("No spelling errors!");
        } else {
            System.out.println("The following words were spelled wrong:");
            for (final Integer index : indices) {
                System.out.println(wordsFromFile.get(index));
            }
        }
    }
}

Following some boilerplate code checking the program arguments, an ApplicationContext object is created. There are several implementations of ApplicationContext; the one used here, ClasspathXmlApplicationContext, examines the JVM classpath for the given resource, and parses that XML document.

The construction of the application context will instantiate the objects defined in that XML file.

Following the construction of the application context, you can ask it to return the bean instances it has constructed, using the getBean method.

The remaining code in this class is the same as the simple SpellCheckRunner in Listing 16-2.

If you want to make changes to the way the dictionary implementation and the spell checker are set up, you can make these changes without touching the code that has already been written. If you were to use a different file location for the dictionary, updating the constructor-ref of the dictionary bean is all that is necessary. If you add a new Dictionary implementation, once you have written your class, you add the definition to your context, and make sure your SpellCheckApplication instance is referring to the correct bean. Listing 16-5 shows a possible application context for this case.

Listing 16-5: Swapping Dictionary implementations

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>

    <bean id="dictionary"
          class="com.wiley.javainterviewsexposed.chapter16.FileDictionary">
        <constructor-arg value="/usr/share/dict/words"/>
    </bean>

    <bean id="thirdPartyDictionary"
          class="com.wiley.javainterviewsexposed.chapter16.OnlineDictionary">
        <constructor-arg value="http://www.example.org/api/dictionary"/>
    </bean>

    <bean id="spellChecker" 
          class="com.wiley.javainterviewsexposed.chapter16.SpellCheckApplication">
        <constructor-arg ref="thirdPartyDictionary"/>
    </bean>

</beans>

One concern with using a plain-text XML document for constructing Spring beans and defining dependencies is that you lose the value of compile-time type checking; any issues such as using the wrong type in a constructor, or even the wrong number of arguments in a constructor, are not found until the application context is constructed at run time. If you have good integration test coverage, which is run as part of your regular application build, this is one way to mitigate that risk. Another approach is not to use XML definitions at all.


How do you define an application context in Java code?


Introduced in Spring 3.0, it is now possible to have Spring scan the classpath for a configuration.

If you provide a class annotated with @Configuration, then any methods in that class that are annotated with @Bean will be treated in the same manner as those defined in XML with the <bean> tag. Listing 16-6 illustrates the same configuration as that in Listing 16-3.

Listing 16-6: A Spring context defined in Java

@Configuration
public class SpringJavaConfiguration {

    @Bean
    public Dictionary dictionary() throws IOException {
        return new FileDictionary("/usr/share/dict/words");
    }

    @Bean
    public SpellCheckApplication spellCheckApplication() throws IOException {
        return new SpellCheckApplication(dictionary());
    }
}

There is one extra change to make; you still need to initialize the application context. You can do this one of two ways: Either instantiate the application with the AnnotationConfigApplicationContext class, which takes a list of classes annotated with @Configuration:

final ApplicationContext context = 
  new AnnotationConfigApplicationContext(SpringJavaConfiguration.class);

or you can still use the original method, loading the application context from an XML file. In that case, you need to give a scope for which packages to look for the @Configuration annotation, by including this line:

<context:component-scan 
     base-package="com.wiley.javainterviewsexposed.chapter16"/>

The beauty of this method is that you can mix both annotated configuration and XML configuration. This may seem silly, and a potential nightmare to manage two different systems for managing dependencies, but it does give you the scope to migrate from one to the other at your own pace.


What are scopes?


On examination of Listing 16-6, you see that the dependency between the SpellCheckApplication and Dictionary is made explicit, by calling dictionary() in the constructor to the SpellCheckApplication class.

It is important to note here that a class defined with an @Configuration annotation is not an application context. It defines how that context is created and managed. This is exactly the same for the XML configuration, too. Taking any of the Spring-managed application contexts from this chapter, you can make multiple calls to getBean on the ApplicationContext instance, and it will always return the same instance. By default, Spring beans are created when the application context is instantiated, called eager instantiation. Additionally, only one instance of a Spring bean is created for a given definition. This is called singleton scope.

When a singleton bean is provided from the context, it is important to note that several concurrent threads may be using that instance at the same time. Therefore, it is very important that any operations are thread-safe.

It is possible for the application context to return a new instance on each invocation of getBean. Listing 16-7 shows such an example for a bean defined as <bean id="date" class="java.util.Date" scope="prototype"/>.

Listing 16-7: Using the prototype scope

@Test
public void differentInstanceScope() {
    final ApplicationContext context =
      new ClassPathXmlApplicationContext(
        "com/wiley/javainterviewsexposed/chapter16/applicationContext.xml");
    final Date date1 = context.getBean(Date.class);
    final Date date2 = context.getBean(Date.class);

    assertNotSame(date1, date2);
}

Having the context return a new instance of a bean on each call to getBean is called prototype scope.

Other scope types exist, too, such as request, where a bean lives for the life of a particular HTTP request, or session, where the bean lives for the life of the HTTP session.


How can environment-specific properties be set in a manageable way?


The class PropertyPlaceholderConfigurer is a simple and easy way to set properties external from a build. It is good practice to keep any environment-specific configuration outside of a regular build, and loaded at run time, rather than building a per-environment artifact for each of the environments you test for.


Rebuilding Your Application for Different Environments
Some applications are deployed to several environments for different rounds of testing, before eventually being released to a “production,” or “live” environment.
Sometimes, the configuration for each environment is pulled in to the application binary as part of the build, and is subsequently rebuilt for each environment. This is a risky approach, because this means that the actual compiled binary artifact you deploy to production is not the same one as was deployed to your test environments.
If you have your environment-specific configuration external to the build, and pulled in at run time using a PropertyPlaceholderConfigurer, it means that you are testing the exact binary artifact you will eventually deploy to your live environment. You have more confidence in your release, because you will not have introduced the risk of creating the binary in a different way for your live environment as to the other environments.
Indeed, if you compile one binary on your computer, and your colleague issues the same build instruction on his or her computer, these could differ in many ways, such as different compiler versions, different operating systems, or even different environment variables set.

Listing 16-8 is a sample application context, which uses the PropertyPlaceholderConfigurer, and then uses the properties to set up other Spring beans.

Listing 16-8: Using the PropertyPlaceholderConfigurer

<bean
 class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property
    name="location"
    value="/com/wiley/javainterviewsexposed/chapter16/environment.properties"/>
  <property name="placeholderPrefix" value="$property{"/>
  <property name="placeholderSuffix" value="}"/>
</bean>

<bean class="com.wiley.javainterviewsexposed.chapter16.ServerSetup">
  <constructor-arg value="$property{server.hostname}"/>
</bean>

The PropertyPlaceholderConfigurer class includes several useful properties. In Listing 16-8, the location property is set to a specific property file, and the class parses that file. The PropertyPlaceholderConfigurer expects the environment.properties file to hold the properties as key-value pairs.

This file is parsed on the startup of the application context, and these properties can be used as configuration parameters for other beans. The property in the file as server.hostname is used to create a ServerSetup bean.

It should be quite clear that, for this application, it is possible to change the values stored in environment.properties, restart the application, and the ServerSetup bean will be configured with a different value to its constructor. This is a simple but powerful way to separate environment-specific configuration from the actual code.


What is autowiring?


Autowiring is the process of letting the application context figure out the dependencies for you. If you are trying to construct a bean with dependencies, sometimes you do not need to explicitly define that link. Listing 16-9 and Listing 16-10 illustrate.

Listing 16-9: XML configuration for autowiring

<bean id="dictionary" class="com.wiley.javainterviewsexposed.chapter16.FileDictionary">
        <constructor-arg value="/usr/share/dict/words"/>
    </bean>

    <bean id="spellChecker"
          class="com.wiley.javainterviewsexposed.chapter16.SpellCheckApplication"
autowire="constructor"/>

Listing 16-10: Using autowiring

@Test
public void getAutowiredBean() {
    final ApplicationContext context = 
            new ClassPathXmlApplicationContext(
                    "com/wiley/javainterviewsexposed/" +
                            "chapter16/applicationContextAutowiring.xml");
    final SpellCheckApplication bean = 
            context.getBean(SpellCheckApplication.class);
    assertNotNull(bean);
}

The XML configuration has instructed the application context to find types that can be used in the constructor of the SpellCheckApplication class, that is, a class of type Dictionary. Because the only other class in this application context is a FileDictionary—an implementation of Dictionary—this is used to construct the SpellCheckApplication class.

Had there not been a Dictionary implementation in the context, an error would have been thrown when trying to construct the application context: NoSuchBeanDefinitionException.

Had there been multiple Dictionary beans, the context would have tried to match the beans by name, that is, match the name given by the ID in the XML definition to the name of the parameter in the constructor. If there were no match, an exception would be thrown; again, a NoSuchBeanDefinitonException.

Again, it cannot be stressed enough that if you are using the XML configuration approach, you must have a good suite of integration tests to ensure that your beans are constructed properly.

Listing 16-9 and Listing 16-10 illustrated a common pattern for everyday use of the Spring application context: using XML context to define the beans, and then autowiring to integrate these beans.

Another use of autowiring is to annotate dependency to be autowired. Listing 16-11 shows how this looks on the SpellCheckApplication constructor.

Listing 16-11: Using the @Autowired annotation on a constructor

@Autowired
public SpellCheckApplication (final Dictionary dictionary) {
    this.dictionary = dictionary;
}

Using the annotation in this way, you do not need to have an autowired attribute on the XML bean definition.

You can even autowire fields within a class, without a publicly accessible constructor or setter method. Listing 16-12 autowires the Dictionary instance on to a private field. There is no setter for the Dictionary in the class, and the constructor can be removed.

Listing 16-12: Using @Autowired on fields

@Autowired
private Dictionary dictionary;

Note that this field cannot be final anymore. The application context will access and set this field after it has been constructed, using reflection.

If your context contains more than one bean of the same type, you can still use the @Autowired annotation, but you need to be explicit as to which bean you mean. A second annotation, @Qualifier, is used for this. The annotation’s constructor takes a string, the name of the bean you require for wiring:

@Autowired
@Qualifier("englishDictionary")
private Dictionary dictionary;

These annotations are specific to Spring. Should you ever decide to change containers for a different provider, such as Google’s Guice, then, although the concepts for your application code do not change, you would need to re-implement your dependency injection and bean creation code to work with their implementation. A specification called JSR-330 worked to standardize the annotations across different providers. Instead of using @Autowired, you can use @Inject instead.


About Java Specification Requests (JSRs)
JSRs are requests from the Java development community, and other interested parties, to add new functionality to upcoming releases of the Java platform.
Past JSRs have included the introduction of the assert keyword in Java 1.4, the specification of the Java Message Service (JMS), and JavaServer Pages (JSPs).

However you decide to construct your beans and manage their dependencies, it is important to remain consistent. As your application grows, it can be hard to manage these dependencies if they are set up in several different ways, especially if you do not have good test coverage.

Spring JDBC


How does Spring improve the readability of JDBC code?


Listing 16-13 is an example of how to use JDBC using APIs shipped as part of the Java Development Kit. Database access and JDBC in general are covered in Chapter 12.

Listing 16-13: Using the JDK APIs for database access

@Test
public void plainJdbcExample() {
    Connection conn = null;
    PreparedStatement insert = null;
    PreparedStatement query = null;
    ResultSet resultSet = null;
    try {
        Class.forName("com.mysql.jdbc.Driver");

        conn = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/springtrans?" +
                "user=nm&" +
                "password=password");

        insert = conn.prepareStatement("insert into user values (?, ?)");

        final List<String> users = Arrays.asList("Dave", "Erica", "Frankie");

        for (String user : users) {
            insert.setString(1, UUID.randomUUID().toString());
            insert.setString(2, user);

            insert.executeUpdate();
        }

        query = conn.prepareStatement("select count(*) from user");
        resultSet = query.executeQuery();

        if (!resultSet.next()) {
            fail("Unable to retrieve row count of user table");
        }

        final int rowCount = resultSet.getInt(1);

        assertTrue(rowCount >= users.size());
    } catch (ClassNotFoundException | SQLException e) {
        fail("Exception occurred in database access: " + e.getMessage());
    } finally {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
            if (query != null) {
                query.close();
            }
            if (insert != null) {
                insert.close();
            }
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            fail("Unable to close Database connection: " + e.getMessage());
        }
    }
}

The prevalent matter in this listing is how much code is necessary to insert some data, and verify that the data is there. All of the heavyweight classes needed for database access, such as Connection, PreparedStatement, and ResultSet can all throw checked SQLExceptions on their creation, use, and destruction. These exceptions cannot simply be ignored: Should a close method throw a SQLException, then that connection to the database may still exist. If this happens several times, all of the connections in the database connection pool will be in use, and any subsequent requests for database access will fail, bringing your entire application to a messy halt.

So using the java.sql.* classes results in a pattern of surrounding all your database access in a try block, and closing the database statements, result sets, and connections inside a finally block. But because these close statements inside the finally block can fail too, they need to be in a try block. If that close fails, there isn’t really much you can do, besides being aware that it has happened, and manually killing the database connection to the running program.

Moreover, because the database resource objects need to be initialized inside the try block but closed inside the finally block, the reference variables cannot be assigned as final variables, which runs the risk (through programming error) of reassigning to these variables before any chance of calling their close method.

Thankfully, Spring provides some utilities for taking care of some of this boilerplate approach. Listing 16-14 provides an alternative finally block for Listing 16-13.

Listing 16-14: A friendlier way to close database resources

try {
    // as Listing 16-13
} catch (ClassNotFoundException | SQLException e) {
    // as Listing 16-13
} finally {
    JdbcUtils.closeResultSet(resultSet);
    JdbcUtils.closeStatement(query);
    JdbcUtils.closeStatement(insert);
    JdbcUtils.closeConnection(conn);
}

You are encouraged to take a look at the implementation of these utility functions. They contain the same code as the finally block in Listing 16-13, but throw no checked exceptions. This is a huge reduction in necessary boilerplate code; they make your own code shorter and much easier to read and reason what is happening.

The JdbcUtils class provides some other useful functions, too, such as extracting results from a ResultSet, or even converting from a database naming convention (that is, separated_by_underscores) to Java’s naming convention (definedWithCamelCase).

Using the try-with-resources statement, introduced in Java 8 and discussed in Chapter 8, can also reduce the boilerplate code here, however you must still have a catch block for a SqlException, as that can be thrown when creating the resource.


How can Spring remove most boilerplate JDBC code?


The JdbcUtils class is intended for use as an enhancement to plain old JDBC code. If you are starting any new development in Java code that needs JDBC access, you should use Spring’s JdbcTemplate.

Spring’s approach to using JDBC abstracts much of the necessary setup to your application context, and therefore removes it from polluting any program logic. Once the template is set up, for executing queries, for instance, you only need to provide functionality for converting each row from a ResultSet to a specific domain object. As its name suggests, this is an application of the Template design pattern, which was covered in a more abstract sense in Chapter 6.

Listing 16-15 and Listing 16-16 show how the JdbcTemplate can be used for everyday database manipulations.

Listing 16-15: Configuring a database in an application context

<bean id="dataSource"
      class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/springtrans" />
    <property name="username" value="nm" />
    <property name="password" value="password" />
</bean>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <constructor-arg ref="dataSource"/>
</bean>

Listing 16-16: Using the SimpleJdbcTemplate

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
        "classpath:com/wiley/javainterviewsexposed /chapter16/jdbcTemplateContext.xml")
public class JdbcTemplateUsage {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Test
    public void retrieveData() {
        final int rowCount = 
                jdbcTemplate.queryForInt("select count(*) from user");

        final List<User> userList = jdbcTemplate.query(
                "select id, username from user", 
                new RowMapper<User>() {
                    
            @Override
            public User mapRow(ResultSet rs, int rowNum) throws SQLException {
                return new User(rs.getString("id"), rs.getString("username"));
            }
        });

        assertEquals(rowCount, userList.size());
    }

}

This code accesses the database twice. The method queryForInt expects the given query to return one row, with one column, and the type of that column is some kind of numerical type, which can be interpreted as an int. Therefore, you do not need to worry about creating a statement, performing the query, and obtaining the ResultSet, making sure the ResultSet has one row and one column, and closing all resources afterwards.

The second query shows a slightly more complex approach, where each row in the database is translated into a User domain object. The template is able to perform the query and iterate over the results. The only thing it does not know how to do is to transform each row into the object you desire. You provide an anonymous implementation of the RowMapper interface, and the mapRow is called for each row in the database. You have access to the data and metadata (by calling the method ResultSet.getMetaData), and also the row number.

Each object returned from the mapRow call is collected by the template and collated in a List of those mapped instances.


Using the JdbcTemplate in Java 8
Because the RowMapper interface has only one method, this fits nicely with the new Lambda functionality, which should appear in Java 8 (see the section “Looking Forward to Java 8” in Chapter 8). This will make the query method even clearer and more concise than it already is:
jdbcTemplate.query(queryString, (rs, rowNum) -> {
    return new User(rs.getString(“id”), rs.getString(“username”));
});
This requires no change to any Spring library code.

Again, you do not need to deal with opening database connections or any of the heavy database resource objects, and you do not need to close any resources after your query—the template does all this for you. It should be clear that this code is more concise, clearer, and much more maintainable than the approach shown earlier in Listing 16-13.

Integration Testing


How do you test that an application context is configured correctly?


In the earlier section on using the application context, having to load the ApplicationContext object manually for each test was becoming unwieldy and distracting, taking the focus away from the test.

Spring has a good integration for using application contexts in integration tests. Listing 16-17 revisits the spell-checking application, showing how Spring helps write integration tests.

Listing 16-17: Using Spring’s integration testing

@ContextConfiguration(
  "classpath:com/wiley/javainterviewsexposed/chapter16/applicationContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringIntegrationTest {

    @Autowired
    private SpellCheckApplication application;


    @Test
    public void checkWiring() {
        assertNotNull(application);
    }

    @Test
    public void useSpringIntegrationTests() {

        final List<String> words = Arrays.asList(
                "correct", 
                "valid", 
                "dfgluharg", 
                "acceptable");
        final List<Integer> expectedInvalidIndices = Arrays.asList(2);

        final List<Integer> actualInvalidIndices =
                                      application.checkDocument(words);

        assertEquals(expectedInvalidIndices, actualInvalidIndices);
    }
}

The class is annotated to run with the SpringJUnit4ClassRunner, which understands how to load a Spring application context through the @ContextConfiguration class-level annotation.

Running tests this way allows the beans under test to be autowired for use in a particular test. Any @Autowired beans are reloaded from the application context for each test; similar to the way the @Before annotated methods are run before each test.

If you have a sufficiently complex test, which may change the state of the application context, you can annotate your class with @DirtiesContext, and this will reload the whole context from scratch for each test. This can significantly increase the running time for all the tests in a defined test suite.


How do you keep databases clean when running integration tests?


The Spring integration testing functionality has a remarkably useful feature for working with databases and transactions. If you have a JUnit test suite, which extends AbstractTransactionalJUnit4SpringContextTests, then each of the tests run inside this suite will be run inside a database transaction, and will be rolled back at the end of each test.

This has the useful capability to check that your code meets any requirements specified by your database, such as referential integrity, or any complex knock-on effects such as those specified in a database trigger. Listing 16-18 shows a test that appears to insert data into a database. The test will fail if the precondition of any of the usernames to insert is already in the database.

Listing 16-18: Using Spring’s transactional support for integration tests

@ContextConfiguration(
  "classpath:com/wiley/javainterviewsexposed/" +
          "chapter16/databaseTestApplicationContext.xml")
 public class SpringDatabaseTransactionTest extends 
                             AbstractTransactionalJUnit4SpringContextTests {

    private int rowCount;

    @Before
    public void checkRowsInTable() {
        this.rowCount = countRowsInTable("user");
    }

    @Before
    public void checkUsersForTestDoNotExist() {
        final int count = this.simpleJdbcTemplate.queryForInt(
                "select count(*) from user where username in (?, ?, ?)",
                "Alice",
                "Bob",
                "Charlie");
        assertEquals(0, count);
    }

    @Test
    public void runInTransaction() {

        final List<Object[]> users = Arrays.asList(
                new Object[]{UUID.randomUUID().toString(), "Alice"},
                new Object[]{UUID.randomUUID().toString(), "Bob"},
                new Object[]{UUID.randomUUID().toString(), "Charlie"}
        );

        this.simpleJdbcTemplate.batchUpdate(
                "insert into user values (?, ?)", users);

        assertEquals(rowCount + users.size(), countRowsInTable("user"));
    }
}

Before any of the @Before methods are run, a transaction is opened. Once the test has been run, and all of the @After methods have completed, the transaction is rolled back, as if the data had never been there. Naturally, you need to make sure that none of your code in the @Test method performs a commit.

Had this test been run outside of a transaction, it would fail on its second run, due to the insertion of the usernames Alice, Bob, and Charlie. But because the insertion is rolled back, it can be run time and time again with no fear of the data persisting. This makes it suitable for running as part of a regular application build, or as part of a set of integration tests, run on a continuous delivery server.

JUnit 4.11 introduced the @FixMethodOrder annotation, which allows you to define the order your @Test methods are run. In Listing 16-18, you could write another test that double-checks that the transaction had indeed been rolled back and the users did not exist in the table, and have that test run after the runInTransaction test.

Specifying the order of tests is bad practice, as you should be able to run each test in isolation. If this test was run on a continuous delivery server, and there was a problem with the transaction rollback, then the test would fail on its second run, which would be early in the development cycle if you have a regular running build.

By extending AbstractTransactionalJUnit4SpringContextTests, and providing an application context with a valid DataSource, the integration test suite gives you access to a SimpleJdbcTemplate object, with which you can perform any relevant database operations for your test. The test suite also provides a couple of utility methods: countRowsInTable and deleteFromTables.

Spring MVC

The Model-View-Controller (MVC) pattern is a common approach to working with user interfaces. As its name implies, it breaks up an application into three parts.

The model is a representation of the data your application is trying to work with.

The view presents the user with a representation of this model. Depending on the nature of the application, this could simply be text on a screen, or perhaps a more complicated visualization using graphics and animation.

The controller joins everything up. It is responsible for processing any input, which will govern how the model is created, and then it passes this model on to an appropriate view.

This section demonstrates how Spring’s web applications use this pattern to provide a clean separation between these three parts and how they fit together, building a small web application for displaying sports results. Listing 16-19 shows the interface to the sports results service.

Listing 16-19: The SportsResultsService interface

public interface SportsResultsService {
    List<Result> getMostRecentResults();
}

How does Spring serve web applications?


Spring’s MVC framework is designed to be compatible with the Java Servlet specification. Many providers and vendors of applications use this specification, such as freely available Apache Tomcat, and Jetty, and also commercial implementations like IBM’s Websphere Application Server. All of these can be used with Spring MVC.

When the application server starts, it looks for the file web.xml, in the META-INF package on the classpath. This file specifies what applications, or servlets, the server will provide. Inside web.xml you provide a class that extends HttpServlet, and that defines how to respond to the HTTP methods such as GET and POST.

Although you can provide your own implementation, to use Spring MVC, you use its implementation, org.springframework.web.servlet.DispatcherServlet. Listing 16-20 gives a complete definition of a sample web.xml file, passing any request starting with /mvc to the DispatcherServlet.

Listing 16-20: Configuring a servlet container for Spring MVC

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
                    http://java.sun.com/xml/ns/javaee 
                    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
        metadata-complete="false"
        version="3.0">

    <servlet>
        <servlet-name>mvc</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc</servlet-name>
        <url-pattern>/mvc/*</url-pattern>
    </servlet-mapping>

</web-app>

When control is passed to the DispatcherServlet, it immediately looks for an application context XML definition, which is held at the classpath location WEB-INF/[servlet-name]-servlet.xml. For Listing-16-20, it will be called mvc-servlet.xml.

This file is a regular, familiar, Spring application context. You can specify any Spring beans here, and they will be instantiated when the server starts. Listing 16-21 is a very simple application context.

Listing 16-21: An application context for a sample Spring MVC application

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan 
            base-package="com.wiley.javainterviewsexposed.chapter16.mvc"/>

    <bean id="freemarkerConfig" 
          class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        <property name="templateLoaderPath" value="/WEB-INF/freemarker/"/>
    </bean>

    <bean 
         id="viewResolver"
         class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
        <property name="prefix" value=""/>
        <property name="suffix" value=".ftl"/>
    </bean>

    <bean 
      class="com.wiley.javainterviewsexposed.chapter16.mvc.DummySportsResultsService"/>

</beans>

There are three main actions here. Most Spring MVC controllers are defined using annotations, so the context:component-scan tag informs the application context of which packages to scan for classes annotated with @Controller. There is the setup of the view resolver, which is used to render and display the results of any request; Spring MVC will request the bean of type ViewResolver when it needs to display the output of a request. Finally, this application has one application-specific bean, an instance of DummySportsResultsService.

This is just a regular application context. You can use it outside of an MVC application if you need to, such as with Spring’s integration testing framework.


How can you create easily testable web controllers with Spring MVC?


Controllers in Spring are lightweight, Plain Old Java Objects. By having very few dependencies, they have been designed to be easily testable, and the framework gives many options for their behavior to fit in with your way of working. Listing 16-22 is the simple example for Spring’s controllers in its MVC framework.

Listing 16-22: A simple Spring controller

@Controller
@RequestMapping("/results")
public class ResultsController {

    private final SportsResultsService resultsService;

    @Autowired
    public ResultsController(final SportsResultsService resultsService) {
        this.resultsService = resultsService;
    }

    @RequestMapping(value = "/recent")
    public String getMostRecentResults(final Model model) {
        model.addAttribute("results", resultsService.getMostRecentResults());
        return "resultsView";
    }

    @RequestMapping("/recent/{team}")
    public String getMostRecentResultsForTeam(
            @PathVariable("team") final String team,
            final Model model) {
        final List<Result> results = resultsService.getMostRecentResults();
        final List<Result> resultsForTeam = new ArrayList<Result>();
        for (Result result : results) {
            if (Arrays.asList(
                    result.getHomeTeam(), 
                    result.getHomeTeam()
               ).contains(team)) {
                resultsForTeam.add(result);
            }
        }

        if (resultsForTeam.isEmpty()) {
            return "teamNotFound";
        } else {
            model.addAttribute("results", resultsForTeam);
            return "resultsView";
        }
    }

}

This controller provides GET access to two URLs, /results/recent and /results/recent/<team>, for a specific team.

Before looking at the mechanics of how this controller integrates with a servlet engine, it should be clear that this class is easily testable as a unit test. Listing 16-23 shows a test for the method getMostRecentResultsForTeam.

Listing 16-23: A unit test for the ResultsController

@Test
public void specificTeamResults() throws Exception {
    final SportsResultsService mockService = mock(SportsResultsService.class);

    final List<Result> results = Arrays.asList(
            new Result("Home", "Away", 1, 2),
            new Result("IgnoreHome1", "IgnoreAway1", 0, 0)
    );

    when(mockService.getMostRecentResults()).thenReturn(results);

    final List<Result> expectedResults = Arrays.asList(
                                   new Result("Home", "Away", 1, 2));

    final ResultsController controller = new ResultsController(mockService);
    final Model model = new ExtendedModelMap();

    controller.getMostRecentResultsForTeam("Home", model);

    assertEquals(expectedResults, model.asMap().get("results"));
}

Examining Listing 16-22, the class is annotated with the @Controller annotation, so the component-scan directive in the servlet’s application context picks it up.

This controller is specific for any URL starting in /results, so that, too, can be annotated at the class level, with the @RequestMapping annotation. Any method-level @RequestMapping annotations will be relative to this.

The getMostRecentResultsForTeam method has a parameter annotated with @PathVariable, given the value team. This value corresponds to the {team} binding in the @RequestMapping annotation. This allows for a RESTful approach if you so wish; it is very simple to parameterize your request URLs. This is type-safe too; Spring can interpret the value as any simple type, such as the primitive types Strings and Dates, and it is possible for you to provide your own conversion from the String in the request path to your own complex type.

Methods on controllers have the single role of providing the view technology with the model to render.

The two methods have similar signatures. Both take at least one parameter, of a Model object, and both return Strings.

The Model parameter is passed to the controller method by the framework. At its core, the Model object is a mapping from Strings to Objects. The controller performs the necessary work, such as retrieving data from a service accessing a database or third-party web application, and populates the given Model. Remember, Java objects are references, so the framework can still reference the model instance after you have updated it, meaning you do not need to return your updated model from the method.

This allows the method to return another necessary component, the name of the view to render. You have the ability to configure Spring’s MVC framework so that it understands how to map a String to a particular view; look ahead to the next question for how this works.

To allow for as much flexibility as possible, and to fit with your own preference of how to define your own controller, the Spring MVC framework understands many different configurations for your method definition. You can specify several annotations on the method parameters, such as @RequestPart, for multipart form uploads, or @RequestHeader, for assigning a specific header to a variable.

You can also specify many different parameter types for the method signature, including:

  • InputStream, providing access to the raw HTTP request stream
  • OutputStream, allowing you to write directly to the HTTP response stream
  • HttpServletRequest, for the exact request object itself
  • ServletResponse, another facility for writing directly to the response

Additionally, you have several options for your return type, such as ModelAndView, an object containing both the model for the view and the view name, all contained in one object. You can even use a void return type if you have written directly to the response stream.


Be Smart: Keep Your Code Simple and Easy to Test
Remember to use tests as often as you can in any interview situation. Like all Java classes, it is advisable to keep your controllers simple and easily testable. It can be quite difficult to create testable controller methods if you are writing directly to the response output stream, and your method has a void return type.


How is the server-side logic kept separate from presenting the results of a request?


Views are how the work done by the controller, represented by the model, is displayed.

The view should simply be displaying the output; the controller should have done all meaningful work before passing the model to the view. This includes operations such as sorting lists or filtering any unwanted content from a data structure.

In essence, most view technologies that work with Spring follow a very similar pattern: They work as templates, with placeholders for dynamic data. Spring integrates tightly with several implementations so that their own integration with Spring’s controllers stays the same.

The usual format is for the controller to populate a mapping, consisting of a name to either a “bean” or data structure. For the bean, the properties, defined on the Java class by getXXX methods, are then directly accessible in the view technology. For data structures, such as a Map or List, the template provides ways to iterate over the collection and access each element, again as a bean. Listing 16-24 is a very simple controller, and Listing 16-25 is a possible view for displaying that data. The view implementation here is called Freemarker.

Listing 16-24: A simple controller for use with Listing 16-25

@RequestMapping("/planets")
public String createSimpleModel(final Model model) {

    model.addAttribute("now", new Date());

    final Map<String, String> diameters = new HashMap<>();
    diameters.put("Mercury", "3000 miles");
    diameters.put("Venus", "7500 miles");
    diameters.put("Earth", "8000 miles");

    model.addAttribute("diameters", diameters);

    return "diameters";
}

Listing 16-25: Using a view template to display the output from a controller

<html>
<head>
    <title>Planet Diameters</title>
</head>
<body>
<#list diameters?keys as planet>
    <b>${planet}</b>: ${diameters[planet]}<br/>
</#list>
This page was generated on <i>${now?datetime}</i>
</body>
</html>

The controller has added two elements to the model: now, a representation of the current time, and diameters, the map of planet names to a description of their diameter.

Listing 16-25 is written as HTML, with slots for the dynamic content to fit. This has several advantages, including a clear separation between the server-side processing and the front-end display. Also, notice that the template is not restricted to HTML: Anything at all could have been displayed, perhaps an XML or comma-separated values (CSV) document, or even a template for use in an e-mail.

The <#list> tag is known as a macro; Freemarker has many of these for different situations. It is being used here to iterate through the keys in the diameters map. Other examples include bool?string("yes", "no"), which is used to map the value bool onto one of two strings; yes or no, and number?round, which will display a rounded version of the value number.


How can Spring be configured to work with different view template engines?


Listing 16-25 uses the Freemarker engine. The controller in Listing 16-24 references the view by the name diameters. The mapping from name to template file is set up in the application context, and is highly dependent on the implementation of ViewResolver. For this application, which was originally set up in Listing 16-21, the view resolver was set as:

<bean id="viewResolver"
 class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
    <property name="prefix" value=""/>
    <property name="suffix" value=".ftl"/>
</bean>

This specifies that the view template files are stored in the default location, and have the file extension .ftl. When using Freemarker, the diameters view should be found on the classpath as /WEB-INF/freemarker/diameters.ftl.

A similar, older view technology is Velocity, and Spring’s view resolver bean uses similar bean properties:

<bean id="viewResolver"
 class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
    <property name="prefix" value=""/>
    <property name="suffix" value=".vm"/>
</bean>

Convention follows that Velocity templates have a .vm suffix.

Summary

Whatever parts of Spring you do and do not use, the core concept for most approaches is the use of the application context. Understanding dependency injection and how components fit together is extremely important, and any interview involving Spring will cover Spring beans, how they are created, and how they interact among themselves.

This chapter has not been an exhaustive look at the Spring Framework. Do take the time to write some code with Spring, and see how the concepts here translate to other parts, such as how to interact with Hibernate using the HibernateTemplate, or how the application context is used in more complicated scenarios with Spring Integration.

Make sure that anything you write in Spring is tested, especially if you are configuring your applications in XML. Spring gives you good support for creating comprehensive tests. Eclipse or IntelliJ have good plug-ins for Spring; they can often highlight any errors in Spring configuration straight away—this may not always be apparent until you run the code and attempt to construct the application context.

Chapter 17 covers Hibernate, a framework that is often paired with Spring. Hibernate enables you to convert database tables directly into a Java object, and vice-versa. The chapter looks at the basics of Hibernate’s different approaches that you can take to configure and use it.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.176.72