This chapter is taken from the book - Getting started with Spring Framework, 4th Edition (https://www.amazon.com/dp/1979962782/). You can download the code for the book from here: https://github.com/getting-started-with-spring/4thEdition

Chapter 1 – Introduction to Spring Framework

1-1 Introduction
In the traditional Java enterprise application development efforts, it was a developer’s responsibility to create well-structured, maintainable and easily testable applications. The developers used myriad design patterns to address these non-business requirements of an application. This not only led to low developer productivity, but also adversely affected the quality of developed applications.

Spring Framework (or ‘Spring’ in short) is an open source application framework that simplifies developing Java enterprise applications. It provides the infrastructure for developing well-structured, maintainable and easily testable applications. When using Spring Framework, a developer only needs to focus on writing the business logic of the application, resulting in improved developer productivity. You can use Spring Framework to develop standalone Java applications, web applications, applets, or any other type of Java application. You can visit the home page of Spring Framework project (https://projects.spring.io/spring-framework/) to view the reference documentation and APIs.

This chapter starts off with an introduction to Spring Framework modules and its benefits. At the heart of Spring Framework is its Inversion of Control (IoC) container, which provides dependency injection (DI) feature. This chapter introduces Spring’s DI feature and IoC container, and shows how to develop a standalone Java application using Spring. Towards the end of this chapter, we’ll look at the new features and enhancements that form part of Spring Framework 5 release. We’ll wrap this chapter up by looking at some of the projects that use Spring Framework as their foundation. This chapter will set the stage for the remaining chapters that delve deeper into the Spring Framework.

In this book, we’ll use an example Internet Banking application, MyBank, to introduce Spring Framework features.

1-2 Spring Framework modules
Spring Framework consists of multiple modules that are grouped based on the application development features they address. The following table describes the different module groups in Spring Framework and specifies the purpose served by some of the important modules in these groups:

Spring Framework 5 no longer supports developing portlet applications. If you want to develop portlet applications using Spring, stick to Spring Framework 4.3.x.

The above table shows that Spring covers every aspect of enterprise application development; you can use Spring for developing web applications, accessing databases, managing transactions, creating unit and integration tests, and so on. The Spring Framework modules are designed in such a way that you only need to include the modules that your application needs. For instance, to use Spring’s DI feature in your application, you only need to include the modules grouped under Core container. As you progress through this book, you’ll find more details about various Spring modules and examples that show how they are used in developing applications.

The naming convention followed by the JAR files in a Spring Framework distribution is:

spring-<short-module-name>-<spring-version>.jar.

here, <short-module-name> is the short name of the Spring module, like aop, beans, context, expressions, and so on. And, the <spring-version> is the Spring Framework version.
Following this naming convention, the names of JAR files in Spring 5.0.1.RELEASE are: spring-aop-5.0.1.RELEASE.jar, spring-beans-5.0.1.RELEASE.jar, and so on.

Figure 1-1 shows the inter-dependencies of Spring modules. You can infer from the figure that the modules contained in the Core container group are central to the Spring Framework, and other modules depend on it. Equally important are the modules contained in the AOP and instrumentation group because they provide AOP features to other modules in the Spring Framework.

Figure 1-1 Spring modules inter-dependencies

Now that you have some basic idea about the areas of application development covered by Spring, let’s look at the Spring IoC container.

1-3 Spring IoC container

A Java application consists of objects that interact with each other to provide application behavior. The objects with which an object interacts are referred to as its dependencies. For instance, if an object X interacts with objects Y and Z, then Y and Z are dependencies of object X. DI (short for 'Dependency Injection') is a design pattern in which the dependencies of an object are typically specified as arguments to its constructor and setter methods. And, these dependencies are injected into the object when it’s created.

In a Spring application, Spring IoC container (also referred to as 'Spring container') is responsible for creating application objects and injecting their dependencies. The application objects that the Spring container creates and manages are referred as beans. As the Spring container is responsible for putting together application objects, you don’t need to implement design patterns, like Factory, Service Locator, and so on, to compose your application. DI is also referred to as Inversion of Control (IoC) because the responsibility of creating and injecting dependencies is not with the application object, but with the Spring container.

Let’s say that the MyBank application (which is the name of our sample application) contains two objects, FixedDepositController and FixedDepositService. The following example listing shows that the FixedDepositController object depends on FixedDepositService object:

Example listing 1-1: FixedDepositController class
public class FixedDepositController {
    private FixedDepositService fixedDepositService;

    public FixedDepositController() {
        fixedDepositService = new FixedDepositService();
    }
    public boolean submit() {
       //-- save the fixed deposit details
        fixedDepositService.save(.....);
    }
}

In the above example listing, FixedDepositController’s constructor creates an instance of FixedDepositService which is later used in FixedDepositController’s submit method. As FixedDepositController interacts with FixedDepositService, FixedDepositService represents a dependency of FixedDepositController.

To configure FixedDepositController as a Spring bean, you first need to modify the FixedDepositController class of example listing 1-1 such that it accepts FixedDepositService dependency as a constructor argument or as a setter-method argument. The following example listing shows the modified FixedDepositController class:

Example listing 1-2: FixedDepositController class FixedDepositService is passed as a constructor argument
public class FixedDepositController {
    private FixedDepositService fixedDepositService;
    public FixedDepositController(FixedDepositService 
          fixedDepositService) {
        this.fixedDepositService = fixedDepositService;
    }
   
    public boolean submit() {
       //-- save the fixed deposit details
      fixedDepositService.save(.....);
    }
}

The above example listing shows that the FixedDepositService instance is now passed as a constructor argument to the FixedDepositController instance. Now, the FixedDepositController class can be configured as a Spring bean. Notice that the FixedDepositController class doesn’t implement or extend from any Spring interface or class.

In Spring-based applications, information about application objects and their dependencies is specified using configuration metadata. Spring IoC container reads application’s configuration metadata to instantiate application objects and inject their dependencies. The following example listing shows the configuration metadata (in XML format) for MyBank application that consists of FixedDepositController and FixedDepositService classes:

Example listing 1-3: MyBank application’s configuration metadata
<beans .....>
    <bean id="fdController" 
           class="sample.spring.controller.FixedDepositController">
        <constructor-arg ref="fdService" />
    </bean>

    <bean id="fdService"             
        class="sample.spring.service.FixedDepositService"/>
</beans>

In the above example listing, each <bean> element defines an application object that is managed by the Spring container, and the <constructor-arg> element specifies that an instance of FixedDepositService is passed as an argument to FixedDepositController’s constructor. The <bean> element is discussed in detail later in this chapter, and the <constructor-arg> element is discussed in chapter 2.

Spring container reads the configuration metadata (like the one shown in example listing 1-3) of an application and creates the application objects defined by <bean> elements and injects their dependencies. Spring container makes use of Java Reflection API (http://docs.oracle.com/javase/tutorial/reflect/index.html) to create application objects and inject their dependencies. The following figure summarizes how the Spring container works:
Figure 1-2 Spring container reads application’s configuration metadata and creates a fully-configured application
The configuration metadata can be supplied to the Spring container via XML (as shown in example listing 1-3), Java annotations (refer chapter 6) and programmatically through the Java code (refer chapter 7).
As the Spring container is responsible for creating and managing application objects, enterprise services (like transaction management, security, remote access, and so on) can be transparently applied to the objects by the Spring container. The ability of the Spring container to enhance the application objects with additional functionality makes it possible for you to model your application objects as simple Java objects (also referred to as POJOs or Plain Old Java Objects). Java classes corresponding to POJOs are referred to as POJO classes, which are nothing but Java classes that don’t implement or extend framework-specific interfaces or classes. The enterprise services, like transaction management, security, remote access, and so on, required by these POJOs are transparently provided by the Spring container.
Now that we know how Spring container works, let’s look at some examples that demonstrate benefits of developing applications using Spring.

1-4 Benefits of using Spring Framework

In the previous section, we discussed the following benefits of using Spring:
>  Spring simplifies composing Java applications by taking care of creating application objects and injecting their dependencies
>  Spring promotes developing applications as POJOs

Spring also simplifies interaction with JMS providers, JNDI, MBean servers, email servers, databases, and so on, by providing a layer of abstraction that takes care of the boilerplate code.
Let’s take a quick look at a few examples to better understand the benefits of developing applications using Spring.

Consistent approach to managing local and global transactions

If you are using Spring for developing transactional applications, you can use Spring’s declarative transaction management support to manage transactions.

The following example listing shows the FixedDepositService class of MyBank application:

Example listing 1-4FixedDepositService class
public class FixedDepositService {
    public FixedDepositDetails getFixedDepositDetails( ..... ) { ..... }
    public boolean createFixedDeposit(FixedDepositDetails 
      fixedDepositDetails) { ..... }
}

FixedDepositService class is a POJO class that defines methods to create and retrieve details of fixed deposits. The following figure shows the form for creating a new fixed deposit:
Figure 1-3 HTML form for creating a new fixed deposit
A customer enters the fixed deposit amount, tenure and email id information in the above form and clicks the SAVE button to create a new fixed deposit. The FixedDepositService’s createFixedDeposit method (refer example listing 1-4) is invoked to create the fixed deposit. The createFixedDeposit method debits the amount entered by the customer from his bank account and creates a fixed deposit of the same amount.

Let’s say that information about the bank balance of customers is stored in BANK_ACCOUNT_DETAILS database table, and the fixed deposit details are stored in FIXED_DEPOSIT_DETAILS database table. If a customer creates a fixed deposit of amount x, amount x is subtracted from the BANK_ACCOUNT_DETAILS table, and a new record is inserted in FIXED_DEPOSIT_DETAILS table to reflect the newly created fixed deposit. If BANK_ACCOUNT_DETAILS table is not updated or a new record is not inserted in FIXED_DEPOSIT_DETAILS table, it’ll leave the system in an inconsistent state. This means the createFixedDeposit method must be executed within a transaction.

The database used by the MyBank application represents a transactional resource. In the traditional approach to perform a set of database modifications as a single unit of work, you’ll first disable auto-commit mode of JDBC connection, then execute SQL statements, and finally commit (or rollback) the transaction. The following example listing shows the createFixedDeposit method that uses the traditional approach to managing database transactions:

Example listing 1-5 – Programmatically managing database transactions using JDBC Connection object
import java.sql.Connection;
import java.sql.SQLException;

public class FixedDepositService {
      public FixedDepositDetails getFixedDepositDetails( ..... ) { ..... }
     
      public boolean createFixedDeposit(FixedDepositDetails 
          fixedDepositDetails) { 
          Connection con = ..... ;
          try {
              con.setAutoCommit(false);
             //-- execute SQL statements that modify database tables
              con.commit();
          } catch(SQLException sqle) {
              if(con != null) {
                  con.rollback();
              }
          }
          .....
      }
}
The above example listing shows that the createFixedDeposit method programmatically manages database transactions using JDBC Connection object. Transactions that are resource-specific, like the transactions associated with a JDBC Connection object, are referred to as local transactions.

The approach of using JDBC Connection object to manage transactions is suitable for application scenarios in which a single database (that is, a single transactional resource) is involved. When multiple transactional resources are involved, JTA (Java Transaction API) is used for managing transactions. For instance, if you want to send a JMS message to a messaging middleware (a transactional resource) and update a database (another transactional resource) in the same transaction, you must use a JTA transaction manager to manage transactions. JTA transactions are also referred to as global (or distributed) transactions. To use JTA, you fetch UserTransaction object (which is part of JTA API) from JNDI and programmatically start and commit (or rollback) transactions.

As you can see, you can either use JDBC Connection (for local transactions) or UserTransaction (for global transactions) object to programmatically manage transactions. It is important to note that a local transaction cannot run within a global transaction. This means that if you want database updates in createFixedDeposit method (refer example listing 1-5) to be part of a JTA transaction, you need to modify the createFixedDeposit method to use the UserTransaction object for transaction management.
Spring simplifies transaction management by providing a layer of abstraction that gives a consistent approach to managing both local and global transactions. This means that if you write the createFixedDeposit method (refer example listing 1-5) using Spring’s transaction abstraction, you don’t need to modify the method when you switch from local to global transaction management, or vice versa. Spring’s transaction abstraction is explained in chapter 8.

Declarative transaction management

Spring gives you the option to use declarative transaction management. You can annotate a method with Spring’s @Transactional annotation and let Spring handle transactions, as shown here:

Example listing 1-6 @Transactional annotation usage
import org.springframework.transaction.annotation.Transactional;

public class FixedDepositService {
    public FixedDepositDetails getFixedDepositDetails( ..... ) { ..... }

    @Transactional
    public boolean createFixedDeposit(FixedDepositDetails 
         fixedDepositDetails) { ..... }
}
The above example listing shows that the FixedDepositService class doesn’t implement or extend from any Spring-specific interface or class to use Spring’s transaction management facility. The Spring Framework transparently provides transaction management feature to @Transactional annotated createFixedDeposit method. This shows that Spring is a non-invasive framework because it doesn’t require your application objects to be dependent upon Spring-specific classes or interfaces. As transaction management is taken care by Spring, you don’t need to directly work with transaction management APIs to manage transactions.

Security

Security is an important aspect of any Java application. Spring Security (http://projects.spring.io/spring-security/) is a project that is built on top of Spring Framework. Spring Security provides authentication and authorization features that you can use for securing Java applications.

Let’s say that the following 3 user roles have been identified for the MyBank application: LOAN_CUSTOMER, SAVINGS_ACCOUNT_CUSTOMER and APPLICATION_ADMIN. A customer must be associated with the SAVINGS_ACCOUNT_CUSTOMER or the APPLICATION_ADMIN role to invoke the createFixedDeposit method of FixedDepositService class (refer example listing 1-6). Using Spring Security you can easily address this requirement by annotating createFixedDeposit method with Spring Security’s @Secured annotation, as shown in the following example listing:

Example listing 1-7 – Secured createFixedDeposit method
import org.springframework.transaction.annotation.Transactional;
import org.springframework.security.access.annotation.Secured;

public class FixedDepositService {
    public FixedDepositDetails getFixedDepositDetails( ..... ) { ..... }

    @Transactional
    @Secured({ "SAVINGS_ACCOUNT_CUSTOMER", "APPLICATION_ADMIN" })
    public boolean createFixedDeposit(FixedDepositDetails fixedDepositDetails) { ..... }
}
If you annotate a method with Spring Security’s @Secured annotation, security feature is transparently applied to the method by the Spring Security framework. The above example listing shows that for implementing method-level security you don’t need to extend or implement any Spring-specific classes or interfaces. Also, you don’t need to write security-related code in your business methods.

Spring Security framework is discussed in detail in chapter 16.

JMX (Java Management Extensions)

Spring’s JMX support simplifies incorporating JMX technology in your applications.
Let’s say that the fixed deposit facility of MyBank application should only be available to customers from 9:00 AM to 6:00 PM every day. To address this requirement, a variable is added to the FixedDepositService class, which acts as a flag indicating whether the fixed deposit service is active or inactive. The following example listing shows the FixedDepositService class that uses such a flag:

Example listing 1-8 FixedDepositService with active variable
public class FixedDepositService {
    private boolean active;
  
    public FixedDepositDetails getFixedDepositDetails( ..... ) {
        if(active) { ..... }
    }
    public boolean createFixedDeposit(FixedDepositDetails 
           fixedDepositDetails) {
        if(active) { ..... }
    }
    public void activateService() {
        active = true;
    }
    public void deactivateService() {
        active = false;
    }
}
The above example listing shows that a variable named active is added to the FixedDepositService class. If the value of the active variable is true, the getFixedDepositDetails and createFixedDeposit methods work as expected. If the value of the active variable is false, the getFixedDepositDetails and createFixedDeposit methods throw an exception indicating that the fixed deposit service is currently inactive. The activateService and deactivateService methods set the value of active variable to true and false, respectively.

Now, who calls the activateService and deactivateService methods? Let’s say a separate scheduler application, Bank App Scheduler, runs at 9:00 AM and 6:00 PM to execute activateService and deactivateService methods, respectively. The Bank App Scheduler application uses JMX (Java Management Extensions) API to remotely interact with FixedDepositService instance. 


Refer to the following article to learn more about JMX: http://docs.oracle.com/javase/tutorial/jmx/index.html.
As Bank App Scheduler uses JMX to change the value of the active variable of the FixedDepositService instance, you need to register the FixedDepositService instance as a managed bean (or MBean) with an MBean server, and expose FixedDepositService’s activateService and deactivateService methods as JMX operations. In Spring, you register instances of a class with the MBean server by annotating the class with Spring’s @ManagedResource annotation, and expose the methods of the class as JMX operations using Spring’s @ManagedOperation annotation.

The following example listing shows usage of @ManagedResource and @ManagedOperation annotations to register instances of the FixedDepositService class with the MBean server, and to expose its activateService and deactivateService methods as JMX operations:

Example listing 1-9 FixedDepositService class that uses Spring’s JMX support
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;

@ManagedResource(objectName =  "fixed_deposit_service:name=FixedDepositService")
public class FixedDepositService {
    private boolean active;

    public FixedDepositDetails getFixedDepositDetails( ..... ) {
        if(active) { ..... }
    }
    public boolean createFixedDeposit(FixedDepositDetails 
          fixedDepositDetails) {
        if(active) { ..... }
    }
 
    @ManagedOperation
    public void activateService() {
        active = true;
    }

    @ManagedOperation
    public void deactivateService() {
        active = false;
    }
}
The above example listing shows that the FixedDepositService class doesn’t directly use JMX API to register its instances with the MBean server and to expose its methods as JMX operations.

JMS (Java Message Service)

Spring’s JMS support simplifies sending and receiving messages from JMS providers.
In MyBank application, when a customer submits a request to receive details of their fixed deposits via email, the FixedDepositService sends the request details to a JMS messaging middleware (like ActiveMQ). The request is later processed by a message listener. Spring simplifies interaction with JMS providers by providing a layer of abstraction. The following example listing shows how FixedDepositService class sends request details to a JMS provider using Spring’s JmsTemplate:

Example listing 1-10FixedDepositService that sends JMS messages
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;

public class FixedDepositService {
    @Autowired
    private transient JmsTemplate jmsTemplate;
    .....
    public boolean submitRequest(Request request) {
        jmsTemplate.convertAndSend(request);
    }
}
The above example listing shows that the FixedDepositService defines a variable of type JmsTemplate, and is annotated with Spring’s @Autowired annotation. For now, you can assume that the @Autowired annotation provides access to a JmsTemplate instance. The JmsTemplate instance knows about the JMS destination to which the JMS message is to be sent. The FixedDepositService’s submitRequest method invokes JmsTemplate’s convertAndSend method to send request details (represented by Request argument of submitRequest method) as a JMS message to the JMS provider. JmsTemplate is discussed in detail in chapter 10.

Once again, the above example listing shows that if you are using Spring Framework to send messages to JMS providers, then you don’t need to directly deal with JMS API.

Caching

Spring’s cache abstraction provides a consistent approach to use caching in your application.

It’s common to use caching solutions to improve the performance of an application. MyBank application uses a caching product to improve the performance of read operations for fixed deposit details. Spring Framework simplifies interacting with different caching solutions by abstracting caching-related logic.

The following example listing shows that the FixedDepositService’s getFixedDepositDetails method uses Spring’s cache abstraction feature to cache fixed deposit details:

Example listing 1-11 FixedDepositService that caches fixed deposit details
import org.springframework.cache.annotation.Cacheable;

public class FixedDepositService {
   
    @Cacheable("fixedDeposits")
    public FixedDepositDetails getFixedDepositDetails( ..... ) { 
        ..... 
    }
   
    public boolean createFixedDeposit(FixedDepositDetails 
      fixedDepositDetails) { ..... }
}
In the above example listing, Spring’s @Cacheable annotation indicates that the fixed deposit details returned by the getFixedDepositDetails method are cached. If the getFixedDepositDetails method is invoked with the same argument value(s), the getFixedDepositDetails method is not executed, and the fixed deposit details are returned from the cache. This shows that if you are using Spring Framework, you don’t need to write caching-related logic in your classes. Spring’s cache abstraction is explained in detail in chapter 10.

In this section, we saw that Spring Framework simplifies developing enterprise applications by transparently providing services to POJOs, thereby shielding developers from lower level API details. Spring also provides easy integration with standard frameworks, like Hibernate, Quartz, JSF, Struts, EJB, and so on, which makes Spring an ideal choice for enterprise application development.
Now that we have looked at some of the benefits of using Spring Framework, let’s take a look at how to develop a simple Spring application.

1-5 A simple Spring application

In this section, we’ll look at a simple Spring application that uses Spring’s DI feature. To use Spring’s DI feature in an application, follow these steps:
1.    identify application objects and their dependencies
2.    create POJO classes corresponding to the application objects identified in step 1
3.   create configuration metadata that depicts application objects and their dependencies
4.   create an instance of Spring IoC container and pass the configuration metadata to it
5.    access application objects from the Spring IoC container instance
Let’s now look at above mentioned steps in the context of MyBank application.

Identifying application objects and their dependencies

We discussed earlier that the MyBank application shows a form for creating a fixed deposit (refer figure 1-3). The following sequence diagram shows the application objects (and their interaction) that come into picture when a user submits the form:
Figure 1-4 MyBank’s application objects and their dependencies

In the above sequence diagram, FixedDepositController represents a web controller that receives the request when the form is submitted. The fixed deposit details are contained in the FixedDepositDetails object. The FixedDepositController invokes the createFixedDeposit method of FixedDepositService (a service layer object). Then, FixedDepositService invokes FixedDepositDao object (a data access object) to save the fixed deposit details in the application’s data store. So, we can interpret from the above diagram that FixedDepositService is a dependency of FixedDepositController object, and FixedDepositDao is a dependency of FixedDepositService object.

IMPORT chapter 1/ch01-bankapp-xml (This project shows a simple Spring application that uses Spring’s DI feature. To run the application, execute the main method of the BankApp class of this project)

Creating POJO classes corresponding to identified application objects

Once you have identified application objects, the next step is to create POJO classes corresponding to these application objects. POJO classes corresponding to the FixedDepositController, FixedDepositService and FixedDepositDao application objects are available in ch01-bankapp-xml project. The ch01-bankapp-xml project represents a simplified version of MyBank application that uses Spring’s DI feature. You should import the ch01-bankapp-xml project into your IDE as in the remaining steps we’ll be looking at the files contained in this project.

In section 1-3, we discussed that a dependency is passed to an application object as a constructor argument or as a setter method argument. The following code listing shows that an instance of FixedDepositService (a dependency of FixedDepositController) is passed as a setter method argument to the FixedDepositController object:

Example listing 1-12FixedDepositController class
Projectch01-bankapp-xml
Source location - src/main/java/sample/spring/chapter01/bankapp 
package sample.spring.chapter01.bankapp;
.....
public class FixedDepositController {
    .....
    private FixedDepositService fixedDepositService;
    .....
    public void setFixedDepositService(FixedDepositService
          fixedDepositService) {
        logger.info("Setting fixedDepositService property");
        this.fixedDepositService = fixedDepositService;
    }
    .....
    public void submit() {
        fixedDepositService.createFixedDeposit(
         new FixedDepositDetails( 1, 10000,
            365, "someemail@something.com"));
    }
    .....
}

If you look at the FixedDepositController, FixedDepositService and FixedDepositDao classes, you’ll notice that none of these classes implement any Spring-specific interface or extend from any Spring-specific class.
Let’s now look at how application objects and their dependencies are specified in the configuration metadata.

Creating the configuration metadata

We saw in section 1-3 that the configuration metadata specifies application objects and their dependencies, which is read by the Spring container to instantiate application objects and inject their dependencies. In this section, we’ll first look at what other information is contained in the configuration metadata, followed by an in-depth look at how configuration metadata is specified in XML format.

The configuration metadata specifies information about the enterprise services (like transaction management, security and remote access) that are required by the application. For instance, if you want Spring to manage transactions, you need to configure an implementation of Spring’s PlatformTransactionManager interface in the configuration metadata. PlatformTransactionManager implementation is responsible for managing transactions (refer chapter 8 to know more about Spring’s transaction management feature).

If your application interacts with messaging middlewares (like ActiveMQ), databases (like MySQL), e-mail servers, and so on, then Spring-specific objects that simplify interacting with these external systems are also defined in the configuration metadata. For instance, if your application sends or receives JMS messages from ActiveMQ, then you can configure Spring’s JmsTemplate class in the configuration metadata to simplify interaction with ActiveMQ. We saw in example listing 1-10 that if you use JmsTemplate for sending messages to a JMS provider, then you don’t need to deal with lower-level JMS API (refer chapter 10 to know more about Spring’s support for interacting with JMS providers).

You can supply the configuration metadata to the Spring container via an XML file or through annotations in POJO classes. Starting with Spring 3.0, you can also supply the configuration metadata to the Spring container through Java classes annotated with Spring’s @Configuration annotation. In this section, we’ll see how configuration metadata is specified in XML format. In chapters 6 and 7, we’ll see how configuration metadata is supplied via annotations in POJO classes and through @Configuration annotated Java classes, respectively.

You provide the configuration metadata for an application in XML format by creating an application context XML file that contains information about the application objects and their dependencies. Example listing 1-3 showed how an application context XML file looks like. The following XML shows the application context XML file of MyBank application that consists of FixedDepositController, FixedDepositService and FixedDepositDao objects (refer figure 1-4 to see how these objects interact with each other):

Example listing 1-13applicationContext.xml - MyBank’s application context XML file
Projectch01-bankapp-xml
Source location - src/main/resources/META-INF/spring
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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="controller"     
    class="sample.spring.chapter01.bankapp.FixedDepositController">
        <property name="fixedDepositService" ref="service" />
  </bean>

    <bean id="service" 
       class="sample.spring.chapter01.bankapp.FixedDepositService">
        <property name="fixedDepositDao" ref="dao" />
    </bean>

    <bean id="dao" 
        class="sample.spring.chapter01.bankapp.FixedDepositDao"/>
</beans>

The following are the important points to note about the application context XML file shown above:
>       The <beans> element is the root element of the application context XML file, and is defined in spring-beans.xsd schema (also referred to as Spring’s beans schema). The spring-beans.xsd schema is contained in spring-beans-5.0.1.RELEASE.jar JAR file that comes with the Spring Framework 5.0.1.RELEASE distribution.

>       Each <bean> element configures an application object that is managed by the Spring container. In Spring Framework’s terminology, a <bean> element represents a bean definition. The object that the Spring container creates based on the bean definition is referred to as a bean. The id attribute specifies a unique name for the bean, and the class attribute specifies the fully-qualified class name of the bean. You can also use the name attribute of <bean> element to specify aliases for the bean. In MyBank application, the application objects are FixedDepositController, FixedDepositService and FixedDepositDao; therefore, we have 3 <bean> elements - one for each application object. As application objects configured by <bean> elements are managed by the Spring container, the responsibility for creating them and injecting their dependencies is with the Spring container. Instead of directly creating instances of application objects defined by <bean> elements, you should obtain them from the Spring container. Later in this section, we’ll look at how to obtain application objects managed by Spring container.

>     No <bean> element is defined corresponding to the FixedDepositDetails domain object of MyBank application. This is because domain objects are not typically managed by the Spring container; they are created by the ORM framework (like Hibernate) used by the application, or you create them programmatically using the new operator.

·       The <property> element specifies a dependency (or a configuration property) of the bean configured by the <bean> element. The <property> element corresponds to a JavaBean-style setter method in the bean class which is invoked by the Spring container to set a dependency (or a configuration property) of the bean.

Let’s now look at how dependencies are injected via setter methods.

Injecting dependencies via setter methods

To understand how dependencies are injected via setter methods defined in the bean class, let’s once again look at the FixedDepositController class of MyBank application:

Example listing 1-14FixedDepositController class
Projectch01-bankapp-xml
Source location - src/main/java/sample/spring/chapter01/bankapp
package sample.spring.chapter01.bankapp;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class FixedDepositController {
    private static Logger logger = 
        LogManager.getLogger(FixedDepositController.class);

    private FixedDepositService fixedDepositService;

    public FixedDepositController() {
       logger.info("initializing");
    }

    public void setFixedDepositService(FixedDepositService 
           fixedDepositService) {
        logger.info("Setting fixedDepositService property");
        this.fixedDepositService = fixedDepositService;
    }
    .....
}
The above example listing shows that the FixedDepositController class declares an instance variable named fixedDepositService of type FixedDepositService. The fixedDepositService variable is set by the setFixedDepositService method - a JavaBean-style setter method for fixedDepositService variable. This is an example of setter-based DI, wherein a setter method satisfies a dependency.

Figure 1-5 describes the bean definition for the FixedDepositController class in the applicationContext.xml file (refer example listing 1-13). 
Figure 1-5 Defining dependencies using <property> elements


The above bean definition shows that the FixedDepositController bean defines its dependence on FixedDepositService bean via <property> element. The <property> element’s name attribute corresponds to the JavaBean-style setter method in the bean class that is invoked by the Spring container at the time of bean creation. The <property> element’s ref attribute identifies the Spring bean whose instance needs to be created and passed to the JavaBean-style setter method. The value of ref attribute must match the id attribute’s value (or one of the names specified by the name attribute) of a <bean> element in the configuration metadata.

In figure 1-5, the value of <property> element’s name attribute is fixedDepositService, which means that the <property> element corresponds to the setFixedDepositService setter method of FixedDepositController class (refer example listing 1-14). As the value of <property> element’s ref attribute is service, the <property> element refers to the <bean> element whose id attribute’s value is service. Now, the <bean> element whose id attribute’s value is service is the FixedDepositService bean (refer example listing 1-13). Spring container creates an instance of FixedDepositService class (a dependency), and invokes the setFixedDepositService method (a JavaBean-style setter method for fixedDepositService variable) of FixedDepositController (a dependent object), passing the FixedDepositService instance.

In the context of FixedDepositController application object, figure 1-6 summarizes the purpose of name and ref attributes of <property> element.
Figure 1-6 <property> element’s name attribute corresponds to a JavaBean-style setter method that satisfies a bean dependency, and ref attribute refers to another bean.

The above figure shows that fixedDepositService value of name attribute corresponds to the setFixedDepositService method of FixedDepositController class, and service value of ref attribute refers to the bean whose id is service.

Figure 1-7 summarizes how the Spring container creates beans and injects their dependencies based on the configuration metadata supplied by the applicationContext.xml file (refer example listing 1-13) of MyBank application. The figure shows the sequence of steps followed by the Spring IoC container to create FixedDepositController, FixedDepositService and FixedDepositDao beans and inject their dependencies. Before attempting to create beans, the Spring container reads and validates the configuration metadata supplied by the applicationContext.xml file. The order in which the beans are created by the Spring container depends on the order in which they are defined in the applicationContext.xml file. Spring container ensures that the dependencies of a bean are completely configured before the setter method is invoked. For example, the FixedDepositController bean is dependent on FixedDepositService bean; therefore, Spring container configures the FixedDepositService bean before invoking the setFixedDepositService method of FixedDepositController bean.



Figure 1-7 - The sequence in which Spring IoC container creates beans and injects their dependencies.

It is fairly common to refer to a bean definition by its name (which is id attribute’s value) or type (which is class attribute’s value) or the interface implemented by the bean class. For instance, you can refer to 'FixedDepositController bean' as 'controller bean'. And, if the FixedDepositController class implements FixedDepositControllerIntf interface, you can refer to 'FixedDepositController bean' as 'FixedDepositControllerIntf bean'.
The bean definitions that we have seen so far, instruct Spring container to create bean instances by invoking the no-argument constructor of the bean class, and inject dependencies using setter-based DI. In chapter 2, we’ll look at bean definitions that instruct Spring container to create a bean instance via a factory method defined in a class. Also, we’ll look at how to inject dependencies through constructor arguments (referred to as constructor-based DI).

Let’s now look at how to create an instance of Spring container and pass configuration metadata to it.

Creating an instance of Spring container

Spring’s ApplicationContext object represents an instance of Spring container. Spring provides a few built-in implementations of ApplicationContext interface, like ClassPathXmlApplicationContext, FileSystemXmlApplicationContext, XmlWebApplicationContext, and so on. The choice of the ApplicationContext implementation depends on how you have defined the configuration metadata (using XML, annotations or Java code), and the type of your application (standalone or web). For instance, ClassPathXmlApplicationContext and FileSystemXmlApplicationContext classes are suitable for standalone applications in which configuration metadata is supplied in XML format, XmlWebApplicationContext is suitable for web applications in which the configuration metadata is supplied in XML format, AnnotationConfigWebApplicationContext is suitable for web applications in which configuration metadata is supplied programmatically through Java code, and so on.

As MyBank application represents a standalone application, we can use either ClassPathXmlApplicationContext or FileSystemXmlApplicationContext class to create an instance of Spring container. You should note that the ClassPathXmlApplicationContext class loads an application context XML file from the specified classpath location, and the FileSystemXmlApplicationContext class loads an application context XML file from the specified location on the filesystem.

The following BankApp class of MyBank application shows that an instance of Spring container is created using the ClassPathXmlApplicationContext class:

Example listing 1-15 BankApp class
Project ch01-bankapp-xml
Source location - src/main/java/sample/spring/chapter01/bankapp
package sample.spring.chapter01.bankapp;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BankApp {
    .....
    public static void main(String args[]) {
        ApplicationContext context = new 
             ClassPathXmlApplicationContext(
               "classpath:META-INF/spring/applicationContext.xml");
        .....
    }
}

The above example listing shows the BankApp’s main method, which is responsible for bootstrapping the Spring container. The classpath location of the application context XML file is passed to the constructor of ClassPathXmlApplicationContext class. The creation of ClassPathXmlApplicationContext instance results in creation of those beans in the application context XML file that are singleton-scoped and set to be pre-instantiated. In chapter 2, we’ll discuss bean scopes, and what it means to have beans pre- or lazily-instantiated by Spring container. For now, you can assume that the beans defined in the applicationContext.xml file of MyBank application are singleton-scoped and set to be pre-instantiated. This means that the beans defined in the applicationContext.xml file are created when an instance of ClassPathXmlApplicationContext is created.

Now that we have seen how to create an instance of the Spring container, let’s look at how to retrieve bean instances from the Spring container.

Access beans from the Spring container

The application objects defined via <bean> elements are created and managed by the Spring container. You can access instances of these application objects by calling one of the getBean methods of the ApplicationContext interface.

The following example listing shows the main method of BankApp class that retrieves an instance of FixedDepositController bean from the Spring container and invokes its methods:

Example listing 1-16BankApp class
Projectch01-bankapp-xml
Source location - src/main/java/sample/spring/chapter01/bankapp

package sample.spring.chapter01.bankapp;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BankApp {
    private static Logger logger = 
            LogManager.getLogger(BankApp.class);

    public static void main(String args[]) {
        ApplicationContext context = new 
          ClassPathXmlApplicationContext(
            "classpath:META-INF/spring/applicationContext.xml");

        

        FixedDepositController fixedDepositController =

                 (FixedDepositController) 

                      context.getBean("controller");

        logger.info("Submission status of fixed deposit : "
                       + fixedDepositController.submit());
        logger.info("Returned fixed deposit info : " + 
              fixedDepositController.get());

    }
}

At first, the ApplicationContext’s getBean method is invoked to retrieve an instance of FixedDepositController bean from the Spring container, followed by invocation of submit and get methods of FixedDepositController bean. The argument passed to the getBean method is the name of the bean whose instance you want to retrieve from the Spring container. The name of the bean passed to the getBean method must be the value of the id or name attribute of the bean that you want to retrieve. If no bean with the specified name is registered with the Spring container, an exception is thrown by the getBean method.

In example listing 1-16, to configure the FixedDepositController instance, we didn’t programmatically create an instance of FixedDepositService and set it on the FixedDepositController instance. Also, we didn’t create an instance of FixedDepositDao and set it on the FixedDepositService instance. This is because the task of creating dependencies, and injecting them into the dependent objects is handled by the Spring container.

If you go to ch01-bankapp-xml project and execute the main method of BankApp class, you’ll see the following output on the console:

INFO  sample.spring.chapter01.bankapp.FixedDepositController - initializing
INFO  sample.spring.chapter01.bankapp.FixedDepositService - initializing
INFO  sample.spring.chapter01.bankapp.FixedDepositDao - initializing
INFO  sample.spring.chapter01.bankapp.FixedDepositService - Setting fixedDepositDao property
INFO sample.spring.chapter01.bankapp.FixedDepositController - Setting fixedDepositService property
INFO  sample.spring.chapter01.bankapp.BankApp - Submission status of fixed deposit : true
INFO  sample.spring.chapter01.bankapp.BankApp - Returned fixed deposit info : id :1, deposit amount : 10000.0, tenure : 365, email : someemail@something.com

The above output shows that the Spring container creates an instance of each of the beans defined in the applicationContext.xml file of MyBank application. Also, Spring container uses setter-based DI to inject an instance of FixedDepositService into FixedDepositController instance, and an instance of FixedDepositDao into the FixedDepositService instance.

Spring Framework 5 introduces many new interesting features and enhancements. Let’s look at some of the important changes to Spring Framework 5.

1-6 What’s new in Spring Framework 5 ?

The following are some of the notable changes to Spring Framework 5 release:
>       compatible with Java 9. This means you can develop applications using Java 9 features and deploy them on Java 9.

>       Spring Framework JARs can be added to Java 9’s module path or classpath. If you add Spring Framework JARs to the module path, they are converted into automatic modules that export all their packages.

>       embraces reactive programming paradigm for developing asynchronous and non-blocking applications. Spring supports using reactive types defined by Reactor 3.1 and RxJava 1.3 and 2.1 libraries. Chapter 18 and 19 discuss developing reactive applications using RxJava 2 and Reactor 3.1.

>       source code of the Spring Framework 5 itself is now based on Java 8

>       the support for portlets, Velocity templates and JasperReports has been dropped from Spring Framework 5

>       @Nullable, @NonNull, @NonNullApi and @NonNullFields annotations bring null-safety to Spring applications. @Nullable annotation indicates that a field, method argument or a method’s return value can be null. @NonNull annotation indicates that a field, method argument or a method’s return value cannot be null. @NonNullApi is a package-level annotation that specifies that the methods and their parameters cannot be null. @NonNullFields is a package-level annotation that specifies that the fields cannot be null. These annotations can be used by static code analysis tools (like FindBugs) to highlight potential issues in the program that can cause java.lang.NullPointerException at runtime.

>       functional style bean registration and customization using the newly introduced methods in AnnotationConfigApplicationContext class (refer chapter 7 for more details)

>       generating and reading an index of Spring components from a file (instead of classpath scanning) for faster application startup (refer chapter 7 for more details)

>       support for Servlet 4.0’s javax.servlet.http.PushBuilder as a controller method argument in Spring Web MVC applications. PushBuilder allows pushing resources to web clients using HTTP/2 protocol.

>       a new web module, spring-webflux, for developing reactive web applications and RESTful web services using RxJava and Reactor libraries (covered in chapters 18 and 19).

>       AsyncRestTemplate support is deprecated in favor of the reactive WebClient (chapter 19 shows how you can use WebClient to access a RESTful web service in a functional and reactive style)


Let’s now look at some of the frameworks that are built on top of Spring Framework. 

1-7 Frameworks built on top of Spring

Though there are many frameworks that use Spring Framework as the foundation, we’ll look at some of the widely popular ones. For a more comprehensive list of frameworks, and for more details about an individual framework, it’s recommended that you visit https://spring.io/projects.


As Spring Framework 5 embraces reactive programming paradigm, the framework built on top of Spring have also undergone changes to support developing reactive applications.
The following table provides a high-level overview of the frameworks that are built on top of Spring Framework:
As the frameworks mentioned in the above table are built on top of Spring Framework, before using any of these frameworks make sure that they are compatible with the Spring Framework version that you are using.

1-8 Summary

In this chapter, we looked at the benefits of using Spring Framework. We also looked at a simple Spring application that showed how to specify configuration metadata in XML format, create the Spring container instance and retrieve beans from it. In the next chapter, we’ll look at some of the foundation concepts of Spring Framework.

Comments

Popular posts from this blog

Creating a reactive RESTful web service using Spring WebFlux, Spring Data and MongoDB

4th Edition of Getting started with Spring Framework now available