A Quick Guide to Spring Boot Login Options

A Quick Guide to Spring Boot Login Options

In this post, you’re going to work through various options for implementing a login feature using Spring Boot 2.1. You’ll start with the most simple, basic auth, which you’d likely never want to use except for perhaps an internal backend tool, and move on to a simple form-based authentication page.

In this post, you’re going to work through various options for implementing a login feature using Spring Boot 2.1. You’ll start with the most simple, basic auth, which you’d likely never want to use except for perhaps an internal backend tool, and move on to a simple form-based authentication page.

Next, you’ll customize the default, auto-generated form by overriding some default templates and controllers. Finally, you’ll move on to adding Single Sign-on using OAuth 2.0. You’ll see how to allow the user to sign in using Github and Okta.

The assumptions for this tutorial are pretty basic. I’m assuming that you’ve got a basic familiarity with Spring and Spring Boot, but not necessarily an in-depth understanding of Spring Security or Spring’s various security features. You’ll want to have git installed, and gradle would be nice, but you can use the Gradle wrapper for all of the gradle commands, so that’s not strictly necessary.

Go ahead and clone the the repository I created for this tutorial:

git clone https://github.com/oktadeveloper/okta-spring-boot-login-options-example.git

This repository contains five subdirectories:

  • basic-auth
  • form-auth
  • custom-form-auth
  • oauth-start
  • oauth-okta-github
  • oauth-okta-starter

These correspond to the four sections of this tutorial (with three for the last section, the OAuth section). Except for the oauth-start, these are fully functional applications. In this tutorial, you’ll walk through what the code means and how to build them.

Build HTTP Basic Login in Spring Boot

Basic authentication is, well, basic. It’s a simple scheme built directly into the HTTP protocol. It comes from pastoral times before massive amounts of data and money flowed through the various pipes and tubes of the internet. As such, it’s really not incredibly secure. According to the spec, the password and username are encoded using Base64 in the HTTP authorization header. Because Base64 might as well be plain text, if you are going to use basic auth for anything, make sure that you’re always using HTTPS/SSL because you’re sending your authentication credentials with every request.

Open the basic-auth Spring Boot project with your favorite IDE or editor.

The first thing you’ll want to check out is the build.gradle file. It’s reproduced below. I won’t go through all of them in detail but I want to orient you to a few things going on here in case you’re not already familiar.

plugins {  
    id 'org.springframework.boot' version '2.1.4.RELEASE'  
    id 'java'  
}  
  
apply plugin: 'io.spring.dependency-management'  

group = 'com.okta.springsecurityauth'  
version = '0.0.1-SNAPSHOT'  
sourceCompatibility = '1.8'  
  
repositories {  
    mavenCentral()  
}  
  
dependencies {  
    implementation 'org.springframework.boot:spring-boot-starter-security'  
    implementation 'org.springframework.boot:spring-boot-starter-web'  
    testImplementation 'org.springframework.boot:spring-boot-starter-test'  
    testImplementation 'org.springframework.security:spring-security-test'  
}

There are two Spring plugins being added to the build: org.springframework.boot and io.spring.dependency-management. Notice that the version is set to 2.1.4.RELEASE. One of the real pains with Spring in the past has been dependency management. Spring is a huge collection of libraries, and when you bring in one, you need to bring in others with compatible versions. When you update one, often this causes others to fall out of compatibility. Fixing this in the past could land you in what was called “dependency hell.”

Fortunately, Spring has made things much easier. Look at our two Spring dependencies:

dependencies {  
    implementation 'org.springframework.boot:spring-boot-starter-security'  
    implementation 'org.springframework.boot:spring-boot-starter-web'  
... 
}

Notice that they have no version numbers. These are basically large, meta-dependencies for feature sets (security and web, in this case), and the Spring plugins manage all of the sub-dependencies for you based on the version set in this line:

id 'org.springframework.boot' version '2.1.4.RELEASE'

The executive summary of all that is that this build.gradle file will be loading Spring Boot version 2.1.4 and will be adding the web and security feature modules. A list of all the available starters from Spring can be found in their docs.

Other than the gradle.file, there are really only three other files of interest, all Java files. Look under src/main/java/com/okta/springsecurityauth and you’ll see them:

  • Application.java (the main class that auto-magic’s the whole Spring Boot framework into existence)
  • SecurityConfiguration.java (configures the security options)
  • WebController.java (a very basic HTTP request controller)

