Top 4 Spring Annotations for Java Developer in 2019

Top 4 Spring Annotations for Java Developer in 2019

In this article, you'll see the most important Spring annotations that every Java developer should know. We will dive into four of the most pertinent annotations that are available in Spring.

In this article, you'll see the most important Spring annotations that every Java developer should know. We will dive into four of the most pertinent annotations that are available in Spring.

The complexity of modern applications never ceases to grow, with more and more features being packed into single applications or groups of applications. Although this growth brings with it some fantastic benefits, such as rich functionality and impressive versatility, it requires that developers utilize an ever-increasing number of paradigms and libraries. To reduce the workload of developers — and the amount of information that developers must memorize — many Java frameworks have turned to annotations.

Spring, in particular, is renowned for its use of annotations, allowing developers to create entire Representational State Transfer (REST) Application Programming Interfaces (APIs) with only a handful of annotations. These annotations reduce the amount of boilerplate code that is required to perform essential functions, but it also can obscure what is happening behind the scenes. For example, how does applying a Dependency Injection (DI) annotation to a field result in a specific bean being injected at runtime? Or, how does a REST annotation know which URL path to bind to?

In this article, we will dive into four of the most pertinent annotations that are available in Spring, paying particular attention to the concepts behind the annotation and how to properly apply the annotation in the context of a larger application. While we will go into detail on each of these annotations and their associated annotations, the wealth of information on Spring annotations is staggering and could not be contained in this single article.

1. Spring Annotations: @Component

At its heart, Spring is a DI framework. In essence, a DI framework is responsible for injecting dependencies— in the form of Java beans — into other beans. This paradigm is the opposite of most basic applications, which directly instantiate their dependencies. In DI, however, beans are created with a level of indirection, expecting a DI framework to inject the dependencies for them. For example, a well-designed bean would have a constructor with a parameter for the dependency — and allow the DI framework to pass in an object that satisfies that dependency upon construction — rather than directly instantiating the dependency in the constructor. This reversal is called Inversion of Control (IoC) and is the basis upon which many of the various Spring libraries rest:

public class Bar {}
// The non-DI way
public class Foo {
    private final Bar bar;
    public Foo() {
        this.bar = new Bar();
    }
}
// The DI way
public class Foo {
    private final Bar bar;
    public Foo(Bar bar) {
        this.bar = bar;
    }
}

One of the most critical questions for a DI framework to answer is: Which beans are candidates to be injected into other beans? To answer this question, Spring provides the @Component annotation. Applying this annotation to class informs Spring that the class is a component and an object of this class can be instantiated and injected into another component. The @Component interface is applied to a class in the following manner:

@Component
public class FooComponent {}

Although the @Component annotation suffices to inform **Spring **of the injectability of a bean; **Spring **also provides specialized annotations that can be used to create components with more meaningful contextual information.

@Service

The @Service annotation — as the name implies — denotes that a bean is a service. According to the official <a href="https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/stereotype/Service.html" target="_blank">@Service</a> annotation documentation:

[The @Service annotation] indicates that an annotated class is a "Service", originally defined by Domain-Driven Design (Evans, 2003) as "an operation offered as an interface that stands alone in the model, with no encapsulated state."> May also indicate that a class is a "Business Service Facade" (in the Core J2EE patterns sense), or something similar.
In general, the concept of service in enterprise applications is vague, but in the context of a Spring application, a service is any class that provides methods to interact with domain logic or external components without maintaining state that changes the overall behavior of the service. For example, a service may act on behalf of an application to obtain documents from a database or obtain data from an external REST API.

@Service
public class FooService {}

While there is no definitive rule about the state of a service, services generally do not contain state in the way that domain objects do. For example, a REST client, cache, or connection pool would not be considered the state of a service in the same way that a name, address, and social security number would be regarded as the state of a domain object. In practice, @Service and @Component are often used interchangeably due to the all-encompassing definition of a service.

@Repository

While @Service is intended for more a general purpose, the @Repository annotation is a specialization of the @Component annotation that is designed for components that interact with data sources, such as databases, and Data Access Objects (DAOs).

@Repository
public class FooRepository {}

According to the official <a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/stereotype/Repository.html" target="_blank">@Repository</a> documentation:

