Spring Boot HandBook

    Introduction#


    A Spring Boot application integrates several Spring projects, simplifying the development of Java applications. Here's a brief introduction to its main components:

    1. Spring Boot Web MVC:
      • Spring Boot Web MVC simplifies web development by providing an out-of-the-box setup for creating web applications. It follows the Model-View-Controller (MVC) pattern to separate concerns:
        • Model handles data (e.g., entities or domain objects).
        • View manages the UI (e.g., Thymeleaf, JSP).
        • Controller processes requests and returns views or data.
      • Spring Boot automatically configures essential components like embedded web servers (e.g., Tomcat) and provides easy handling of RESTful endpoints.
    2. Spring Boot Data JPA:
      • Spring Boot Data JPA simplifies data access and interaction with relational databases by integrating JPA (Java Persistence API). It provides easy CRUD operations, pagination, and query methods.
      • JpaRepository offers built-in methods for interacting with the database, while custom query methods can be created with query derivation or JPQL.

    Build A Spring Boot Application#

    1. Go to https://start.spring.io/, configure the necessary project settings as shown in the image, add the required dependencies, and generate the application as a ZIP file.

    1. After that, go to File Explorer > Downloads, and extract the ZIP file.
    2. After that, open the project in your preferred IDE. Here, we are using IntelliJ IDEA.
    3. After opening the project, the first thing we need to do is reload Maven.

    4. Now, let's add some packages. To do this, navigate to src > main > java > <group package> . After that, right-click on <group package>, select New > Package or Java Class, and create the necessary packages and classes.

    5. In the same way, you can create different classes, interfaces, enums, and packages within your specific package.


       

    Dto Class

    Here, we are using @AllArgsConstructor and @NoArgsConstructor. These constructors are required by Jackson to convert JSON into DTO classes.

    package com.example.user.product_ready_features.product_ready_features.dtos; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor public class ProductDto { private Long id; private String title; private String description; }

    Entity Class

    Here, we are using @AllArgsConstructor and @NoArgsConstructor because Hibernate requires these constructors to create entities and map database tables to entity objects.

    package com.example.user.product_ready_features.product_ready_features.entities; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @Entity @Getter @Setter @AllArgsConstructor @NoArgsConstructor @Table(name = "Products") public class ProductEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String title; private String description; }

    Repository Interface

    This repository interface extends JpaRepository<ProductEntity, Long>, where ProductEntity is the entity type and Long is the type of the entity's ID.

    package com.example.user.product_ready_features.product_ready_features.repositories; import com.example.user.product_ready_features.product_ready_features.entities.ProductEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface ProductRepository extends JpaRepository<ProductEntity,Long> { }

    Controller Class

    package com.example.user.product_ready_features.product_ready_features.controllers; import com.example.user.product_ready_features.product_ready_features.dtos.ProductDto; import com.example.user.product_ready_features.product_ready_features.services.ProductService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequiredArgsConstructor @RequestMapping("/products") public class ProductController { private final ProductService productService; @GetMapping public List<ProductDto> getAllProducts(){ return productService.getAllProducts(); } @GetMapping("/{id}") public ProductDto getProductById(@PathVariable Long id){ return productService.getProductById(id); } @PostMapping public ProductDto createNewProduct(@RequestBody ProductDto input){ return productService.createNewProduct(input); } }

    Service Class

    Here, we need to create the necessary constructor, or we can use @RequiredArgsConstructor from Lombok, which automatically generates the required constructors for us.

    package com.example.user.product_ready_features.product_ready_features.services; import com.example.user.product_ready_features.product_ready_features.dtos.ProductDto; import com.example.user.product_ready_features.product_ready_features.entities.ProductEntity; import com.example.user.product_ready_features.product_ready_features.exceptions.ResourceNotFoundException; import com.example.user.product_ready_features.product_ready_features.repositories.ProductRepository; import lombok.RequiredArgsConstructor; import org.modelmapper.ModelMapper; import org.springframework.stereotype.Service; import java.util.List; import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class ProductService { private final ProductRepository productRepository; private final ModelMapper modelMapper; public List<ProductDto> getAllProducts(){ return productRepository.findAll() .stream().map(productEntity -> modelMapper.map(productEntity,ProductDto.class)) .collect(Collectors.toList()); } public ProductDto createNewProduct(ProductDto input){ ProductEntity productEntity = modelMapper.map(input,ProductEntity.class); ProductEntity savedProductEntity = productRepository.save(productEntity); return modelMapper.map(savedProductEntity,ProductDto.class); } public ProductDto getProductById(Long id) { ProductEntity productEntity = productRepository.findById(id) .orElseThrow(()->new ResourceNotFoundException("Product not found with id: "+id)); return modelMapper.map(productEntity,ProductDto.class); } }

    Here, we use the DTO class for business logic, and we need to convert it to an Entity class. To do this, you should add the ModelMapper dependency and configure it as a bean.

    Here, we need to handle all exceptions by creating custom exception classes.
     

    Add dependency

    Go to https://mvnrepository.com/artifact/org.modelmapper/modelmapper and copy the dependency for the latest version.

    Add it in dependencies section of your Pom.xml file and after adding it, reload your maven.

    <!-- https://mvnrepository.com/artifact/org.modelmapper/modelmapper --> <dependency> <groupId>org.modelmapper</groupId> <artifactId>modelmapper</artifactId> <version>3.2.1</version> </dependency

    Configuration Class

    package com.example.user.product_ready_features.product_ready_features.configs; import org.modelmapper.ModelMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MapperConfig { @Bean ModelMapper getMapper(){ return new ModelMapper(); } }

    Custom Exception Class

    package com.example.user.product_ready_features.product_ready_features.exceptions; public class ResourceNotFoundException extends RuntimeException{ public ResourceNotFoundException(String message) { super(message); } }

    Dependencies and Plugins

    <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.modelmapper/modelmapper --> <dependency> <groupId>org.modelmapper</groupId> <artifactId>modelmapper</artifactId> <version>3.2.1</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build>

    Database Setup#

    To store our data, we need to connect to a real database (e.g., MySQL, PostgreSQL). We can familiarize ourselves with industry-standard practices using applications like DBeaver. While there are several other applications available for connecting to multiple databases and running queries, DBeaver is popular among developers due to its versatility. Let’s explore how to use it after installing the software.

    Installing MySql

    Visit Setting up MySQL db with Spring Data JPA page and for further guides you can check https://www.dataquest.io/blog/install-mysql-windows/

    Installing DBeaver

    How to Connect to a Database in DBeaver:#

    • Open DBeaver application

    • Go to New Database Connection and select the database you want to connect to

    • Here, we have created a new database connection (MySQL) and clicked the Next button.

    • Here, you enter the password.

    • Click ‘Test Connection’. After testing, you will see a pop-up like the image. Press ‘OK.’

    • After that, check ‘Database Navigator’; you should see the localhost:3306 (MySQL) connection.

    • You need to check every time whether the connection is established. Essentially, ‘the green tick’ indicates that you are connected.

    • If you see nothing, that means you are disconnected, and you will need to reconnect. To do this, right-click on it, and you will see the ‘Connect’ option.

    • If you see a ‘red cross,’ that means you need to log in to MySQL again using the MySQL command line. After that, you can reconnect.

    How to Create a Database in DBeaver:#

    • After connecting to MySQL, you can go to localhost:3306 > Databases. Right-click on Databases to create new databases.

    • Go to ‘Create New Database,’ and enter the name of the database you want to create, then press ‘OK.’

    Application Configure Database Connection#

    This configuration is crucial for connecting a Spring application to a MySQL database, defining how Hibernate interacts with that database, and providing useful logging for development. Adjustments should be made for production environments, especially concerning security and schema management. If you have specific areas you want to delve deeper into, let me know!

    Go to resources > application.properties or resources > application.yml

    Application Properties

    spring.application.name

    spring.application.name=product_ready_features

    Purpose: Sets the name of the Spring application. This name can be useful for logging, monitoring, and managing different services in a microservices architecture.

    Database Configuration

    1. spring.datasource.url

    spring.datasource.url=jdbc:mysql://localhost:3306/<Your Database Name>?useSSL=false

    Purpose: Specifies the URL for the database connection. In this case:

    • jdbc:mysql:// indicates that the application will use the MySQL JDBC driver.
    • localhost:3306 refers to the database server running on the local machine at port 3306 (the default port for MySQL).
    • /<Your Database Name> is the name of the database to connect to.
    • ?useSSL=false disables SSL for the connection, which can be useful in a development environment where SSL is not set up.
    1. spring.datasource.username

    spring.datasource.username=root

    Purpose: Specifies the username to connect to the database. In this case, it is set to root, which is the default administrative user for MySQL.

    1. spring.datasource.password

    spring.datasource.password=<your mysql login password>

    Purpose: Sets the password for the specified username to connect to the database. Ensure that sensitive information like passwords is handled securely (e.g., using environment variables or a secrets management tool).

    1. JPA Configuration
      1. spring.jpa.hibernate.ddl-auto

    spring.jpa.hibernate.ddl-auto=create

    Purpose

    : Configures the behavior of the Hibernate framework regarding the database schema:

    • create: Drops the existing schema and creates a new one on application startup. This is useful during development but should be changed to update or none in production to avoid data loss.

    spring.jpa.show-sql

    spring.jpa.show-sql=true

    Purpose: Enables the logging of SQL statements generated by Hibernate. This is useful for debugging and understanding what queries are being executed against the database.

    spring.jpa.properties.hibernate.format_sql

    spring.jpa.properties.hibernate.format_sql=true

    Purpose: Formats the SQL output for better readability in the logs. When set to true, it indents the SQL statements, making it easier to read in the log files.

    Run Application#

    Go to main application file and go to run button to run it.

    Output#

    • Output of IDE Console:

    • Output of Postman Console:
      • For creating a new product, getting all products, getting product by product id, we are basically sending the request through Postman.
        • Create New Product

        • Get All Products

        • Get Product By Id
          • If the ID is present, the product is displayed.

          • If the ID is not present, an internal server error is returned.

    • To handle this server-related exception, we need to create a custom exception handler class (GlobalExceptionHandler).
       
    • ApiError Class
    package com.example.user.product_ready_features.product_ready_features.advices; import lombok.Data; import org.springframework.http.HttpStatus; import java.time.LocalDateTime; @Data public class ApiError { private LocalDateTime timestamp; private String error; private HttpStatus status; public ApiError() { this.timestamp = LocalDateTime.now(); } public ApiError(String error, HttpStatus status) { this(); this.error = error; this.status = status; } }
    • GlobalExceptionHandler
    package com.example.user.product_ready_features.product_ready_features.advices; import com.example.user.product_ready_features.product_ready_features.exceptions.ResourceNotFoundException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ResourceNotFoundException.class) public ResponseEntity<ApiError> handleResourceNotFoundException(ResourceNotFoundException ex){ ApiError apiError = new ApiError(ex.getLocalizedMessage(), HttpStatus.NOT_FOUND); return new ResponseEntity<>(apiError,HttpStatus.NOT_FOUND); } }
    • In this class, we will specifically handle the 404 Not Found error.
    • After running the application, if you send an invalid request, it will display a 404 Not Found error.

    • Output of Database:
      • After running applications

    After creating new product. Let’s see our database.



     

    In this article, we explored the essential components of a Spring Boot application, including Spring Boot Web MVC for streamlined web development and Spring Boot Data JPA for simplified data access. We guided you through the process of setting up a Spring Boot project, creating the necessary classes such as DTOs, entities, repositories, controllers, and services, and configuring them effectively. Additionally, we discussed integrating ModelMapper for object mapping and handling custom exceptions. We also covered the crucial steps for setting up a MySQL database and connecting it to your Spring Boot application, providing you with a comprehensive overview of building a robust application with Spring Boot.

    Last updated on Oct 25, 2024