A Guide to Spring’s Open Session In View

A Guide to Spring’s Open Session In View

**Overview**: Spring Open Session in View is one of the transactional patterns, for binding Hibernate session/JPA Entity Manager to user request life-cycle. Spring MVC comes with one of the implementations for an open session in view pattern...

Overview: Spring Open Session in View is one of the transactional patterns, for binding Hibernate session/JPA Entity Manager to user request life-cycle. Spring MVC comes with one of the implementations for an open session in view pattern, named OpenSessionInViewInterceptor or OpenSessionInViewFilter to work with lazy associations, and improving hire Java developer productivity.

Introduction:
For a better understanding of Open Session in View, let’s suppose we have an incoming request, and spring MVC will do the below things on behalf of you:

  1. Spring MVC open a Hibernate session/ JPA Entity Manager at the begging of the request, these sessions initially it may not necessary to obtain the connection from connection-pool, and it will bind the session into TransactionSynchronizationManager class.
  2. During the request life cycle, the application needs the session, it re-uses the session that we already created.
  3. At the end of the request, session will be closed.

If we understand the overview of this process, it can boosts the developer productivity as session creation/binding the session/ closing the session will be done by framework.

But sometimes Open Session in View will also cause performance issues mainly in production.

Spring Boot: By default Open Session in View, is enabled.

Since Spring Boot 2.0, if this is enabled, it will log the below warning in the console.

Spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning

We can also disable this property by setting spring.jpa.open-in-view to false.

Pros and Cons of Open Session in View (OSIV):
Pros of OSIV:

  1. Fewer queries need to write in service layer.
  2. It provides the transaction outside of the transactional-context.
  3. Avoid lazyInitializationExceptions.

Cons of OSIV:

  1. OSIV can be easily misused, and it will introduce the N+1 performance issues.
  2. Entity property navigation may invoke number of unnecessary queries.
  3. Every session is executing auto-commit mode, after each SQL statement session will commit the transaction, using read-only transaction type, we can avoid the commit the transaction after each SQL statement execution.

Lazy initialization:
For better understanding the OSIV, let’s consider the example, user is one of the entities, class, having a set of permissions.

@Table(name = "users")
public class User {
 
    @Id
    @GeneratedValue
    private Long id;
 
    private String username;
 
    @ElementCollection
    private Set<String> permissions;
 
    // getters and setters
}```

And sample Service class for finding the user by using username:

```@Service
public class SimpleUserService implements UserService {
 
    private final UserRepository userRepository;
 
    public SimpleUserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
 
    @Override
    @Transactional(readOnly = true)
    public Optional<User> findOne(String username) {
        return userRepository.findByUsername(username);
    }
}```

And Sample User Controller will look like below:

```@RestController
@RequestMapping("/users")
public class UserController {
 
    private final UserService userService;
 
    public UserController(UserService userService) {
        this.userService = userService;
    }
 
    @GetMapping("/{username}")
    public ResponseEntity<?> findOne(@PathVariable String username) {
        return userService
                .findOne(username)
                .map(DetailedUserDto::fromEntity)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }
}```

Here, based on the username path-variable, it will fetch the user from database.

Below is the JUnit test case for testing this:

```@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
class UserControllerIntegrationTest {
 
    @Autowired
    private UserRepository userRepository;
 
    @Autowired
    private MockMvc mockMvc;
 
    @BeforeEach
    void setUp() {
        User user = new User();
        user.setUsername("root");
        user.setPermissions(new HashSet<>(Arrays.asList("PERM_READ", "PERM_WRITE")));
 
        userRepository.save(user);
    }
 