Indicates that an annotated class is a "Repository", originally defined by Domain-Driven Design (Evans, 2003) as "a mechanism for encapsulating storage, retrieval, and search behavior which emulates a collection of objects".> Teams implementing traditional Java EE patterns such as "Data Access Object" may also apply this stereotype to DAO classes, though care should be taken to understand the distinction between Data Access Object and DDD-style repositories before doing so. This annotation is a general-purpose stereotype and individual teams may narrow their semantics and use as appropriate.
Apart from marking a specific class as a component dealing with data sources, the Spring Framework treats beans annotated with @Repository with special exception processing. To maintain a consistent data interface, Spring can translate the exceptions thrown by native repositories — such as SQL or Hibernate implementations — into general exceptions that can be handled uniformly. To include exception translation for classes annotated with @Repository, we instantiate a bean of type <a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/dao/annotation/PersistenceExceptionTranslationPostProcessor.html" target="_blank">PersistenceExceptionTranslationPostProcessor</a> (we will see in later sections how to use the @Configuration and @Bean annotations):

@Configuration
public class FooConfiguration {
    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslator() {
        return new PersistenceExceptionTranslationPostProcessor()
    }
}

Including this bean will inform **Spring **to look for all implementations of <a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/dao/support/PersistenceExceptionTranslator.html" target="_blank">PersistenceExceptionTranslator</a> and use these implementations, if possible, to translate native RuntimeExceptions into DataAccessExceptions. For more information on exception translation with the @Repository annotation, see the official Spring Data Access documentation.

@Controller

The last specialization of the @Component annotation is arguably the most commonly used of the trio. Spring Model-View-Controller (MVC) is one of the most popular portions of the Spring Framework and allows developers to easily create REST APIs using the @Controller annotation. This annotation, when applied to a class, instructs the *Spring Framework *that the class should be treated as a part of the web interface for the application.

Endpoints are created in this class by applying the @RequestMapping annotation to the methods of that class — where the value of the @RequestMapping annotation is the path (relative to the root path of the controller to which the API endpoints are bound), and the method is the Hypertext Transfer Protocol (HTTP) method to which the endpoint is bound. For example:

@Controller
public class FooController {
    @RequestMapping(value = "/foo", method = RequestMethod.GET)
    public List<Foo> findAllFoos() {
        // ... return all foos in the application ... 
    }
}

This would create an endpoint that listens on the /foo path for GET requests and returns a list of all Foo objects — represented as a JavaScript Object Notation (JSON) list by default — to the caller. For example, if the web application was started on <a href="https://localhost" target="_blank">https://localhost</a>, the endpoint would be bound to <a href="https://localhost/foo" target="_blank">https://localhost/foo</a>. We will cover the @RequestMapping annotation in greater detail below, but for the time being, it suffices to know that the @Controller annotation is a potent part of the Spring Framework and one that instructs the Spring Framework to create large and complex web service implementations on our behalf.

@ComponentScan

As described in Creating Annotations in Java, annotations do not execute any logic in-and-of themselves. Instead, annotations are simply markers that denote some information about a construct, such as a class, method, or field. For the annotation to be useful, it must be processed. In the case of the @Component annotation — and its specializations — **Spring **does not know where to look to find all of the classes annotated with @Component.

To do so, we must instruct **Spring **which packages on the classpath should be scanned. During the scanning process, the Spring DI Framework processes each of the classes in the provided package, recording any classes that are annotated with @Component or specialization of @Component. Once the scanning process is complete, the DI framework is aware of which classes are eligible for injection.

To instruct Spring which packages to scan, we use the @ComponentScan annotation:

@Configuration
@ComponentScan
public class FooConfiguration {
    // ...
}

In a later section, we will delve into the @Configuration annotation, but for the time being, it suffices to know that the @Configuration annotation instructs Spring that the annotated class provides configuration information to be used by the DI framework. By default — if no arguments are supplied to the @ComponentScan annotation — the package that contains the configuration, and all its subpackages, are scanned. To specify a package or set of packages, the basePackages field is used:

@Configuration
@ComponentScan(basePackages = "com.example.foo")
public class FooConfiguration {
    // ...
}

In the above example, Spring would scan the package com.example.foo and all of its subpackages for eligible components. If only one base package is provided, the @ComponentScan annotation can be simplified to @ComponentScan("com.example.foo"). If more than one base package is required, the basePackages field can be assigned a set of strings:

@Configuration
@ComponentScan(basePackages = {"com.example.foo", "com.example.otherfoo"})
public class FooConfiguration {
    // ...
}

2. Spring Annotations: @Autowired

A second, vital question for any DI framework is: What are the dependencies that must be satisfied when creating a bean? To inform the Spring Framework which fields or constructor parameters we are expecting to be injected — or **wired **— with dependencies, Spring provides the @Autowired annotation. This annotation is usually applied to either fields or constructors — although it can be applied to setters as well (this usage is less common).

When applied to fields, **Spring **will inject a qualifying dependence directly into the field upon creation, even when there is no setter present:

@Component
public class FooComponent {
    @Autowired
    private Bar bar;
}

This is a convenient means of injecting dependencies into a component, but it does create an issue when testing a class. For example, if we were to write a test fixture that exercises our FooComponent class, without including the Spring testing framework into our fixture, we would be unable to inject a mock Bar value into the bar field (without performing cumbersome reflection). We could instead add the @Autowired annotation to a constructor that accepts a Bar parameter and assigns it to the bar field:

@Component
public class FooComponent {
    private final Bar bar;
    @Autowired
    public Foo(Bar bar) {
        this.bar = bar;
    }
}

This still allows us to directly instantiate objects of the FooComponent class with mock Bar implementations without burdening the fixture with Spring test configuration. For example, the following would be a valid JUnit test case (using Mockito for mocking):

