Monthly Archives: May 2020

Spring Bean Singleton Scope

In this post I’m going to implement a small demo to show the behavior of the Singleton Scope applied to a Bean in a Spring Boot Application. Before doing that let’s think about what beans in the Spring world are.

The beans are the backbone of an application. They are objects instantiated, assembled and managed by a Spring IoC container of which the ApplicationContext interface is responsible for.

The scope of a bean defines the life cycle and visibility of that bean in the contexts in which it is used. The latest version of Spring framework defines 6 types of scopes:

  • singleton
  • prototype
  • request
  • session
  • application
  • websocket

For now I’m going to focus on the first one Singleton Scope. Using singleton scope (the default scope) the container will create a single instance of that bean and all request for that bean will return the same object. That means that all modification will be reflected in all references to that bean.

Let’s create from an Address, a Customer and an Employee entity.

Class Diagram

Let’s also define the @Configuration annotated class, where to specify the initialization of the Customer and Employee bean to use the Singleton Bean Address.

@Configuration
public class Config {
	@Bean
	@Scope("singleton")
	public Address personSingleton() {
		return new Address();
	}

	@Bean
	public Customer customer(Address address) {
		Customer customer = new Customer();
		customer.setAddress(address);
		return customer;
	}

	@Bean
	public Employee employee(Address address) {
		Employee employee = new Employee();
		employee.setAddress(address);
		return employee;
	}
}

If we execute this Junit Test we can see that the hashCode for these 2 objects is the same and that if we change the value of one of the Address fields both reference to the Address beans will have the updated value as well as all objects that use that reference of the bean.

@SpringBootTest
class ScopeDemoApplicationTests {
	private static final String CITY = "San Francisco";

	@Autowired
	private ApplicationContext context;

	@Test
	public void givenSingletonScope_whenSetName_thenEqualNames() {

		Address personSingletonA = (Address) context.getBean("personSingleton");
		Address personSingletonB = (Address) context.getBean("personSingleton");

		Customer customer = (Customer) context.getBean("customer");
		Employee employee = (Employee) context.getBean("employee");

		personSingletonA.setCity(CITY);
		Assert.assertEquals(CITY, personSingletonB.getCity());

		Assert.assertEquals(personSingletonA.hashCode(),
                                    personSingletonB.hashCode());

		Assert.assertEquals(customer.getAddress().hashCode(),
                                    employee.getAddress().hashCode());
	}
}

The code for this example is available in GitHub.

Spring @RestController vs @Controller

To understand the difference between @RestController and @Controller we can think about the main difference between a REST API and a Web application. The response of a REST API is generally JSON or XML; in a web application, instead, the response is usually a view (some html + css) intended for human viewers.

This is also the main difference between @Controller and @RestController annotation. Basically in a spring mvc @Controller the handler method returns the response “view name” which is resolved to a view technology file (e.g. JSP) and the parsed view content is sent back to browser client. It just create a map of the model object and find a view. If we want instead to bundle the return value yo a web response body we can use the @ResponseBody annotation and no view resolver is needed.

For example assuming that we have a view and a greeting Api in a MVCController that take a param as input and return a view we can use @Controller annotation

// Path of view template
/src/main/resources/templates/greeting.html

@Controller
public class MVCController {

    @RequestMapping("/greeting")
    public String greeting(@RequestParam(name = "name", required = 
              false, defaultValue = "World") String name, Model model) {
        model.addAttribute("name", name);
        // We can return a view name that is present in 
        return "greeting";
    }
}

The @RestController simply returns the object and object data is directly written into HTTP response as JSON or XML. One notice is that in Spring MVC the @RestController annotation is a combination of @Controller and @ResponseBody annotation.

@Controller
@ResponseBody
public class MVCController {
  // your logic
}

@RestController
public class RestFulController { 
  // your logic
}