Application.java is the entry point into the app. It’s pretty simple in this case, and in many cases. The most important thing is the @SpringBootApplication annotation, which tells your Spring dependencies to bootstrap the whole Spring Boot framework. There is, of course, also the main() method, which is where the Application class is loaded and run by Spring.

package com.okta.springsecurityauth;  
  
import org.springframework.boot.SpringApplication;  
import org.springframework.boot.autoconfigure.SpringBootApplication;  
  
@SpringBootApplication  
public class Application {  
  
    public static void main(String[] args) {  
        SpringApplication.run(Application.class, args);  
    }  
  
}

WebController.java is, cleverly enough, your web request controller. It defines request endpoints and determines the responses.

package com.okta.springsecurityauth;  
  
import org.springframework.stereotype.Controller;  
import org.springframework.web.bind.annotation.RequestMapping;  
import org.springframework.web.bind.annotation.ResponseBody;  
  
@Controller  
public class WebController {  
      
    @RequestMapping("/")  
    @ResponseBody  
    public String index() {  
        return "That's pretty basic!";  
    }  
  
}

In this case, the web controller is returning a simple string instead of routing to a template file, as we’ll see in a bit. The @ResponseBody annotation is what allows this method to directly return the string.

SecurityConfiguration.java is where the action is happening in this tutorial. This is where Spring Boot is configured to use basic authentication. This is also where you can configure a hard-coded default user and password (not something I’d do in production, obviously, but great for tutorials).

package com.okta.springsecurityauth;  
  
import org.springframework.context.annotation.Configuration;  
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;  
import org.springframework.security.config.annotation.web.builders.HttpSecurity;  
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;  
  
@Configuration  
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {  
      
    @Override  
    public void configure(HttpSecurity http) throws Exception {  
        http  
            .authorizeRequests()  
            .anyRequest().authenticated()  
            .and()  
            .httpBasic();  
    }  
      
    @Override  
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {  
        auth.inMemoryAuthentication()  
            .withUser("user")  
            .password("{noop}pass") // Spring Security 5 requires specifying the password storage format  
            .roles("USER");  
    }  
      
}

If you look at the configure() method, you’ll see the http object being used with its fluent interface to tell spring to authenticate all requests and use HTTP basic authentication. This is pretty trivial, but there’s tons of power here in this interface as you’ll see in a minute.

The configure() method is mostly a hack for this tutorial to create a user in an in-memory authentication manager. You’re creating a user with username user and password pass. The user has the USER role assigned to it.

That’s it!

Open a terminal and make sure you’re in the root directory of the basic-auth project. Run the project with the following command:

./gradlew bootRun

Wait for the Spring Boot app to finish loading.

Navigate to <a href="http://localhost:8080" target="_blank">http://localhost:8080</a>.

You’ll see a login window.

Log in using user and pass as credentials.

You’ll be taken to a success screen that says, “That’s pretty basic!”

Configure Spring Boot Form-based Login

When using basic auth, the login form is actually generated by the browser, not by the application. It appears as an un-styled pop-up window. This isn’t great flow or very professional looking.

With some pretty minimal changes to the code, you can have Spring Boot auto-generate a more professional-looking login form. The completed code can be found in the form-auth subdirectory of the GitHub repo, or you can just make the changes to the basic-auth project if that’s still open.

You want to change the configure() method of the SecurityConfiguration.java file to look like this:

@Override  
public void configure(HttpSecurity http) throws Exception {  
    http  
        .authorizeRequests()  
        .anyRequest().authenticated()  
        .and()  
        .formLogin()  
        .and()  
        .httpBasic();  
}

The only different is the addition of the .and().formLogin(). Other than that the two projects are the same.

Run it again using ./gradlew bootRun.

Navigate to <a href="http://localhost:8080" target="_blank">http://localhost:8080</a> (you may need to open an incognito window to trigger re-authentication).

This time you’ll see the login page that Spring generates for you.

Customize the Spring Boot Login Form

The next step in our journey of increasingly sophisticated Spring Boot authentication is to customize the login form. Spring makes this super easy. There are, however, a number of new files and more changes to the code than last time, so I’d suggest opening the project found under the custom-form-auth folder of the repo.