public class FooTest {
    @Test
    public void exerciseSomeFunctionalityOfFoo() {
        Bar mockBar = Mockito.mock(Bar.class);
        FooComponent foo = new FooComponent(mockBar);
        // ... exercise the FooComponent object ...
    }

Annotating the constructor with @Autowired also allows us to access and manipulate the injected Bar bean before assigning it to the bar field. For example, if we wanted to ensure that the injected Bar bean is never null, we can perform this check prior to assigning the supplied Bar bean to the bar field:

@Component
public class FooComponent {
    private final Bar bar;
    @Autowired
    public FooComponent(Bar bar) {
        this.bar = Objects.requireNonNull(bar);
    }
}

@Qualifier

In some instances, there may be multiple candidates for a dependency. This causes a problem for Spring since it must decide on which specific beans to inject when creating a component, or fail if a single candidate cannot be decided upon. For example, the following code will throw a NoUniqueBeanDefinitionException:

public interface FooDao {
    public List<Foo> findAll();
}
@Repository
public class HibernateFooDao implements FooDao {
    @Override
    public List<Foo> findAll() {
        // ... find all using Hibernate ...
    }
}
@Repository
public class SqlFooDao implements FooDao {
    @Override
    public List<Foo> findAll() {
        // ... find all using SQL ...
    }
}
@Controller
public class FooController {
    private final FooDao dao;
    @Autowired
    public FooController(FooDao dao) {
        this.dao = dao;
    }
}

**Spring **would not know whether to inject the HibernateDooDao or the SqlFooDao and would, therefore, throw a fatal NoUniqueBeanDefinitionException. To aid Spring in resolving which bean to select, we can use the @Qualifier annotation. By supplying a key to @Qualifier annotation that matches the name supplied to the @Component annotation (or any of its specialization) in conjunction with the @Autowired annotation, we can narrow the eligible injection candidates. For example, in the following snippet, the HibernateFooDao would be injected into the FooController and no NoUniqueBeanDefinitionException would be thrown:

public interface FooDao {
    public List<Foo> findAll();
}
@Repository("hibernateDao")
public class HibernateFooDao implements FooDao {
    @Override
    public List<Foo> findAll() {
        // ... find all using Hibernate ...
    }
}
@Repository("sqlDao")
public class SqlFooDao implements FooDao {
    @Override
    public List<Foo> findAll() {
        // ... find all using SQL ...
    }
}
@Controller
public class FooController {
    private final FooDao dao;
    @Autowired
    @Qualifier("hibernateDao")
    public FooController(FooDao dao) {
        this.dao = dao;
    }
}

3. Spring Annotations: @Configuration

Due to the enormous scale of the Spring Framework — dealing with everything from DI to ***MVC ***to transaction management—a level of developer-supplied configuration is needed. For example, if we wish to define a set of beans that can be used for autowiring — such as the <a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/dao/annotation/PersistenceExceptionTranslationPostProcessor.html" target="_blank">PersistenceExceptionTranslationPostProcessor</a> bean seen above — we must inform Spring with some configuration mechanism. Spring provides this mechanism through the aptly named @Configuration annotation. When this annotation is applied to a class, Spring treats that class as if it contains configuration information that can be used to parameterize the framework. According to the official Spring <a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html" target="_blank">@Configuration</a> documentation:

Indicates that a class declares one or more @Bean methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime, for example:### @Bean

As we saw above, we can manually create new beans that Spring will include as candidates for injection without annotating the class itself. This may be the case when we do not have access to the source code for the class or the class exists in a package that is not part of the component scanning process. In the case of our @Qualifier example above, we could also forego the @Repository annotations and use the @Bean annotation inside a class annotated with @Configuration to instruct Spring to use the HibernateFooDao when a FooDao is needed:

public interface FooDao {
    public List<Foo> findAll();
}
public class HibernateFooDao implements FooDao {
    @Override
    public List<Foo> findAll() {
        // ... find all using Hibernate ...
    }
}
public class SqlFooDao implements FooDao {
    @Override
    public List<Foo> findAll() {
        // ... find all using SQL ...
    }
}
@Configuration
public class FooConfiguration {
    @Bean
    public FooDao fooDao() {
        return new HibernateFooDao(); 
    }
}

Using this configuration, Spring will now have the logic necessary to instantiate a HibernateDooDao when a FooDao is requested. In essence, we have created a Factory Method that the framework can use to instantiate instances of FooDao when needed. If an @Autowired parameter is excepted when creating a bean, we can object that dependency by adding a parameter to the method annotated with @Bean. If we annotate the component with @Component — or any specialization of @Component — Spring would know to inject the dependency when creating the component, but because we are calling the constructor directly — outside the Spring Framework — we must supply the dependency. For example:

@Component
public class Bar {}
public class FooComponent {
    private final Bar bar;
    @Autowired
    public FooComponent(Bar bar) {
        this.bar = bar;
    }
}
@Configuration
public class FooConfiguration {
    @Bean
    public FooComponent fooComponent(Bar bar) {
        return new FooComponent(bar);
    }
}

Spring looks for registered candidates that satisfy the fooComponent method parameters and when one is found, it is passed in and eventually passed to the FooComponent constructor. Note that any bean annotated with @Component — or any specialization — or a bean created using another @Bean method can be injected into the @Bean method parameters. For example:

public class Bar {}
public class FooComponent {
    private final Bar bar;
    @Autowired
    public FooComponent(Bar bar) {
        this.bar = bar;
    }
}
@Configuration
public class FooConfiguration {
    @Bean
    public Bar bar() {
        return new Bar();
    }
    @Bean
    public FooComponent fooComponent(Bar bar) {
        return new FooComponent(bar);
    }
}

Note that is a convention to name the method annotated with @Bean the same as the bean, with the first letter lowercase. For example, if we are creating a FooComponent, the method used to create the bean — and annotated with @Bean — is usually called fooComponent.

4. Spring Annotations: @RequestMapping

A large portion of the functionality of the @Controller annotation is derived from the @RequestMapping annotation, which instructs Spring to create a web endpoint that maps to the annotated method. When creating web API, a framework needs to know how to handle requests made to a specific path. For example, if an HTTP GET call is made to <a href="https://localhost/foo" target="_blank">https://localhost/foo</a>, Spring needs to know how to handle that request. This binding — or mapping — process is the purview of the @RequestMapping annotation, which informs Spring that a specific HTTP verb and path should be mapped to a specific method. For example, in a previous section, we saw that we could instruct Spring to map an HTTP GET to /foo using the following snippet:

@Controller
public class FooController {
    @RequestMapping(value = "/foo", method = RequestMethod.GET)
    public List<Foo> findAll() {
        // ... return all foos in the application ... 
    }
}

Note that multiple HTTP verbs can be supplied to the method parameter, but this is abnormal in practice. Since a single HTTP verb is almost always provided to the method parameter — and these verbs usually end up being GET, POST, PUT, and DELETE — Spring also includes four additional annotations that can be used to simplify the creation of @RequestMapping methods:

  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping

If a root path is desired (i.e. a path matching the path of the controller), no value parameter is needed. The @RequestMapping annotation can also be applied to the controller itself, which sets the root path for the entire controller. For example, the following controller creates a GET endpoint at the /foo path and another POST endpoint at /foo/bar:

@Controller
@RequestMapping("/foo")
public class FooController {
    @GetMapping
    public List<Foo> findAll() {
        // ... return all foos in the application ... 
    }
    @PostMapping("/bar")
    public void doSomething() {
        // ... do something ...
    }
}

@PathVariable

In some cases, a path variable may be supplied in the path, which is needed for properly handling the request. To obtain the value of this path variable, a parameter can be provided to the method annotated with @RequestMapping and the @PathVariable annotation can be applied to this parameter. For example, if the ID of an entity is needed to DELETE it, the ID can be provided as a path variable, such as a DELETE request to /foo/1. In order to capture the 1 supplied to the method responsible for handling the DELETE request, we capture the path variable by enclosing the variable name with curly braces and applying the @PathVariable annotation for a parameter of the handler method, where the value supplied to the @PathVariable matches the name of the variable captured in the path:

@Controller
public class FooController {
    @DeleteMapping("/foo/{id}")
    public void deleteById(@PathVariable("id") String id) {
        // ... delete Foo with ID "id" ... 
    }
}

By default, the name of the @PathVariable is assumed to match the name of the annotated parameter, so if the name of the parameter exactly matches the name of the captured variable in the path, no value needs to be supplied to @PathVariable annotation:

@Controller
public class FooController {
    @DeleteMapping("/foo/{id}")
    public void deleteById(@PathVariable String id) {
        // ... delete Foo with ID "id" ... 
    }
}

Spring will attempt to coerce the captured path variable into the data type of the parameter annotated with @PathVariable. For example, if we except the value of the ID path variable to be an integer, we could change the data type of the id parameter to int:

@Controller
public class FooController {
    @DeleteMapping("/foo/{id}")
    public void deleteById(@PathVariable int id) {
        // ... delete Foo with ID "id" ... 
    }
}

If a value, such as the string baz, is supplied in the path (i.e., /foo/baz), an error will occur.

@RequestParam

Apart from capturing path variables, we can also capture query parameters using the @RequestParam annotation. The @RequestParam decorates a parameter to the handler method in the same manner as the @PathVariable annotation, but the value supplied to the @RequestParam annotation matches the key of the query parameter. For example, if we expect that an HTTP GET call will be made to a path of /foo?limit=100, we can create the following controller to capture the limit value:

@Controller
public class FooController {
    @GetMapping("/foo")
    public List<Foo> findAll(@QueryParam("limit") int limit) {
        // ... return all Foo objects up to supplied limit ... 
    }
}

Just as with @PathVariable, the value supplied to the @RequestParam annotation can be omitted, and the name of the parameter will be used by default. Likewise, Spring will coerce the value of the captured query parameter into the type of the parameter, if possible (in the case above, to int).

@RequestBody

In cases where a request body is supplied in a call —commonly done with POST or PUT calls that create or update entries — Spring provides the @RequestBody annotation. As with the previous two annotations, the @RequestBody annotation is applied to a parameter of the handler method. Spring will then deserialize the supplied request body into the type of the parameter. For example, we can create a new Foo with an HTTP call that has a request body similar to the following:

{"name": "some foo", "anotherAttribute": "bar"}

We can then create a class that encompasses fields that match the expected request body and create a handler method that captures this request body:

public class FooRequest {
    private String name;
    private String anotherAttribute;
    public void setName(String name) {
        this.name = name; 
    }
    public String getName() {
        return name;
    }
    public void setAnotherAttribute(String anotherAttribute) {
        this.anotherAttribute = anotherAttribute;
    }
    public String getAnotherAttribute() {
        return anotherAttribute;
    }
}
@Controller
public class FooController {
    @PostMapping("/foo")
    public void create(@RequestBody FooRequest request) {
        // ... create a new Foo object using the request body ...
    }
}

Coda

Although there are many Java frameworks, Spring is far and away, one of the most ubiquitous. From REST APIs to DI, **Spring **includes a rich set of features that allow developers to create complex applications without writing reams of boilerplate code. One mechanism that Spring provides is annotations, which enables developers to decorate classes and methods and provide them with contextual information that can be consumed by the Spring Framework to create components and services on our behalf. Due to the universality of Spring, every Java developer can significantly benefit from understanding these Spring annotations and how they are applied in practice.

Spring Boot Tutorial For Beginner- Spring Boot Full Course

Spring Boot Tutorial For Beginner- Spring Boot Full Course

This "Spring Boot Tutorial For Beginner- Spring Boot Full Course" video will help you learn Spring Boot Framework from scratch with examples. This Spring Tutorial is ideal for both beginners as well as professionals who want to master the Spring Boot Framework

Spring Boot Full Course - Learn Spring Boot In 4 Hours | Spring Boot Tutorial For Beginner

Below are the topics covered in this Spring Boot Tutorial for Beginners video:

1:40 What is Spring Boot?
2:35 Features of Spring Boot
3:50 Why Do We Need Spring Boot?
4:30 Spring Boot Market Trend
5:15 Spring vs Spring Boot
6:25 Install & Setup Spring Boot
6:45 System Requirements
7:35 Install & Set up Spring Boot CLI
14:00 Install & Setup Spring Tool Suite
25:40 Model View Controller
26:00 What is MVC?
27:35 Model View Controller Workflow
29:00 What is Dependency Injection?
31:50 Inversion of Control
33:10 Types of Dependency Injection
34:05 Benefits of Dependency Injection
48:35 Auto wire
49:50 Create First Web Application Using Spring Boot
1:06:50 Create a Web Application To Pass Client Data
1:13:40 Model View & Object Example
1:20:30 Create a Submission Form In Spring Boot
1:40:50 Connect Web Application To Database
2:04:50 REST API
2:07:35 What is REST API?
2:08:50 Features of REST API
2:09:35 Principles of REST API
2:11:40 Methods of REST API
2:12:20 REST API Hands-On
2:35:55 Spring Data REST
2:36:55 Spring Data REST Hands-On
2:46:35 Spring Security
2:47:30 Secure Applications Using Spring Boot
2:58:56 Spring Boot Interview Questions

Full-stack Reactive Java with Spring Framework, Spring Boot and Project Reactor

Full-stack Reactive Java with Spring Framework, Spring Boot and Project Reactor

Reactive programming offers Java developers a way to build message-driven, elastic, resilient, and responsive services...yet many Java developers don't know where to begin.

Reactive programming offers Java developers a way to build message-driven, elastic, resilient, and responsive services...yet many Java developers don't know where to begin.

The Reactive Streams initiative provides a baseline and Project Reactor provides a great way to become immediately productive, leveraging reactive capabilities from end to end. Whether you're coming from a Spring MVC environment or a functional perspective, Reactor empowers you to spin up fully reactive Spring Boot 2 applications quickly and efficiently.

In this talk, the presenter dives into the net-new Netty-based web runtime and shows you how to:

  • integrate easily with existing Spring-stack technologies
  • easily transition from blocking to reactive applications & systems
  • define your API in an imperative style and functionally, reaping all benefits both ways
  • leverage powerful new testing mechanisms to make code better and life easier

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Further reading about Java Spring Framework and Spring Boot

Java Programming Masterclass for Software Developers

100+ Java Interview Questions and Answers In 2019

Build a microservices architecture with Spring Boot and Spring Cloud

Spring Framework - Top 50 Questions for Interview In 2019

Building a Simple CRUD App using Spring Boot, MySQL, JPA/Hibernate

Full Stack Web Development with Angular and Spring MVC

Spring Boot vs. Spring MVC vs. Spring: How Do They Compare?

Spring Boot vs. Spring MVC vs. Spring: How Do They Compare?

In this article, you will receive overviews of Spring, Spring MVC, and Spring Boot, learn what problems they solve, and where they’re best applied. The most important thing that you will learn is that Spring, Spring MVC, and Spring Boot are not competing for the same space. They solve different problems and they solve them very well.

In this article, you will receive overviews of Spring, Spring MVC, and Spring Boot, learn what problems they solve, and where they’re best applied. The most important thing that you will learn is that Spring, Spring MVC, and Spring Boot are not competing for the same space. They solve different problems and they solve them very well.

Spring, Spring Boot, Spring MVC, there are springs everywhere! Let's walk through where and when you should apply each of these tools.

What Is the Core Problem That Spring Framework Solves?

Think long and hard. What’s the problem Spring Framework solves?

The most important feature of Spring Framework is Dependency Injection. At the core of all Spring Modules is Dependency Injection or IOC Inversion of Control.
Why is this important? Because, when DI or IOC is used properly, we can develop loosely coupled applications. And loosely coupled applications can be easily unit tested.

Let’s consider a simple example.

Example Without Dependency Injection

Consider the example below: WelcomeController depends on WelcomeService to get the welcome message. What is it doing to get an instance of WelcomeService?

WelcomeService service = new WelcomeService();

It’s creating an instance of it. And that means they are tightly coupled. For example: If I create a mock for WelcomeService in a unit test for WelcomeController, how do I make WelcomeController use the mock? Not easy!

@RestController
public class WelcomeController {

