Book Image

Spring Essentials

Book Image

Spring Essentials

Overview of this book

Spring is an open source Java application development framework to build and deploy systems and applications that run on the JVM. It is the industry standard and the most popular framework among Java developers with over two-thirds of developers using it. Spring Essentials makes learning Spring so much quicker and easier with the help of illustrations and practical examples. Starting from the core concepts of features such as inversion of Control Container and BeanFactory, we move on to a detailed look at aspect-oriented programming. We cover the breadth and depth of Spring MVC, the WebSocket technology, Spring Data, and Spring Security with various authentication and authorization mechanisms. Packed with real-world examples, you’ll get an insight into utilizing the power of Spring Expression Language in your applications for higher maintainability. You’ll also develop full-duplex real-time communication channels using WebSocket and integrate Spring with web technologies such as JSF, Struts 2, and Tapestry. At the tail end, you will build a modern SPA using EmberJS at the front end and a Spring MVC-based API at the back end.By the end of the book, you will be able to develop your own dull-fledged applications with Spring.
Table of Contents (14 chapters)
Spring Essentials
Credits
About the Authors
About the Reviewer
www.PacktPub.com
Preface
Index

Beans in detail


A Spring application is composed of a set of beans that perform functionality specific to your application layers and are managed by the IoC container. You define your beans with configuration metadata in the form of XML, annotation, or JavaConfig.

Note

The default scope of a Spring bean is singleton. This means that a single instance is shared between clients anywhere in the application. Beware of keeping state (class level data) in singleton classes, as a value set by one client will be visible to all others. The best use case for such singleton classes are stateless services.

Beans are uniquely identified by an id attribute, any of the values supplied to the (comma, semicolon, or space separated) name attribute of the bean definition, or even as an alias definition. You can refer to a bean anywhere in the application with id or any of the names or aliases specified in the bean definition.

It's not necessary that you always provide an id or name to the bean. If one isn't provided, Spring will generate a unique bean name for it; however, if you want to refer to it with a name or an id, then you must provide one.

Spring will try to autowire beans by type if id or name is not provided. This means that ApplicationContext will try to match the bean with the same type or implementation in case it is an interface.

You can refer to a bean by type if it is either the only bean registered of that type or marked as @Primary (primary="true" for XML). Generally, for nested bean definitions and autowire collaborators, you don't need to define a name unless you refer to it outside the definition.

You can alias a bean outside the bean definition using the <alias/> tag, as follows:

<alias name="fromName" alias="toName"/>

Bean definition

A bean definition object that you define to describe a bean has the following metadata:

Property

Description

class

The fully qualified class name of the bean.

id

The unique identifier of the bean.

name

One or more unique names separated by commas, semicolons, or whitespace. Typically, id and name would be the same, and you supply either of these. Other names in the list become aliases.

parent

The parent bean for inheriting configuration data from a parent bean definition.

scope

This decides the scope of the objects. The default scope of a Spring bean is singleton. This means that a single instance is shared between calls. We will discuss more about bean scopes later.

constructor args

Bean references or names for constructor-based DI.

properties

Values or references for setter-based DI.

autowire mode

Instructs the bean whether or how to autowire relationships with collaborators. Autowiring will be discussed later.

primary

This indicates that the bean should be considered as the primary autowiring candidate in case of multiple matches being found.

depends-on

This forces instantiation of dependent beans prior to this bean.

lazy-init

If true, this creates a bean instance when it is first requested.

init-method

Initialization callback method. This has no args void method and will be invoked post instance creation.

destroy-method

Destruction callback method. This has no args void method and will be invoked before destroy.

factory-method

Static instance factory method on the bean itself, unless factory-bean is provided.

factory-bean

Another bean reference that is acting as an instance factory for this bean. Usually comes along with the factory-method property.

Let's take a look at a sample bean definition in XML form:

<bean id="xmlTaskService" class="com...XmlDefinedTaskService"
init-method="init" destroy-method="cleanup">
   <constructor-arg ref="userService"/>
   <constructor-arg>
      <bean class="com...TaskInMemoryDAO"></bean>
   </constructor-arg>
</bean>