    @Test
    Void givenTheUserExists_WhenOsivIsEnabled_ThenLazyInitWorksEverywhere() throws Exception {
        mockMvc.perform(get("/users/root"))
          .andExpect(status().isOk())
          .andExpect(jsonPath("$.username").value("root"))
          .andExpect(jsonPath("$.permissions", containsInAnyOrder("PERM_READ", "PERM_WRITE")));
    }
}```


If we execute this, it will be successful, if the OSIV is not configured then it will fail, as for permission property, it will throw LazyInitializationException exception.

**Alternatives to OSIV:**
1) A developer can handle all dependencies to load in transaction context using like Hibernate.initialize(user.getPermissions()).
2) We can JPA 2 Entity graphs for fetching all dependent entities.
3) We can use the JOIN FETCH keyword to fetch all nested properties.

Conclusion: we learned about Open Session in View (OSIV), pros and cons of it, and also how Spring boot internally uses OSIV, and what is the alternative to OSIV.

Angular 9 Tutorial: Learn to Build a CRUD Angular App Quickly

What's new in Bootstrap 5 and when Bootstrap 5 release date?

What’s new in HTML6

How to Build Progressive Web Apps (PWA) using Angular 9

What is new features in Javascript ES2020 ECMAScript 2020

How to build the MVC Java Web App using Spring Boot and Netbean

How to build the MVC Java Web App using Spring Boot and Netbean

In this tutorial, you'll learn how to build the MVC (Model, View, Controller) Java Web App using Spring Boot and Netbeans 11.1

In this Spring Boot tutorial, we will guide you on how to build the MVC Java web app using Netbeans (we are using Apache Netbeans 11.1). Netbeans IDE development continues by Apache since version 9. You can use Eclipse, Intellij, or JDeveloper as well. By using Spring Boot, building Java web app actually a little bit easier than creating Java projects manually using Maven or Gradle. Especially when we are using Spring Initialzr that will help you to create a set of application bundles with the supported dependencies.

Table of Contents:

  • Step #1: Generate Spring Boot Java Web App
  • Step #2: Create Java Model or Entity Class
  • Step #3: Create Java Repository Interface
  • Step #4: Create Spring MVC Controller
  • Step #5: Create Spring MVC Views
  • Step #6: Run The Spring Boot Java Web App

As you can see in the above table of contents that build MVC Java web app required a few steps. Starting from creating Spring Boot project, Java model, Java repository, Java controller, and Java view. This MVC Java web app also uses a database and we will use an H2 In-Memory database or HSQLDB. For the view, we will use Thymeleaf and Bootstrap. So the following tools, frameworks, and libraries are required for this tutorial:

  1. Java Development Kit (JDK) 8
  2. Gradle
  3. Spring Boot
  4. Spring MVC
  5. Spring Data JPA
  6. H2 Database
  7. Thymeleaf
  8. Webjars Bootstrap
  9. Spring Initializer
  10. Netbeans
  11. Terminal or cmd

We assume that you have to install Netbeans, JDK 8 and Gradle in your machine. So, we need just generate a new Spring Boot Gradle Java Web App.

Step #1: Generate Spring Boot Java Web App

We will create a new Spring Boot Gradle project using Spring Initializer. Spring Initializr provides an extensible API to generate quickstart projects, and to inspect the metadata used to generate projects, for instance, to list the available dependencies and versions. Just go to Spring Initializer web-based Spring project generator then fill the required frameworks and libraries (Spring Web, H2 Database, Thymeleaf, Spring Data JPA, Spring Data JDBC).

After filling all fields, click Generate Project. It will automatically download the zipped project. Next, extract the zipped project to your java projects folder then open the folder from Netbeans IDE a project (use open project menu). Next, from the Projects panel expand the project name (ours: springmvc) then expand Build Scripts and you will see the build.gradle file. Open that file and you will see this project information, plugin, repositories, and dependencies.

plugins {
    id 'org.springframework.boot' version '2.1.9.RELEASE'
    id 'io.spring.dependency-management' version '1.0.8.RELEASE'
    id 'java'
}

group = 'com.djamware'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    runtimeOnly 'com.h2database:h2'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

Add this dependency for Bootstrap and Thymeleaf Layout Dialect inside dependencies body.

dependencies {
  ...
    compile 'org.webjars:bootstrap:3.3.7'
  compile 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:2.4.1'
    ...
}

In Netbeans, right-click the project name then click build to build the project for the first time.

Step #2: Create Java Model or Entity Class

We will create a single table of product data for this Spring MVC Java web app. Now, we will implement the term "M" of the Spring MVC by creating a new Java model or entity. Right-click the project name -> New -> Java Class. Fill the class name as Product, the package name as com.djamware.springmvc.models, and leave other fields as default then click the Finish button. The new Java class automatically opened then replace all Java codes with these codes of Java entity, auto-generation ID, required fields, the constructors, and getter and setter.

package com.djamware.springmvc.models;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String prodName;

    private String prodDesc;

    private String prodImage;

    private Double prodPrice;

    public Product() {
    }

    public Product(String prodName, String prodDesc, String prodImage, Double prodPrice) {
        this.prodName = prodName;
        this.prodDesc = prodDesc;
        this.prodImage = prodImage;
        this.prodPrice = prodPrice;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getProdName() {
        return prodName;
    }

    public void setProdName(String prodName) {
        this.prodName = prodName;
    }

    public String getProdDesc() {
        return prodDesc;
    }

    public void setProdDesc(String prodDesc) {
        this.prodDesc = prodDesc;
    }

    public String getProdImage() {
        return prodImage;
    }

    public void setProdImage(String prodImage) {
        this.prodImage = prodImage;
    }

    public Double getProdPrice() {
        return prodPrice;
    }

    public void setProdPrice(Double prodPrice) {
        this.prodPrice = prodPrice;
    }

}
Step #3: Create Java Repository Interface

Next, we have to create a User Repository that extends the JPA Repository for the Product model. Right-click the project name -> New -> Java Interface. Fill the class name as ProductRepository, the package name com.djamware.springmvc.repositories, and leave other fields as default then click the Finish button. That newly created file will open then replace all Java codes with these codes.

package com.djamware.springmvc.repositories;

import com.djamware.springmvc.models.Product;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ProductRepository extends JpaRepository<Product, Long> {

    Product findByProdName(final String prodName);

}

As you see, the ProductRepository interface now extends the JpaRepository of Product type and it only has an additional query interface of find product by product name. Since Spring Boot 2.1, overriding is disable by default. So, overriding this ProductRepository will result in this error in runtime.

The bean 'productRepository', defined in null, could not be registered. A bean with that name has already been defined in null and overriding is disabled.

To fix that, just open and edit Resources/application.properties then add this line to enable overriding.

spring.main.allow-bean-definition-overriding=true
Step #4: Create Spring MVC Controller

Now, it's time for C terms of MVC that means Controller. To create it on Netbeans just right click on project name -> New -> Java Class. Fill the class name with ProductController and the package with com.djamware.springmvc.controllers. Leave other fields as default then click the Finish button. That newly created Java class file will be opened automatically. Replace all Java codes with these codes of @Controller, @RequestMapping, @RequestParam, ProductRepository, and all required CRUD methods that return the page for each CRUD operation.

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.djamware.springmvc.controllers;

import com.djamware.springmvc.models.Product;
import com.djamware.springmvc.repositories.ProductRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class ProductController {

    @Autowired
    ProductRepository productRepository;

    @RequestMapping("/product")
    public String product(Model model) {
        model.addAttribute("products", productRepository.findAll());
        return "product";
    }

    @RequestMapping("/create")
    public String create(Model model) {
        return "create";
    }

    @RequestMapping("/save")
    public String save(@RequestParam String prodName, @RequestParam String prodDesc, @RequestParam Double prodPrice, @RequestParam String prodImage) {
        Product product = new Product();
        product.setProdName(prodName);
        product.setProdDesc(prodDesc);
        product.setProdImage(prodImage);
        product.setProdPrice(prodPrice);
        productRepository.save(product);

        return "redirect:/show/" + product.getId();
    }

    @RequestMapping("/show/{id}")
    public String show(@PathVariable Long id, Model model) {
        model.addAttribute("product", productRepository.findById(id).orElse(null));
        return "show";
    }

    @RequestMapping("/delete")
    public String delete(@RequestParam Long id) {
        Product product = productRepository.findById(id).orElse(null);
        productRepository.delete(product);

        return "redirect:/product";
    }

    @RequestMapping("/edit/{id}")
    public String edit(@PathVariable Long id, Model model) {
        model.addAttribute("product", productRepository.findById(id).orElse(null));
        return "edit";
    }

    @RequestMapping("/update")
    public String update(@RequestParam Long id, @RequestParam String prodName, @RequestParam String prodDesc, @RequestParam Double prodPrice, @RequestParam String prodImage) {
        Product product = productRepository.findById(id).orElse(null);
        product.setProdName(prodName);
        product.setProdDesc(prodDesc);
        product.setProdImage(prodImage);
        product.setProdPrice(prodPrice);
        productRepository.save(product);

        return "redirect:/show/" + product.getId();
    }

}
Step #5: Create Spring MVC Views

Now, it's the time of V for the View of MVC pattern. Since we are using the Thymeleaf library for view template, so we can create the same layout for all HTML pages. Thymeleaf is a Java XML/XHTML/HTML5 template engine that can work both in web (servlet-based) and non-web environments. It is better suited for serving XHTML/HTML5 at the view layer of MVC-based web applications, but it can process any XML file even in offline environments. To create the layout, first, create a default.html file on the Resources/templates folder then add or replace it with these lines of codes.

<!DOCTYPE html>
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
    <head>
        <meta charset="UTF-8"/>
        <title>Default title for my pages</title>
        <link rel="stylesheet" href="/webjars/bootstrap/3.3.7/css/bootstrap.min.css"/>
        <link rel="stylesheet" href="/webjars/bootstrap/3.3.7/css/bootstrap-theme.min.css"/>
        <link rel="stylesheet" href="/css/style.css" />
    </head>
    <body>
        <nav class="navbar navbar-inverse navbar-fixed-top">
            <div class="container">
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    <a class="navbar-brand" href="#">Spring MVC</a>
                </div>
                <div id="navbar" class="collapse navbar-collapse">
                    <ul class="nav navbar-nav">
                        <li class="active"><a href="/product">Home</a></li>
                    </ul>
                </div><!--/.nav-collapse -->
            </div>
        </nav>

        <div class="container">
            <div class="starter-template" layout:fragment="content"></div>
        </div><!-- /.container -->

        <script src="/webjars/jquery/1.11.1/jquery.min.js"></script>
        <script src="/webjars/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    </body>
</html>

That HTML shows a layout template using Thymeleaf Layout. To making this layout working, make sure you have additional dependencies of Thymeleaf Layout Dialect that previously added in the first steps. All CSS and Javascript files put on that file and called once for all pages that use default.html as layout holder. Also, we call Bootstrap and JQuery on that file. Next, we create a view for the Product list with the name product.html then replace all codes to that file with this.

<!DOCTYPE HTML>
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="default">
    <head>
        <title>Product List</title>
    </head>
    <body>
        <div layout:fragment="content" class="row">
            <div class="col-xs-8 col-md-8">
                <h3>
                    <a href="/create" class="btn btn-primary"><span class="glyphicon glyphicon-plus-sign"></span> Product</a>
                </h3>
                <h2>Product List</h2>
                <div class="table-responsive">
                    <table class="table" id="product-table">
                        <thead>
                            <tr>
                                <th>Product Name</th>
                                <th>Product Desc</th>
                                <th>Product Price</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr th:each="product : ${products}">
                                <td><a th:text="${product.prodName}" th:href="@{'/show/' + ${product.id}}"></a></td>
                                <td th:text="${product.prodDesc}"></td>
                                <td th:text="${product.prodPrice}"></td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </body>
</html>

Next, create a view for creating a product form with the name create.html on Resources/templates folder then replace all codes with this.

<!DOCTYPE HTML>
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="default">
    <head>
        <title>Create Product</title>
    </head>
    <body>
        <div layout:fragment="content" class="row">
            <div class="col-xs-8 col-md-8">
                <h3>
                    <a href="/product" class="btn btn-lg btn-primary"><span class="glyphicon glyphicon-list"></span> Product</a>
                </h3>
                <h2>Create Product</h2>
                <form action="/save">
                    <div class="form-group">
                        <label for="email">Product Name:</label>
                        <input type="text" class="form-control" name="prodName" />
                    </div>
                    <div class="form-group">
                        <label for="email">Product Description</label>
                        <textarea class="form-control" name="prodDesc" cols="60" rows="3"></textarea>
                    </div>
                    <div class="form-group">
                        <label for="email">Product Price</label>
                        <input type="number" class="form-control" name="prodPrice" />
                    </div>
                    <div class="form-group">
                        <label for="email">Product Image URL:</label>
                        <input type="url" class="form-control" name="prodImage" />
                    </div>
                    <button type="submit" class="btn btn-success">Save</button>
                </form>
            </div>
        </div>
    </body>
</html>

Next, create a view for show product detail with the name show.html on Resources/templates folder then replace all codes with this.

<!DOCTYPE HTML>
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="default">
    <head>
        <title>Show Product</title>
    </head>
    <body>
        <div layout:fragment="content" class="row">
            <div class="col-xs-8 col-md-8">
                <h3>
                    <a href="/product" class="btn btn-primary"><span class="glyphicon glyphicon-list"></span> Product</a>
                </h3>
                <h2 th:text="${product.prodName}"></h2>
                <h2><img th:src="${product.prodImage}" width="200" /></h2>
                <dl class="list">
                    <dt>Product Description</dt>
                    <dd th:text="${product.prodDesc}"></dd>
                    <dt>Product Description</dt>
                    <dd th:text="${product.prodPrice}"></dd>
                </dl>
                <form action="/delete">
                    <input type="hidden" name="id" th:value="${product.id}" />
                    <h2><input type="submit" class="btn btn-danger" value="Delete" onclick="return confirm('Are you sure?');" />
                        <a th:href="@{'/edit/' + ${product.id}}" class="btn btn-warning">Edit</a></h2>
                </form>
            </div>
        </div>
    </body>
</html>

Next, create a view for edit product with the name edit.html on Resources/templates folder then replace all codes with this.

<!DOCTYPE HTML>
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="default">
    <head>
        <title>Edit Product</title>
    </head>
    <body>
        <div layout:fragment="content" class="row">
            <div class="col-xs-8 col-md-8">
                <h3>
                    <a href="/product" class="btn btn-lg btn-primary"><span class="glyphicon glyphicon-list"></span> Product</a>
                </h3>
                <h2>Edit Product</h2>
                <form action="/update">
                    <div class="form-group">
                        <label for="email">Product Name:</label>
                        <input type="text" class="form-control" name="prodName" th:value="${product.prodName}" />
                    </div>
                    <div class="form-group">
                        <label for="email">Product Description</label>
                        <textarea class="form-control" name="prodDesc" cols="60" rows="3" th:text="${product.prodDesc}"></textarea>
                    </div>
                    <div class="form-group">
                        <label for="email">Product Price</label>
                        <input type="number" class="form-control" name="prodPrice" th:value="${product.prodPrice}" />
                    </div>
                    <div class="form-group">
                        <label for="email">Product Image URL:</label>
                        <input type="url" class="form-control" name="prodImage" th:value="${product.prodImage}" />
                    </div>
                    <input type="hidden" name="id" th:value="${product.id}" />
                    <button type="submit" class="btn btn-success">Save</button>
                </form>
            </div>
        </div>
    </body>
</html>

Next, open and edit static HTML file Resources/static/index.html then replace all codes with this.

<!DOCTYPE HTML>
<html>
    <head>
        <title>Spring MVC Java Web App</title>
    </head>
    <body>
        <h2>Spring MVC Java Web App</h2>
        <p><a href="/product">Product List</a></p>
    </body>
</html>

This index.html is the first page that shows up on the browser after Web Application run. Next, add a little style by creating a new CSS folder inside the static folder then add a file style.css. Add these lines of CSS codes to that CSS file.

body {
  padding-top: 50px;
}
.starter-template {
  padding: 40px 15px;
  text-align: center;
}
Step #6: Run The Spring Boot Java Web App

To run the Spring Boot app inside Netbeans IDE, just click on the play button in the toolbar or right-click the project name in the Project panel then click run. It's the same as typing this command from the terminal.

./gradlew --configure-on-demand -x check bootRun

Here the full Spring Boot MVC Java web app looks like.





That it's, a quick way to create a Java web app using Spring Boot, Data, and MVC in just 5 steps. You can get the full working source code from our GitHub.

That just the basic. If you need more deep learning about Java and Spring Framework you can take the following cheap course:

Thanks!

Spring Boot Tutorials - Spring Boot Full Course

Spring Boot Tutorials - Spring Boot Full Course

Spring Boot Tutorials | Full Course - What is Spring? Spring Boot is an open source Java-based framework used to create a Micro Service. Spring Boot contains a comprehensive infrastructure support for developing a micro service and enables you to develop enterprise-ready applications that you can “just run”.

  1. What is Spring ? – 00:05
  2. Dependency Injection? – 05:34
  3. Spring Tool Suite | Spring Boot IDE – 13:40
  4. Spring, Autowire, Dependency Injection – 22:17
  5. Web App using Spring Boot – 40:39
  6. Application Properties File – 55:33
  7. Accepting Client Data – 01:00:11
  8. ModelAndView – 01:08:51
  9. Model Object – 01:16:12
  10. JPA | MVC | H2 Example – 01:20:29
  11. JPA | MVC | H2 Example Part 2 – 01:35:29
  12. Data JPA | MVC | H2 | Query Methods Example – 01:45:12
  13. Data JPA | MVC | H2 | REST Example – 01:54:43
  14. Data JPA | MVC | H2 | REST Example – 02:02:22
  15. Postman | Data JPA | MVC | H2 | REST Example – 02:06:55
  16. Content Negotiation | Data JPA | MVC | H2 | REST – 02:11:29
  17. Spring Boot | MVC | REST Post Example – 2:19:36
  18. Spring Boot | MVC | REST PUT DELETE Example – 02:27:35
  19. Spring Boot Data REST Example – 02:36:30

Spring Boot Tutorials | Full Course:- https://github.com/navinreddy20/Spring-Boot

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