    private WelcomeService service = new WelcomeService();

    @RequestMapping("/welcome")
    public String welcome() {
        return service.retrieveWelcomeMessage();
    }
}

Same Example with Dependency Injection

The world looks much simpler with dependency injection. You let the Spring Framework do the hard work. We just use two simple annotations: @Component and @Autowired.

  • Using @Component, we tell Spring Framework: Hey there, this is a bean that you need to manage.
  • Using @Autowired, we tell Spring Framework: Hey find the correct match for this specific type and autowire it in.

In the example below, Spring framework would create a bean for WelcomeService and autowire it into WelcomeController.

In a unit test, I can ask the Spring framework to auto-wire the mock of WelcomeService into WelcomeController. (Spring Boot makes things easy to do this with @MockBean. But, that’s a different story altogether!)

@Component
public class WelcomeService {
    //Bla Bla Bla
}

@RestController
public class WelcomeController {

    @Autowired
    private WelcomeService service;

    @RequestMapping("/welcome")
    public String welcome() {
        return service.retrieveWelcomeMessage();
    }
}

What Else Does Spring Framework Solve?

Problem 1: Duplication/Plumbing Code

Does Spring Framework stop with Dependency Injection? No. It builds on the core concept of Dependency Injection with a number of Spring Modules

  • Spring JDBC
  • Spring MVC
  • Spring AOP
  • Spring ORM
  • Spring JMS
  • Spring Test

Consider Spring JMS and Spring JDBC for a moment.

Do these modules bring in any new functionality? No. We can do all this with J2EE or Java EE. So, what do these bring in? They bring in simple abstractions. The aim of these abstractions is to