In the build.gradle file there’s one new dependency. This brings in the Thymeleaf templating engine, the default web templating engine for use with Spring Boot.

dependencies {  
    ...
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'  
    ... 
}

The SecurityConfiguration.java file now looks like this (with some parts omitted for brevity):

package com.okta.springsecurityauth;  
  
...
  
@Configuration  
@EnableWebSecurity  
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {  
      
    @Override  
    public void configure(HttpSecurity http) throws Exception {  
        http  
            .authorizeRequests()  
            .antMatchers( "/public/**").permitAll()  
            .anyRequest().authenticated()  
                .and()  
            .formLogin()  
                .loginPage("/login.html")  
                .failureUrl("/login-error.html")  
                .permitAll();  
    }

    ...

}

Notice that the .httpBasic() is gone, and the .formLogin() has some new options. Here you’re setting a login page and a login failure page and making sure that these are publicly available.

Also notice this line:

.antMatchers( "/public/**").permitAll()  

Here you are making the public directory on the classpath root available without authentication. Under src/main/resources/static there is a public directory. When the app is launched, everything under the src/main/resources/static directory is copied to the classpath, so the public directory ends up at the classpath root and all files within it will be available without authentication. This is great for things like images, JavaScript files, and CSS files.

The WebController.java also has some new endpoints:

package com.okta.springsecurityauth;  
  
...
  
@Controller  
public class WebController {  
      
    @RequestMapping("/")  
    @ResponseBody  
    public String index() {  
        return "You made it!";  
    }  

    // Login form  
    @RequestMapping("/login.html")  
    public String login() {  
        return "login.html";  
    }  

    // Login form with error  
    @RequestMapping("/login-error.html")  
    public String loginError(Model model) {  
        model.addAttribute("loginError", true);  
        return "login.html";  
    }  

}

Notice that while the index() method has the @RequestBody annotation, meaning that it is going to return its request body directly as a string, the login() and loginError() methods do not. Instead, they are returning the name of the Thymeleaf templates that Spring Boot will render. By default these templates are found under src/main/resources/templates. Also, notice that the loginError() is a bit of a routing trick. It actually just returns the login.html template but with an error attribute injected into the model.

src/main/resources/templates/login.html is a new file. It’s the login template file.

<!DOCTYPE html>  
<html xmlns:th="http://www.thymeleaf.org">  
<head>  
    <title>Login page</title>  
    <link th:href="@{/public/style.css}" rel="stylesheet" />  
</head>  
<body>  
<div id="container">  
    <h2>Login page</h2>  
    <form th:action="@{/login.html}" method="post">  
        <label for="username">Username</label>  
        <input type="text" id="username" name="username" autofocus="autofocus" />  
        <label for="password">Password</label>  
        <input type="password" id="password" name="password" />  
        <input id="submit" type="submit" value="Log in" />  
    </form>  
    <p th:if="${loginError}" class="error">Wrong user or password</p>  
</div>  
</body>  
</html>

A real, in-depth explanation of Thymeleaf is well beyond the scope of this tutorial. Head over to their website to dig into it if you like.

Remember when you made the public directory public? There is a very basic stylesheet that is being pulled in by this line here. Mostly I included this to demonstrate one way to include static resources in template files.

<link th:href="@{/public/style.css}" rel="stylesheet" />  

The error line is rendered conditionally based on the loginError attribute of the model, which is injected by the loginError() method of the controller.

<p th:if="${loginError}" class="error">Wrong user or password</p>  

Other than that, it’s a pretty simple login form!

Once again, ./gradlew bootRun to run it.

You’ll see the styled, customized login form:

Log in again using user:pass and you’ll see our success screen saying, “You made it!”

Spring Boot OAuth 2.0 Login Using GitHub and Single Sign-On

Up until this point, all of your authentications have been done locally, using the ad hoc in-memory AuthenticationManager. More commonly in production, applications are supporting OAuth 2.0 and OIDC (Open ID Connect). OAuth 2.0 is an open standard for authorization. OIDC is built on top of OAuth 2.0 and adds authentication, for a more complete identity management protocol.

In this tutorial, you’ll first see how to add Single Sign-on (SSO) using GitHub. After that, you’ll see how to use Okta, a software-as-service identity solutions provider.

