According to Yann, who was among the first readers of the framework, Spring is the fresh new start after the winter of traditional J2EE. The Spring Framework provides a complete solution to most of the problems that occur in handling the development of numerous complex modules collaborating with each other in a Java enterprise application. Spring is not a replacement for the traditional Java Development, but it is a reliable solution for companies to withstand in today's competitive and fast-growing market without forcing the developers to be tightly coupled on Spring APIs.
In this chapter, we will cover the following topics:
- Introduction to the Spring Framework
- Problems addressed by Spring in enterprise application development
- Spring road map
- What's new in Spring 5.0
Rod Johnson is an Australian computer specialist and cofounder of SpringSource. He is also the author of the book, Expert One-on-One J2EE Design and Development, published in November 2002. This book contains about 30,000 lines of code that contain the fundamental concepts such as Inversion of Control (IoC) and Dependency Injection (DI) of the framework. This code is referred to as interface21. He wrote this code with an intention for it to be used by developers to simplify their work or use it as a basis of their own development. He never thought of any framework development or anything like that. There happened to be a long discussion at the Wrox forum about the code, its improvement, and quite a lot of things changed. Juergen Horller and Yann Caroffa, two readers of the forum, proposed the thought of making the code as a base of a new framework. This is the reasoning of Yann, Spring the fresh new start after Winter of traditional J2EE, who named the framework as the Spring Framework. The project became public in June 2003 and powered towards 1.0. After that, lots of changes and upgrades took place to withstand and support the technologies in the market. In this book, we aim, about the latest version, 5.0 RC1. In a couple of pages, we will cover the new features added in this version. In the subsequent pages, we will cover how to use the latest features in your application and how, as a developer, you can take advantage of these new features to develop applications faster, and with better performance.
Java Platform is a long term, complex, scalable, aggressive, and rapidly developing platform. The application development takes place on a particular version. The applications need to keep on upgrading to the latest version in order to maintain recent standards and cope up with them. These applications have numerous classes that interact with each other and reuse the APIs to take their fullest advantage to ensure that the application is running smoothly. However, this leads to some very common problems, such as scalability, plumbing code, boilerplate code, unavoidable non-functional code, and unit testing. Let's discuss these problems one by one.
The growth and development of each of the technologies in the market is pretty fast, both in hardware as well as software. The application that was developed a couple of years ago may get outdated because of the growth. In the growing market, the hardware is revolving very fast. Starting from the RAM to hard disk capacity, headphones to bluetooth, and network to wireless communication, many things have been changed from the hardware point of view. Software is also not apart from the changes. The market is so demanding that the developers need to keep on changing the application on a frequent basis. This means, whatever the application that we develop today should be capable of handling the upcoming demands and growth without affecting the working application tomorrow. The scalability of an application is about handling or supporting the increased load of work to adapt to the growing environment instead of replacing them. Internet websites are a very simple example of what scalability means. We can call the website scalable when it supports the handling of increased traffic due to the increase in number of hits. As the code is tightly coupled, making it scalable becomes a problem.
Let's take an example of configuring DataSource
in the Tomcat environment. Now that the developers want to use this configured DataSource
in the application, what will we do? Yes, we will do the JNDI lookup to get DataSource
. In order to handle JDBC, we will acquire the connection using DataSource
and then release the resources in try...catch
. The code written in try...catch
and the inter-computer communication using Socket are not application-specific code. Such a type of low-level code that helps you communicate between the application and its underlying layers is called plumbing code. The plumbing code is an unavoidable part of the application, without which, the system will not be able to work as per requirements. The plumbing code increases the length of the code and makes the debugging complex.
How do we get the connection while executing the JDBC code? We will need to register the Driver
class and invoke the getConnection()
method on DriverManager
to obtain the Connection
object. Is there any alternative to these steps? Actually, no! Whenever, wherever we have to perform JDBC operations, these same steps have to be repeated every time. This kind of repetitive code that developers need to write at many places with little or no modification to achieve some task is called the boilerplate code. The boiler plate code makes the Java development unnecessarily lengthier and complex.
Whenever application development happens, the developer concentrates on the business logic, look and feel, and persistency to be achieved. However, along with these things, the developers also give a rigorous thought on how to manage the transactions, handle the increasing load on the site, make the application secure, and much more. If we take a closer look, these things are not the core concerns of the application, but still, these are unavoidable. Such kind of code that is not handling the business logic (functional) requirement but is important for maintenance, troubleshooting, and managing security of an application is called a nonfunctional code. In most of the Java applications, along with core concerns, the developers have to write down nonfunctional code quite frequently. This leads to providing biased concentration on business logic development.
Let's take an example. We want to test some code that is saving the data to the table in the database. Here, testing the database is not our motive; we just want to be sure whether the code that we have written is working fine or not. Enterprise Java application consists of many classes that are interdependent. As dependency exists in the objects, it becomes difficult to carry out the testing.
Spring mainly addresses the discussed problems and provides a very powerful yet easy solution. Let's discuss one by one how Spring provides this solution.
In any application development, the class is a very basic structure where the developers do the coding. The class comprises of different methods. If the class is getting extended or implements an interface of the framework, reusing it becomes difficult as they are tightly coupled with API. Plain Old Java Object (POJO) is a very famous and regularly used terminology in the Java application development. Unlike Struts and EJB, Spring doesn't force developers to write the code that is importing or extending Spring APIs. The best thing about Spring is that developers can write the code that generally doesn't have any dependencies on the framework, and, for this, POJOs are the favorite choice. POJOs support loosely-coupled modules, which are reusable and easy to test.
Coupling is the degree of knowledge one class has about the other class. When a class is less dependent on the design of any other class, it will be called loosely coupled. Loose coupling can be best achieved by interface programming. In the Spring Framework, we can keep the dependencies of the class separated from the code in a separate configuration file. Using the interfaces and dependency injection techniques provided by Spring, developers can write loosely-coupled code. (Don't worry; very soon, we will discuss dependency injection and how to achieve it.) With the help of loose coupling, one can write a code that needs a frequent change due to the change in the dependency it has. It makes the application more flexible and maintainable.
In declarative programming, the code states what it will perform, but not how it will be performed. This is totally the opposite of imperative programming, where we need to state stepwise what we will execute. The declarative programming can be achieved using XML and annotations. Spring Framework keeps all configurations in XML from where it can be used by the framework to maintain the life cycle of a bean. As the development happened in Spring Framework, the 2.0 onward version gave an alternative to XML configuration with a wide range of annotations.
Earlier, we discussed that repetitive code is boilerplate code. The boilerplate code is essential, without which, providing transactions, security logging, and so on will become difficult. The framework gives a solution of writing an Aspect that will deal with such cross-cutting concerns, and there is no need to write them along with the business logic code. The use of Aspect helps us in the reduction of the boilerplate code, but the developers can still achieve the same end effect. The template for different requirements is another thing that the framework provides. Templates such as JDBCTemplate
, HibernateTemplate
have been provided by Spring, ensuring the reduction of the boilerplate code. However, as a matter of fact, you will need to wait to understand and discover the actual potential.
Unlike Struts and Hibernate, which provide web persistency solutions respectively, Spring has a wide range of modules for numerous enterprise-development problems. This layered architecture helps the developer choose any one or more of the modules to write solutions for their application in a coherent way. For example, one can choose the Web MVC module to handle the web request efficiently, without even knowing that there are many other modules available in the framework.
Spring provides more than 20 different modules that can broadly be summarized under seven main modules, which are as follows:
Spring modules
Spring provides the core modules, which are discussed in the following sections.
Spring Core module supports ways of creating Spring beans and injecting the dependencies in to the beans. It provides a means to configure the beans and how to obtain the configured beans from the Spring container using BeanFactory
and ApplicationContext
to develop a standalone application.
The Beans module provides BeanFactory
, which provides an alternative for programmatic singletons. The BeanFactory
module has been designed based upon the factory design pattern.
The Context module inherits the features from the beans module and supports Java enterprise features, such as EJB, JMX, internationalization, loading of the resources, and basic remoting. It supports integration of third-party libraries for caching, Java Mailing, and templating engines such as Velocity.
Spring Expression Language (SpEL) is an extension of the unified Expression Language that is specified in the JSP 2.1 specifications. The SpEL module supports the setting and getting of property values and the configuration of collections using logical as well as arithmetic operators. It provides the support for named variables and retrieves the objects from Spring IoC by their names.
The following are the modules by the Spring Framework that enable the integration of databases in the application.
This JDBC module provides an abstraction layer on JDBC. It supports reduction of the boilerplate code that occurs in getting the connection object via loading of Driver
, the getting Statement
object, and many more. It also supports templates such as JdbcTemplate
and HibernateTemplate
to simplify the development.
The Object Relational Mapping (ORM) module supports the integration of very popular frameworks, such as Hibernate, iBATIS, Java Persistence API (JPA), and Java Data Object (JDO).
The Object XML Mapper (OXM) module supports object to XML mapping and integration for JAXB, Castor, XStream, and more.
The JMS module provides support for an abstract layer over Java Message Service (JMS) for asynchronous integration with other applications via messaging.
The following are the modules offered by Spring to handle Web MVC and remoting.
The Web module supports the integration of web application created in other frameworks. Using this module, the developers can also develop web applications using the Servlet
listener. It supports multipart file uploading and handling of request and response. It also provides web-related remoting support.
The Servlet module contains the Spring Model View Controller (MVC) implementation for web applications. Using Spring MVC, developers can write the handling of request and response to develop a full-fledged web application. It helps in getting rid of the boilerplate code while handling request and response by supporting the handling form submission.
The Portlet module provides MVC implementations to be used in the portlet environment that supports Java's portlet API.
The WebSocket module is a protocol that provides two-way communications between client and server, which was included in Spring 4. This module provides support for integration of the Java WebSocket API in the application.
The following are the modules offered by Spring to handle Aspect-oriented programming (AOP).
The Aspect-oriented programming module helps us to handle and manage the cross-cutting concern services in the application, and helps keep the code cleaner.
The following modules facilitate the use of Instrumentation.
Java Instrumentation gives an innovative way to access a class from JVM with the help of class loader, and modifies its byte code by inserting the custom code. This module supports the Instrumentation
and ClassLoader
implementations for some application servers.
The Instrument Tomcat module contains the Spring instrumentation support for Tomcat.
Spring supports the integration of JDBC using the DAO module, it simplifies web development by the Web MVC module, and, for messaging, Spring provides the integration of STOMP, but that's not the end. Along with these modules, Spring also provides the following modules to integrate the advance features.
Nowadays, applications alone with the basic functionalities also need to provide sound ways to handle security at different levels. Spring 5 supports the declarative security mechanism using Spring AOP.
The Java Enterprise application needs to perform bulk processing and handle a large amount of data in many business solutions without user interactions. To handle such things in batches is the best solution available. Spring provides integration of batch processing to develop robust applications.
In the development of enterprise application, the application may need interaction with them. Spring integration is an extension of the core Spring Framework to provide integration of other enterprise applications with the help of declarative adapters. The messaging is one such integration that is extensively supported by Spring.
The extensive use of Mobile opens the new doors in development. The Mobile module is an extension of Spring MVC that helps us develop mobile web applications known as Spring Android Project. It also provides the detection of the type of device that is making the request, and, accordingly, renders the views.
The basic aim of Spring was to simplify the development and reduce the boilerplate code. The Spring LDAP module supports easy LDAP integration using template-based development.
Since 2004, when the announcement of the public release of the Spring Framework was made, the framework had undergone various updates. Let's discuss the modules and changes that have been in various versions released till date.
Spring 1.0 supports JDO1.0 and iBATIS 1.3, which is integrated with Spring transaction management. This version was supporting functionalities such as Spring Core, Spring Context, Spring AOP, Spring DAO, Spring ORM, and Spring Web.
The Spring Framework enhanced support for Java 5. It added out-of-the-box namespaces such as jee, tx, aop, lang, and util to simplify the configuration. The IoC was supporting scopes as singleton and prototype. In addition to these scopes, scopes for HttpSession, Cluster cache, and request were also introduced. The annotation bases configuration such as @Transactional
, @Required
, and @PersistenceContext
were introduced.
In this version, Spring fully supports Java6 and Java EE5 features such as JDBC4, JavaMail 1.4, JTA1.1, and JAX WS 2.0. It also extends the support for annotation-based DI, including support for a qualifier as well. A new bean named pointcut
element in AspectJ pointcut
expressions is introduced. The built-in support for AspectJ for load time weaving, which is based on the LoadTimeWeaver
abstraction, is provided. For convenience, an introduction of custom namespaces, such as context
and jms
, is included. The testing support is extended for Junit4 and TestNG. The annotation-based SpringMVC controllers are added. It also supports the auto detection of components on the classpath, such as @Repository
, @Service
, @Controller
, and @Component
. Now, SimpleJdbcTemplate
supports named SQL parameters. The certified WebSphere support has been included. It also includes support for JSR-250 annotations, such as @Resource
, @PostConstruct
, and @PreDestroy
.
The entire code of version 2.5 is revised to support Java 5 features, such as generics and varargs
. SpEL has been introduced, which adds the power of using expressions in XML as well as annotation-based configurations. Spring 3.0 supports annotation for the REST web application. It extends support for many Java EE6 features, such as JPA 2.0 and JSF 2.0. The Spring 3.0.5 version supports Hibernate 3.6 final as well.
In this version, testing support has been upgraded for JUnit 4.9. It also supports load time weaving on the WebSphere versions 7 and 8.
For the very first time, the full support for Java 8 features has been included. This version uses JavaEE6 as its baseline. Using Spring 4, now it is possible to define external bean configuration using Groovy DSL. Developers can now treat generic types as a form of qualifier. The @Lazy
annotation can be used on injection points as well as on @Bean
definitions. The @Description
annotation has been introduced for developers using Java-based configuration. The @Conditional
annotation has been introduced for conditional filtering. Now, there is no requirement to have a default constructor used by CGLIB-based proxy classes. The @RestController
annotation has been introduced to remove the need of @ResponseBody
to each of @RequestMapping
. The AsynchRestTemplate
has been included, which allows non-blocking asynchronous support for the REST client development. The spring-websocket
module has been introduced as a new model to provide support for a WebSocket-based two-way communication between server and client. The spring-messaging module has been introduced for the support of WebSocket subprotocol, STOMP. Most of the annotations from the spring-test module can now be used as meta annotations to create custom-composed annotations. The set of mocks from org.springframework.mock.web
is based on Servlet API 3.0.
Spring 5 RC1 will support Java 8+, but, basically, it aims to track and support greatly to the new bee Java 9. It will also support reactive programming Spring 5 with focus on HTTP 2.0. It also aims to focus on reactive programming through reactive architecture. Spring 5.0.RC1 supports reactive multipart request, Jackson 2.9. The access to the request and response objects has been simplified in WebClient
. It also supports reactive types in return values by the Spring Controllers. It supports the JSON binding API. The mock.staticmock
from spring-aspects, web.view.tiles2
, has been dropped. No more support for Portlet, Velocity, JasperReports, XMLBeans, JDO, and Guava.
It can be summarized, as shown in the following figure:
Spring modules
POJO development is the backbone of the Spring Framework. POJO will be configured in the XML. The object instantiation of the configured POJO, object assembling, and object management is done by the Spring IoC container. POJO configured either using XML-based configuration or annotation-based configuration is called bean or Spring bean. We will use Spring IoC as it is based on the Inversion of Control design pattern.
In every Java application, the first important thing that each developer does is to get an object that they can use in the application. The state of an object can be obtained at runtime, or it may be at compile time. However, developers create objects where they use the boilerplate code a number of times. When the same developer uses Spring instead of creating an object by themselves, they will be dependent on the framework to obtain the object. The term Inversion of Control (IoC) comes as Spring container inverts the responsibility of object creation from developers.
The Spring IoC container is just a terminology; the Spring Framework provides the following two containers:
- BeanFactory
- ApplicationContext
The BeanFactory
container provides the basic functionalities and framework configuration. Nowadays, developers don't prefer using BeanFactory
. Now, the obvious question comes to your mind; why is BeanFactory
still in the framework? Why has it not been removed? If not BeanFactory
, then what's the alternative? Let's answer them one by one. The very simple answer of BeanFactory
in the framework is to support the backward compatibility of JDK 1.4. The BeanFactory
container provides BeanFactoryAware
, InitializingBean
, and DisposableBean
interfaces to support backward compatibility for a third-party framework that has integration with Spring. It's an interface; don't worry, we don't need to implement it. The framework has already provided the implementation, as discussed in the following sections.
Today's enterprise application development demands much more than yesterday's development, making the developer's life miserable. The developer will be happy to get a helping hand to manage the object life cycle, or injection of the dependencies, or reduction in the boilerplate code from the IoC container. XMLBeanFactory
is a common implementation of BeanFactory
.
Let's find out, practically, how the BeanFactory
container gets initialized:
- Create a Java application with the name
Ch01_Container_Initialization
. - Add the JARs, as shown in the following screenshot:
Jars to be added
Note
Make sure that you are using JRE to 1.8, as it's a baseline for Spring 5.0 RC1 .
You can download the jars from http://repo.spring.io/milestone/org/springframework/spring/5.0.0.RC1/. To use Maven, the pom.xml
file is available at projects.spring.io/spring-framework
for all the versions of Spring.
- Create a
TestBeanFactory
class under thecom.ch01.test
package. - Create an XML file,
beans_classpath.xml
, in the classpath where we can write bean definitions later. Each bean's definition file contains the referencing schema tobeans.xsd
of the particular Spring version. The root tag of this XML file will be<beans>
.
The basic structure of the XML file is as follows:
<?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/ beanshttp://www.springframework.org/schema/beans/spring- beans.xsd"> </beans>
Our XML file contains the same code as shown in the preceding example, without any beans configured.
- In the main function, let's write down the following code to initialize the bean factory:
BeanFactory beanFactory=new XmlBeanFactory( new ClassPathResource("beans_classpath.xml"));
Here, beans_classpath.xml
will contain the beans definitions. (For simplicity, we haven't added any bean definition; we will see it in detail in the next chapter.) ClassPathResource
loads the resource from the classpath.
- Sometimes, the resource will not be in the classpath, and it will be in the filesystem. The following code can be used to load the resource from the filesystem:
BeanFactory beanFactory=new XmlBeanFactory( new FileSystemResource("d:\\beans_fileSystem.xml"));
We will need to create beans_fileSystem.xml
on the D:
drive, which will contain the same content as that of beans_classpath.xml
.
- The complete code to load the XML will be as follows:
public class TestBeanFactory { public static void main(String[] args) { // TODO Auto-generated method stub BeanFactory beanFactory=new XmlBeanFactory(new ClassPathResource("beans_classpath.xml")); BeanFactory beanFactory1=new XmlBeanFactory(new FileSystemResource("d:\\beans_fileSystem.xml")); System.out.println("beanfactory created successfully"); } }
- There will not be any output on the console apart from logging information of the spring container as we haven't written any output code here. However, the following screenshot shows that the XML file loads and the container gets initialized:
The console logger output
The registration of BeanProcessor
and BeanFactoryPostProcessor
, which plays an important role in AOP and property place holders, needs the explicit code writing that makes it inconvenient to work with. Developers don't want to write code that supports internationalization. The event publication to handle AOP integration is unavoidable. For all of these, the simple solution is to expand the services provided by BeanFactory
with ApplicationContext
. ApplicationContext
is not a replacement of BeanFactory
, but it's an extension for enterprise-specific solutions and more advanced mechanisms for bean configuration.
Let's take a look at the implementations.
The subclass of AbstractXmlApplicationContext
is used for standalone applications. It uses the bean-configured XML file from the class path. Sometimes, the application may have more than one configuration file in the classpath, and, accidentally, they may write the definition for the same bean. In such conditions where the application has more than one XML configuration file, the later bean definition from the XML file will override the earlier bean definition. It provides the advantage of writing a new bean definition to replace the previous one.
Let's find out, practically, how the ClassPathXmlApplicationContext
container gets initialized. We will use the same Ch01_Container_Initialization
project by following these steps:
- Create a
TestClasspathApplicationContext
class under thecom.ch01.test
package. - Create a new XML file,
beans_classpath.xml
, in the classpath, just like we created in the previous application. - In the main function, let's write down the following code to initialize the bean factory:
try { ApplicationContext context=new ClassPathXmlApplicationContext ("beans_classpath.xml"); System.out.println("container created successfully"); } catch (BeansException e) { // TODO Auto-generated catch block e.printStackTrace(); }
No need to create an XML file as we already created it for the previous example. ClassPathXmlApplicationContext
loads beans_classpath.xml
from the classpath that contains the beans definitions. (For simplicity, we haven't added any bean definition; we will see it in detail in the next chapter.)
- Run the application, which will give the following output, suggesting that the container was created successfully:
Console output
- In the Java enterprise application, the project can have multiple configuration files as it's easy to maintain, and it supports modularity as well. To load the multiple bean configuration files, we can use the following code:
try { ApplicationContext context1 = new ClassPathXmlApplicationContext (new String[] { "beans_classpath.xml","beans_classpath1.xml" }); } catch (BeansException e) { // TODO Auto-generated catch block e.printStackTrace(); }
To use the preceding lines of code, we will need to create beans_classpath1.xml
in the classpath.
Similar to ClassPathXmlApplicationContext
, this class also extends AbstractXmlApplicationContext
and is used for standalone applications. However, this class helps us load the bean XML definition from the file system. The file path is relative to the current working directory. In case of specifying the absolute file path, one can use file:
as a prefix. It also provides the advantage of writing a new bean definition to replace the previous one, in case of having multiple XML configurations.
Let's find out, practically, how the ClassPathXmlApplicationContext
container gets initialized. We will use the same Ch01_Container_Initialization
project by following these steps:
- Create a
TestFileSystemApplicationContext
class under thecom.ch01.test
package. - Create a new XML file,
beans_fileSystem.xml
, in theD:
drive as we created in the previous application. - In the main function, let's write down the following code to initialize the bean factory:
try { ApplicationContext context=new FileSystemXmlApplicationContext ("d:\\beans_fileSystem.xml"); System.out.println("container created successfully"); } catch (BeansException e) { // TODO Auto-generated catch block e.printStackTrace(); }
FileSystemXmlApplicationContext
loads the bean_fileSystem.xml
file from the path specified.
- Run the application that will give the following output, suggesting that the container is created successfully.
The structure of the project discussed here will be as shown in the following screenshot:
Project directory structure
AbstractRefreshableWebApplicationContext
has been extended by WebXmlApplicationContext
. We can write the context definition related to the root application context in applicationContext.xml
and keep it under WEB-INF
as it's the default location from where the context definition will be loaded. The XXX-servlet.xml
file is loaded to load the controller definition, as in the case of the MVC application. Also, we can override the default locations by configuring contextConfigLocation
for context-param
and init-param
.
Yes, beans or object of beans will not be available without doing anything from the development side. Spring manages beans, but what to manage has to be decided and passed on to the container. Spring supports declarative programming via the XML file configuration. The beans definitions configured in the XML file are loaded by the container, and using org.springframework.beans
, the object instantiation and the property value injection takes place. The bean life cycle explains the stages, phases, or activities through which each bean object goes through, from making the object usable by the application until it's cleaned up and removed from the container when the application no longer requires the bean. In the next chapter, we will discuss the initialization process in detail.
This chapter gives you an overview of the Spring Framework. We discussed the general problems faced in the Java enterprise application development and how they have been addressed by the Spring Framework. We have seen the overall major changes happen in each version of Spring from its first introduction to the market. The backbone of the Spring Framework is the bean. We used Spring to simplify the work of managing them by the container. We also discussed two Spring containers in depth, BeanFactory
and ApplicationContext
, and how they can be used by the developers. The containers are involved in the process of the bean life cycle management.
In the next chapter, we are aiming to discuss the bean state management in depth, with a very famous terminology, dependency injection, and the bean life cycle management in detail.