Friday, June 28, 2024

Global Exception Handling With Spring Boot


In a Spring Boot controller, things can sometimes go wrong. For example, an API consumer might not send the expected path parameter or header value. They might call the API with an invalid payload or encounter an unexpected runtime error. When these kinds of errors occur, we can use Spring Boot's Global Exception Handling mechanism to manage them and provide meaningful responses back to the API consumer.

@ExceptionHandler is used to handle exceptions in specific controllers classes and/or methods level. In a Spring Boot Restful service, errors can be handled in three different ways:

  1. Using ControllerAdvice - This annotation allows global(central) exception handling across multiple controllers.
  2. Using @ExceptionHandler at each controller level - For more granular control
  3. Returning ResponseEntity with the appropriate status code

In this post, I will explain how to implement Global Exception Handling in a Spring Boot RESTful service. 

Wednesday, June 26, 2024

Spring Boot Key Annotations With Examples

 When developing a RESTful service (REST API) using Spring Boot, need to have clear understanding of some of the annotations provided by Spring Boot Web. 


@RestController - RestController is class level annotation used to define a class as a rest full service and it also combines @Controller and @ResponseBody annotations. So the response object is automatically serialised into JSON format.  

@RequestMapping - RequestMapping is used to map web requests to a specific controller or method. For RESTful services, the RequestMapping annotation is typically used at the class level, with HTTP method-specific annotations used at the method level.

@GetMapping, @PostMapping, @PutMapping, @DeleteMapping @PatchMapping- These are specialised versions of the @RequestMapping annotation. they are mostly used at the method level to map HTTP methods. These annotations improve code readability and maintainability as well. 

Saturday, June 22, 2024

Integrate Swagger 3 with Spring Boot Rest API

 What is Swagger:

Swagger (now known as OpenAPI) is a specification for describing and documenting a REST API. It specifies the format of the REST web services including URL, resources, methods, etc. Swagger generates documentation from the application code and handles the rendering part as well.

In this post, I will integrate Swagger 3 documentation into a Spring Boot 3 based REST web service using Spring Doc OpenAPI. If you need guidance on running or building a Spring Boot project, please refer to my previous post.

Thursday, June 20, 2024

Building a RESTful Service with Spring Boot 3

 This blog post is an upgraded version of my 2017 guide on building RESTful services using Spring Boot. It includes updates for the latest Spring Boot version, best practices, and enhanced code examples. 

Creating Spring boot project is straightforward, You can create the structure of your project using "Spring Initialiser," an online tool where you can add all the desired dependencies to your project's POM file. Since I am a big fan of Maven, I generated a Maven project.

In the Spring Initializer UI, you can choose the Language, Spring Boot Version, Project Group ID, artifact name, etc. Please refer below screenshot for information I have provided while generating the project.


Spring Initialiser

When clicking on "Generate Project", it will download zipped maven project into your computer. Unzip it and import into an IDE. The initial project structure is like below.

Spring Boot Project Structure

In my HelloWorld REST service implementation, it accepts user's name as a path parameter(or URL parameter) and returns a greeting JSON payload(response). So I am expecting to invoke my REST service by calling below URL: APP_NAME/api/hello/chandana.

The @RestController is a way to implement RESTFul service using Spring. So, this new controller class is going to name as HelloWorldController. @RequestMapping annotation maps HTTP requests to the handler. This @RequestMapping annotation can be used in class-level and/or method-level as well. If you have multiple request mappings for a method or class, you can add one @RequestMapping annotation with a list of values. So my HelloWorldController class looks like below.

package com.chandana.helloworld;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class HelloWorldController {
    @RequestMapping("/")
    public String welcome() {// Welcome page, non-rest
        return "Welcome to RestTemplate Example.";
    }

    @RequestMapping("/hello/{name}")
    public Greeting message(@PathVariable String name) {
        Greeting msg = new Greeting(name, "Hello " + name);
        return msg;
    }

    @GetMapping("/greeting/{name}/{message}")
    public Greeting message(@PathVariable String name, @PathVariable String message) {
        Greeting msg = new Greeting(name, message);
        return msg;
    }

}


You can use @GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping annotations as well, these are variation of @RequestMapping to support each HTTP methods. 


So everything is in place. you can build and run Spring Boot project using below maven command. It will compile the project and run it.

mvn spring-boot:run

Once the Spring Boot DispatcherServlet is started, you can invoke the following API URLs:

http://localhost:8080/api/hello/Alex - This API supports all HTTP methods.
http://localhost:8080/api/greeting/Alex/WelCome - This API only supports the HTTP GET method.


Final Project Structure:

Spring Boot Final Project Structure

Greeting POJO class:

package com.chandana.helloworld;

public class Greeting {
    private String player;
    private String message;

    public Greeting(String player, String message) {
        this.player = player;
        this.message = message;
    }

    public String getPlayer() {
        return player;
    }

    public void setPlayer(String player) {
        this.player = player;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}


POM XML:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.0</version>
        <relativePath/>
        <!-- lookup parent from repository -->
    </parent>
    <groupId>com.chandana</groupId>
    <artifactId>helloworld</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Hello World</name>
    <description>Demo project for Spring Boot</description>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>


HelloWorldController class: 

package com.chandana.helloworld;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class HelloWorldController {
    @RequestMapping("/")
    public String welcome() {// Welcome page, non-rest
        return "Welcome to RestTemplate Example.";
    }

    @RequestMapping("/hello/{name}")
    public Greeting message(@PathVariable String name) {
        Greeting msg = new Greeting(name, "Hello " + name);
        return msg;
    }

    @GetMapping("/greeting/{name}/{message}")
    public Greeting message(@PathVariable String name, @PathVariable String message) {
        Greeting msg = new Greeting(name, message);
        return msg;
    }

}


Please refrain from copying content to other websites

View Counts


Followers