Both are super easy, and there is a real benefit in allowing users to re-use existing identity providers. Forcing users to handle and manage separate, strong passwords for hundreds of websites is a fool’s errand that ultimately results in weaker passwords and passwords reused across multiple sites (multiplying their vulnerability to attack); not to mention the old “just scribble it on a sticky note and stick it to the monitor” password management solution.

Simplify Your Spring Boot App Login with GitHub Single Sign-on

Now it’s time to implement a GitHub OAuth 2.0 client.

First, you need to register a new OAuth application with GitHub. Go to their website and do this now. Fill in the values as shown below.

Pay particular attention to the Authorization callback URL, as this needs to be <a href="http://localhost:8080/login/oauth2/code/github" target="_blank">http://localhost:8080/login/oauth2/code/github</a>.

Click Register application. Take note of the Client ID and Client Secret as you’ll need them in a sec.

Now, back to Java. Open the oauth-start project in your IDE.

In the build.gradle file, notice a couple of new dependencies:

...
dependencies {  
    implementation 'org.springframework.boot:spring-boot-starter-security'  
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'  
    implementation 'org.springframework.boot:spring-boot-starter-web'  
    implementation 'org.springframework.security:spring-security-oauth2-client'  
    implementation 'org.springframework.security:spring-security-oauth2-jose'  
    ...  
}

The security, Thymeleaf, and web starters are still there. However, there two new Spring starters: oauth2-client and oauth2-jose.

oauth2-client brings in the libraries required for implementing an OAuth 2.0 client. oauth2-jose brings in some common libraries for signing and encryption. JOSE stands for Java Object Signing and Encryption.

The SecurityConfiguration.java file has been updated for OAuth login:

package com.okta.spring.SpringBootOAuth;    
...
  
@Configuration  
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {  
    @Override  
    public void configure(HttpSecurity http) throws Exception {  
        http.antMatcher("/**")  
            .authorizeRequests()  
            .antMatchers("/", "/login**").permitAll()  
            .anyRequest().authenticated()  
            .and()  
            .oauth2Login();  
    }  
}

Two things to notice: 1) all requests to / and login are public, and 2) the oauth2Login() method is what is causing Spring Boot to configure the OAuth 2.0 client.

If this seems too easy, you’re correct. Some of the configuration has been moved to the application.yml file.

Open the src/main/resources/application.yml file:

spring:  
  thymeleaf:  
    cache: false  
  security:  
    oauth2:  
      client:  
        registration:  
          github:  
            client-id: << your GitHub client ID>>  
            client-secret: << your GitHub client secret >>

You need to fill in the Client ID and Client Secret from above into this file.

The web routing and templating have changed as well. Look at the WebController.java file:

package com.okta.spring.SpringBootOAuth;  

...

@Controller  
public class WebController {  

    @RequestMapping("/securedPage")  
    public String securedPage(Model model,  
                              @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient,  
                              @AuthenticationPrincipal OAuth2User oauth2User) {  
        model.addAttribute("userName", oauth2User.getName());  
        model.addAttribute("clientName", authorizedClient.getClientRegistration().getClientName());  
        model.addAttribute("userAttributes", oauth2User.getAttributes());  
        return "securedPage";  
    }  
  
    @RequestMapping("/")  
    public String index() {  
        return "index";  
    }  
  
}

This controller defines two endpoints that return two template files:

  • / –> src/main/resources/templates/index.html
  • /securedPage –> src/main/resources/templates/securedPage.html

In the securedPage() method, notice how dependency injection is used to get information about the authenticated user so that it can be injected into the model, which is then passed to the template file.

The src/main/resources/templates/index.html is pretty simple:

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <title>Home</title>  
</head>  
<body>  
    <h1>Spring Security SSO</h1>  
    <a href="securedPage">Login</a>  
</body>  
</html>

And the src/main/resources/templates/securedPage.html template file:

<!DOCTYPE html>  
<html xmlns:th="http://www.thymeleaf.org">  
<head>  
    <meta charset="UTF-8">  
    <title>Secured Page</title>  
</head>  
<body>  
    <h1>Secured Page</h1>  
    <div>User Name: <span th:text="${userName}"></span></div>  
    <div>Client Name: <span th:text="${clientName}"></span></div>  
    <div>User Attributes: <span th:text="${userAttributes}"></span></div>  