In this sample application-context file, the bean, xmlTaskService, is autowired via a constructor, that is, dependencies are injected via a constructor. The first constructor argument refers to an existing bean definition, and the second one is an inline bean definition without an id. The bean has init-method and destroy-method pointed to its own methods.

Now, let's take a look at an annotated bean with slightly different features:

@Service
public class AnnotatedTaskService implements TaskService {

...
   @Autowired
   private UserService userService;

   @Autowired
   private TaskDAO taskDAO;

   @PostConstruct
   public void init() {
      logger.debug(this.getClass().getName() + " started!");
   }

   @PreDestroy
   public void cleanup() {
      logger.debug(this.getClass().getName() + " is about to destroy!");
   }

   public Task createTask(String name, int priority, int createdByuserId, int assigneeUserId) {
      Task task = new Task(name, priority, "Open",
         userService.findById(createdByuserId), null,
         userService.findById(assigneeUserId));
      taskDAO.createTask(task);
      logger.info("Task created: " + task);
      return task;
   }
...
}

This @Service bean autowires its dependencies on its fields (properties) using an @Autowired annotation. Note the @PostConstruct and @PreDestroy annotations, the equivalents of init-method and destroy-method in the previous XML bean definition example. These are not Spring specific but are JSR 250 annotations. They work pretty well with Spring.

Instantiating beans

Bean definitions are recipes for instantiating bean instances. Depending on metadata attributes such as scope, lazy, and depends-on, Spring Framework decides when and how an instance is created. We will discuss it in detail later. Here, let's look at the "how" of instance creation.

With constructors

Any bean definition with or without constructor arguments but without a factory-method is instantiated via its own constructor, using the new operator:

<bean id="greeter" class="com...GreetingBean"></bean>

Now let's see an annotated @Component with a default constructor-based instantiation:

@Component("greeter")
public class GreetingService {
...
}

With a static factory-method

A static method within the same class, marked as factory-method, will be invoked to create an instance in this case:

<bean id="Greeter" class="...GreetingBean" factory-method="newInstance"></bean>

With Java configuration, you can use an @Bean annotation instead of factory methods:

@Configuration
@ComponentScan(basePackages = "com.springessentialsbook")
public class SpringJavaConfigurator {
...
   @Bean
   public BannerService createBanner() {
      return new BannerServiceImpl();
   }
...
}

With an instance factory-method

In this case, bean definition does not need a class attribute, but you specify the factory-bean attribute, which is another bean, with one of its non-static methods as factory-method:

<bean id="greeter"  factory-bean="serviceFactory" factory-method="createGreeter"/>
<bean id="serviceFactory"  class="...ServiceFactory">
<!— ... Dependencies ... -->
</bean>

Injecting bean dependencies

The main purpose of an IoC container is to resolve the dependencies of objects (beans) before they are returned to the clients who called for an instance (say, using the getBean method). Spring does this job transparently based on the bean configuration. When the client receives the bean, all its dependencies are resolved unless specified as not required (@Autowired(required = false)), and it is ready to use.

Spring supports two major variants of DI—constructor-based and setter-based DI—right out of the box.

Constructor-based Dependency Injection

In constructor-based DI, dependencies to a bean are injected as constructor arguments. Basically, the container calls the defined constructor, passing the resolved values of the arguments. It is best practice to resolve mandatory dependencies via a constructor. Let's look at an example of a simple POJO @Service class, a ready candidate for constructor-based DI:

public class SimpleTaskService implements TaskService {
...
   private UserService userService;
   private TaskDAO taskDAO;

   public SimpleTaskService(UserService userService, TaskDAO taskDAO) {
      this.userService = userService;
      this.taskDAO = taskDAO;
   }
...
}

Now, let's define this as a Spring bean in XML:

<bean id="taskService" class="com...SimpleTaskService"">
   <constructor-arg ref="userService" />
   <constructor-arg ref="taskDAO"/>
</bean>

The Spring container resolves dependencies via a constructor based on the argument's type. For the preceding example, you don't need to pass the index or type of the arguments, since they are of complex types.

However, if your constructor has simple types, such as primitives (int, long, and boolean), primitive wrappers (java.lang.Integer, Long, and so on) or String, ambiguities of type and index may arise. In this case, you can explicitly specify the type and index of each argument to help the container match the arguments, as follows:

<bean id="systemSettings" class="com...SystemSettings">
   <constructor-arg index="0" type="int" value="5"/>
   <constructor-arg index="1" type="java.lang.String" value="dd/mm/yyyy"/>
   <constructor-arg index="2" type="java.lang.String" value="Taskify!"/>
</bean>

Remember, index numbers start from zero. The same applies to setter-based injection as well.

Setter-based Dependency Injection

The container calls the setter methods of your bean in the case of setter-based DI after the constructor (with or without args) is invoked. Let's see how the bean definition for the previous SystemSettings would look if the dependencies were injected via setter methods, assuming the SystemSettings now has a no-args constructor:

<bean id="systemSettings" class="com...SystemSettings">
   <property name="openUserTasksMaxLimit" value="5"/>
   <property name="systemDateFormat" value="dd/mm/yyyy"/>
   <property name="appDisplayName" value="Taskify!"/>
</bean>

Spring validates the bean definitions at the startup of the ApplicationContext and fails with a proper message in case of a wrong configuration. The string values given to properties with built-in types such as int, long, String, and boolean are converted and injected automatically when the bean instances are created.

Constructor-based or setter-based DI – which is better?

Which of these DI methods is better purely depends on your scenario and some requirements. The following best practices may provide a guideline:

  1. Use constructor-based DI for mandatory dependencies so that your bean is ready to use when it is first called.

  2. When your constructor gets stuffed with a large number of arguments, it's the figurative bad code smell. It's time to break your bean into smaller units for maintainability.

  3. Use setter-based DI only for optional dependencies or if you need to reinject dependencies later, perhaps using JMX.

  4. Avoid circular dependencies that occur when a dependency (say, bean B) of your bean (bean A) directly or indirectly depends on the same bean again (bean A), and all beans involved use constructor-based DI. You may use setter-based DI here.

  5. You can mix constructor-based and setter-based DI for the same bean, considering mandatory, optional, and circular dependencies.

In a typical Spring application, you can see dependencies injected using both approaches, but this depends on the scenario, considering the preceding guidelines.

Cleaner bean definitions with namespace shortcuts

You can make your bean definitions cleaner and more expressive using p:(property) and c:(constructor) namespaces, as shown here. While the p namespace enables you to use the <bean/> element's attributes instead of the nested <property/> elements in order to describe your property values (or collaborating bean refs), the c namespace allows you to declare the constructor args as the attributes of the <bean/> element:

<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:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context/spring-context.xsd">

   <bean id="p-taskService" class="com...SimpleTaskService" c:userService-ref="userService" c:taskDAO-ref="taskDAO"/>

   <bean id="p-systemSettings" class="com...SystemSettings"
      p:openUserTasksMaxLimit="5"
      p:systemDateFormat"dd/mm/yyyy"
      p:appDisplayName="Taskify!"/>
</beans>

The bean definitions in the preceding listing are cleaner but more expressive. Both c: and p: namespaces follow the same conventions. You need to declare both at the XML root element (<beans/>) before using them with the <bean/> elements. Note that you use the -ref suffix for bean references.

Wiring a List as a dependency

On occasion, we will need to inject static collections of data as bean dependencies. Spring provides a natural method to wire lists. See this example:

<bean id="systemSettings" class="com...SystemSettings">
. . .
  <constructor-arg>
    <list>
      <value>[email protected]</value>
      <value>[email protected]</value>
      <value>[email protected]</value>
    </list>
  </constructor-arg>
</bean>

The preceding example wires a java.util.List<String> for simplicity. If your list contains a collection of beans, you can replace <value> with <ref> or <bean>.

Wiring a Map as a dependency

You can inject java.util.Map instances too in a similar fashion. Look at this example:

<bean id="systemSettings" class="com...SystemSettings">
. . .
  <property name="emails">
    <map>
      <entry key="admin" value="[email protected]"></entry>
      <entry key="it" value="[email protected]"></entry>
      <entry key="devops" value="[email protected]"></entry>
    </map>
  </property>
</bean>

You can inject beans as values, replacing <value> with <ref> or <bean>.

Autowiring dependencies