  • Reduce Boilerplate Code/Reduce Duplication
  • Promote Decoupling/Increase Unit Testability

For example, you need much less code to use a JDBCTemplate or a JMSTemplate compared to a traditional JDBC or JMS.

Problem 2: Good Integration With Other Frameworks

The great thing about Spring Framework is that it does not try to solve problems that are already solved. All that it does is to provide a great integration with frameworks which provide great solutions.

  • Hibernate for ORM
  • iBatis for Object Mapping
  • JUnit and Mockito for Unit Testing
What Is the Core Problem That Spring MVC Framework Solves?

Spring MVC Framework provides decoupled way of developing web applications. With simple concepts like Dispatcher Servlet, ModelAndView and View Resolver, it makes it easy to develop web applications.## Why Do We Need Spring Boot?

Spring based applications have a lot of configuration.

When we use Spring MVC, we need to configure component scan, dispatcher servlet, a view resolver, web jars(for delivering static content) among other things.

  <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/views/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
  </bean>

  <mvc:resources mapping="/webjars/**" location="/webjars/"/>


The code snippet below shows the typical configuration of a dispatcher servlet in a web application.

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/todo-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>


When we use Hibernate/JPA, we would need to configure a datasource, an entity manager factory, a transaction manager among a host of other things.

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <property name="driverClass" value="${db.driver}" />
        <property name="jdbcUrl" value="${db.url}" />
        <property name="user" value="${db.username}" />
        <property name="password" value="${db.password}" />
    </bean>

    <jdbc:initialize-database data-source="dataSource">
        <jdbc:script location="classpath:config/schema.sql" />
        <jdbc:script location="classpath:config/data.sql" />
    </jdbc:initialize-database>