</body>  
</html>

Now you’re ready to try it out. Again, make sure you’re in the project root, and run ./gradlew bootRun.

Navigate to <a href="http://localhost:8080" target="_blank">http://localhost:8080</a> and click the Login link.

If your browser bypasses the login page and goes straight to the /securedPage endpoint, open an incognito browser and try it again.

First, you will need to authorize the Spring Boot Login application to use your Github account for OAuth login.

Next, you will see the GitHub OAuth login screen:

If you’re successful, you’ll see a simple text page that says “Secured Page” in bold letters and displays some information about your OAuth user.

Pretty sweet, huh?

Now you’re going to add a second OAuth provider: Okta.

Add OAuth 2.0 Login with Okta to Your Spring Boot App

First, go to developer.okta.com and sign up for a free developer account, if you don’t already have one.

Once you have an account, to create an OAuth/OIDC app, open your Okta developer dashboard. Click on the Applications top menu item, and then click on Add Application.

Select Web as the platform and click Next.

Give the app a name. I named mine “Spring Boot Login”, but you can name yours whatever you like.

Change the Login redirect URIs to <a href="http://localhost:8080/login/oauth2/code/okta" target="_blank">http://localhost:8080/login/oauth2/code/okta</a>.

The other defaults are fine.

Click Done.

Take note of the Client ID and Client Secret on the next page.

Update the application.yml file for Okta:

spring:  
  ...
  security:  
    oauth2:  
      client:  
        registration:  
          github:  
            client-id: << Your GitHub Client ID >>  
            client-secret: << Your GitHub Client Secret >>  
          okta:  
            client-id: << Your Okta Client ID >>  
            client-secret: << Your Okta Client Secret >> 
            client-name: Okta
        provider:  
          okta:  
            issuer-uri: https://{yourOktaDomain}/oauth2/default

You need to add the Okta registration and provider entries, making sure to fill in your Client ID, Client Secret, and Okta issuer.

Restart the app, go to <a href="http://localhost:8080" target="_blank">http://localhost:8080</a>, and click the Login link.

This time you’ll be given a choice of OAuth providers. This screen is auto-generated by Spring Boot.

Click Okta and you’ll be taken to the Okta login page (usual caveat about logging out and/or incognito apply).

Log in successfully and you’ll see our success page.

At this point, you’ve brought the oauth-start project up to date with the oauth-github-okta project folder, and you’ve seen how easy it is to add multiple OAuth providers to a Spring Boot app.

Simplify OAuth 2.0 Login With Okta’s Spring Boot Starter

The last thing you’re going to do in this tutorial is to configure Okta to allow new user registration. Before you do that, however, I want to introduce you to the Okta Spring Boot Starter. The project simplifies integrating Spring Boot and Okta. The project’s README is a great source for more in-depth info.

You’re going to integrate the Okta Spring Boot Starter into this project and simplify the configuration a little. Just for simplicity, you’re also going to remove the GitHub OAuth integration.

Add one dependency to the build.gradle file:

dependencies {
    ...
    implementation 'com.okta.spring:okta-spring-boot-starter:1.1.0'
    ...
}

Now update the application.yml file:

okta:  
  oauth2:  
    issuer: https://{yourOktaDomain}/oauth2/default  
    client-id: <<yourOktaClientID>>
    client-secret: <<yourOktaClientSecret>> 
spring:  
  thymeleaf:  
    cache: false

Fill in your Client Secret and Client ID.

Try it. Run ./gradlew bootRun.

You should be able to log in via Okta. This time you won’t be given a choice of OAuth 2.0 providers.

Enable User Registration

Log into your developer.okta.com account.

Hover over Users and click on Registration.

Enable registration. Also, enable the Show “Sign Up” link in the sign-in page… option. This causes the registration link to be shown in the hosted login page.

Log in again, using an incognito window. This time you’ll notice the user has the option of registering as a new user.

Enter your email address, password, and name; set up a few security questions, and you’re done! You registered a new user for your application using Okta.

There’s a lot more you can do with Okta’s Self-Service Registration options. All of this can be configured and customized. Take a look at their docs to dig deeper.

The final product for this using the Okta Spring Boot Starter and with the GitHub OAuth removed is found in the oauth-okta-starter directory.

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