Spring can autowire dependencies of your beans automatically by inspecting the bean definitions present in the ApplicationContext if you specify the autowire mode. In XML, you specify the autowire attribute of the <bean/> element. Alternatively, you can annotate a bean with @Autowired to autowire dependencies. Spring supports four autowiring modes: no, byName, byType, and constructor.

Note

The default autowiring of Spring beans is byType. If you are autowiring an interface, Spring will try to find an implementation of that interface configured as a Spring bean. If there are multiple, Spring will look for the primary attribute of the configuration to resolve; if not found, it will fail, complaining about an ambiguous bean definition.

Here is an example of autowiring constructor arguments:

@Service
public class AnnotatedTaskService implements TaskService {
...
   @Autowired
   public AnnotatedTaskService(UserService userService, TaskDAO taskDAO) {
      this.userService = userService;
      this.taskDAO = taskDAO;
   }
...
}

Alternatively, you can autowire at the field level, as follows:

@Service
public class AnnotatedTaskService implements TaskService {
...
   @Autowired
   private UserService userService;
   @Autowired
   private TaskDAO taskDAO;
...
}

Autowiring can be fine-tuned with an @Qualifier annotation and required attribute:

@Autowired(required = true)
@Qualifier("taskDAO")
private UserService userService;

You can use @Qualifier at the constructor level too:

@Autowired
public AnnotatedTaskService(@Qualifier("userService") UserService userService, @Qualifier("taskDAO") TaskDAO taskDAO) {
   this.userService = userService;
   this.taskDAO = taskDAO;
}

Bean scoping

When defining a bean with its dependencies and other configuration values, you can optionally specify the scope of a bean in the bean definition. The scope determines the life span of the bean. Spring comes up with six built-in scopes out of the box and supports the creation of custom scopes too. If not explicitly specified, a bean will assume the singleton scope, which is the default scope. The following table lists the built-in Spring scopes:

Scope

Description

singleton

This ensures a single instance inside the container. This is the default scope.

prototype

A new instance is created for every request for the bean.

request

Scopes an instance with the life cycle of every new HTTP request.

session

Scopes with the life cycle of every new HTTP session.

globalSession

Scopes with an HTTP session inside a portlet context.

application

Scopes with the life cycle of a ServletContext. It's singleton for ServletContext.

While singleton and prototype work in all environments, request, session, and application work only in web environments. The globalSession scope is for portlet environments.

In an XML bean definition, the scope is set via the scope attribute of the <bean/> element:

<bean id="userPreferences" class="com...UserPreferences" scope="session">... </bean>

You can annotate the bean scope as a meta-annotation to @Component or its derivations, such as @Service and @Bean, as shown in the following listing:

@Component
@Scope("request")
public class TaskSearch {...}

Generally, service classes and Spring data repositories are declared as singleton, since they are built stateless according to best practice.

Dependency Injection with scoped beans

Beans of different scopes can be wired up as collaborators in your configuration metadata. For example, if you have a session-scoped bean as a dependency to singleton and face an inconsistency problem, the first instance of the session-scoped bean will be shared between all users. This can be solved using a scoped proxy in place of the scoped bean:

<bean id="userPreferences" class="com...UserPreferences" scope="session">
   <aop:scoped-proxy />
</bean>
<bean id="taskService" class="com...TaskService">
   <constructor-arg ref="userPreferences"/>
</bean>

Every time the scoped bean is injected, Spring creates a new AOP proxy around the bean so that the instance is picked up from the exact scope. The annotated version of the preceding listing would look like this:

@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserPreferences { ... }

public class AnnotatedTaskService implements TaskService {
...
   @Autowired
   private UserPreferences userPreferences;
...
}

Creating a custom scope

At times, the scopes supplied by Spring are not sufficient for your specific needs. Spring allows you to create your own custom scope for your scenario. For example, if you want to keep some business process level information throughout its life, you will want to create a new process scope. The following steps will enable you to achieve this:

  1. Create a Java class extending org.springframework.beans.factory.config.Scope.

  2. Define it in your application context (XML or annotation) as a Spring bean.

  3. Register the scope bean with your ApplicationContext either programmatically or in XML with CustomScopeConfigurer.