    <bean
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
        id="entityManagerFactory">
        <property name="persistenceUnitName" value="hsql_pu" />
        <property name="dataSource" ref="dataSource" />
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
        <property name="dataSource" ref="dataSource" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"/>


Problem #1: Spring Boot Auto Configuration: Can We Think Different?

Spring Boot brings a new thought process around this.

Can we bring more intelligence into this? When a spring mvc jar is added into an application, can we auto configure some beans automatically?* How about auto-configuring a Data Source if Hibernate jar is on the classpath?

  • How about auto-configuring a Dispatcher Servlet if Spring MVC jar is on the classpath?

There would be provisions to override the default auto configuration.

Spring Boot looks at a) Frameworks available on the CLASSPATH b) Existing configuration for the application. Based on these, Spring Boot provides basic configuration needed to configure the application with these frameworks. This is called Auto Configuration.### Problem #2: Spring Boot Starter Projects: Built Around Well-Known Patterns

Let’s say we want to develop a web application.

First of all, we would need to identify the frameworks we want to use, which versions of frameworks to use and how to connect them together.

All web application have similar needs. Listed below are some of the dependencies we use in our Spring MVC Course. These include Spring MVC, Jackson Databind (for data binding), Hibernate-Validator (for server side validation using Java Validation API) and Log4j (for logging). When creating this course, we had to choose the compatible versions of all these frameworks.

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-webmvc</artifactId>
   <version>4.2.2.RELEASE</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.5.3</version>
</dependency>

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.0.2.Final</version>
</dependency>

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>


Here’s what the Spring Boot documentations says about starters.

Starters are a set of convenient dependency descriptors that you can include in your application. You get a one-stop-shop for all the Spring and related technology that you need, without having to hunt through sample code and copy paste loads of dependency descriptors. For example, if you want to get started using Spring and JPA for database access, just include the spring-boot-starter-data-jpa dependency in your project, and you are good to go.
Let’s consider an example starter: Spring Boot Starter Web.

If you want to develop a web application or an application to expose restful services, Spring Boot Start Web is the starter to pick. Let’s create a quick project with Spring Boot Starter Web using Spring Initializr.

Dependency for Spring Boot Starter Web

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>


The following screenshot shows the different dependencies that are added into our application

Dependencies can be classified into:

  • Spring: core, beans, context, aop
  • Web MVC: (Spring MVC)
  • Jackson: for JSON Binding
  • Validation: Hibernate Validator, Validation API
  • Embedded Servlet Container: Tomcat
  • Logging: logback, slf4j

Any typical web application would use all these dependencies. Spring Boot Starter Web comes pre-packaged with these. As a developer, I would not need to worry about either these dependencies or their compatible versions.

Spring Boot Starter Project Options

As we see from Spring Boot Starter Web, starter projects help us in quickly getting started with developing specific types of applications.

  • spring-boot-starter-web-services: SOAP Web Services
  • spring-boot-starter-web: Web and RESTful applications
  • spring-boot-starter-test: Unit testing and Integration Testing
  • spring-boot-starter-jdbc: Traditional JDBC
  • spring-boot-starter-hateoas: Add HATEOAS features to your services
  • spring-boot-starter-security: Authentication and Authorization using Spring Security
  • spring-boot-starter-data-jpa: Spring Data JPA with Hibernate
  • spring-boot-starter-cache: Enabling Spring Framework’s caching support
  • spring-boot-starter-data-rest: Expose Simple REST Services using Spring Data REST
Other Goals of Spring Boot

There are a few starters for technical stuff as well

  • spring-boot-starter-actuator: To use advanced features like monitoring and tracing to your application out of the box
  • spring-boot-starter-undertow, spring-boot-starter-jetty, spring-boot-starter-tomcat: To pick your specific choice of Embedded Servlet Container
  • spring-boot-starter-logging: For Logging using logback
  • spring-boot-starter-log4j2: Logging using Log4j2

Spring Boot aims to enable production ready applications in quick time.

  • Actuator: Enables Advanced Monitoring and Tracing of applications.
  • Embedded Server Integrations: Since the server is integrated into the application, I would need to have a separate application server installed on the server.
  • Default Error Handling