banner



How To Handle Exceptions In Restful Web Service

When you develop a Spring Bool RESTful service, you as a programmer are responsible for handling exceptions in the service. For instance, by properly treatment exceptions, you tin end the disruption of the normal menstruum of the application. In addition, proper exception treatment ensures that the code doesn't break when an exception occurs.

Another important thing is to ensure as a programmer is not to send whatsoever exceptions or error stacks to clients. Exception and error letters sent to clients should be brusque and meaningful.

In this postal service, I will explain how to gracefully handle exceptions in Jump Boot RESTful services.

Dependency

For this post, nosotros will create a Sprinfg Boot RESTful service that performs CRUD operations on Blog entities. We will use embedded H2 as the database. The following code shows the dependencies of the application in the pom.xml file.

          <dependency>         <groupId>org.springframework.boot</groupId>         <artifactId>spring-boot-starter-spider web</artifactId>      </dependency>       <dependency>         <groupId>org.springframework.boot</groupId>         <artifactId>bound-boot-starter-data-jpa</artifactId>      </dependency>       <dependency>         <groupId>com.h2database</groupId>         <artifactId>h2</artifactId>         <version>one.iv.200</version>      </dependency>        

Exception Handling in Jump Instance

In the context of our Blog RESTful service, the awarding may encounter several types of exceptions. For case, the database may be downward. Another scenario can be a user trying to save an already existing web log. Or a user trying to access a weblog nonetheless to be published.

Y'all should handle such scenarios gracefully in the application.

As an example, for database failure, the awarding throws SQLException. Instead of returning the exception stack trace to client, you should return a meaningful exception message.

The Entity Class

The code for the Weblog Entity course is this.

Blog.java

@Entity public class Weblog {     @Id     private int blogId;     individual String blogTitle;     individual Cord blogCreator;     private int yearOfPost; // No-Args and Parametrized Constructor //Getters and Setters }

It is a JPA Entity form annotated with the @Entity annotation and corresponding getters and setters for the fields.

The Repository

This is the Blog Repository Interface.

BlogRepository.java

package org.springframework.guru.repository;  import org.springframework.guru.model.Web log; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository;  @Repository public interface BlogRepository extends CrudRepository<Blog,Integer> { }        

Here, the BlogRepository extends the CrudRepository of Spring Data JPA.

Custom Exception Classes

In our application, we volition create custom exception classes. Such classes enable us to customize an exception according to the callers' needs.

Nosotros will create 2 custom exception classes:

  • BlogAlreadyExistsException: Is thrown when a user tries to add an already existing blog.
  • BlogNotFoundException: Is thrown when a user tries to admission a weblog that is not nowadays.

The code of the BlogAlreadyExistsException class is this.

BlogAlreadyExistsException.coffee

packet org.springframework.guru.exception;  public class BlogAlreadyExistsException extends RuntimeException {     private String message;      public BlogAlreadyExistsException(String message) {         super(bulletin);         this.message = message;     }      public BlogAlreadyExistsException() {     } }        

The code for the BlogNotFoundException class is this.

BlogNotFoundException.coffee

bundle org.springframework.guru.exception;  public class BlogNotFoundException extends RuntimeException {     private String bulletin;      public BlogNotFoundException(String message) {         super(message);         this.bulletin = message;     }      public BlogNotFoundException() {     } }        

The Service

This is the BlogService interface which has various methods to perform operations on Web log entities.

BlogService.java

package org.springframework.guru.service;  import org.springframework.guru.exception.BlogAlreadyExistsException; import org.springframework.guru.exception.BlogNotFoundException; import org.springframework.guru.model.Weblog;  import coffee.util.List;  public interface BlogService {      Blog saveBlog(Blog blog) throws BlogAlreadyExistsException;     List getAllBlogs() throws BlogNotFoundException;     Weblog getBlogById(int id) throws BlogNotFoundException; }        

In the preceding BlogService interface, the saveBlog() method declares that it throws BlogAlreadyExistsException. The 2 other methods, getAllBlogs() and getBlogById() declares that they throw BlogNotFoundException.

The service implementation class for BlogService is this.

BlogServiceImpl.coffee

@Service public form BlogServiceImpl implements BlogService {     individual BlogRepository blogRepository;      @Autowired     public BlogServiceImpl(BlogRepository blogRepository) {         this.blogRepository = blogRepository;     }      @Override     public Blog saveBlog(Web log weblog) {         if (blogRepository.existsById(blog.getBlogId())) {             throw new BlogAlreadyExistsException();         }         Blog savedBlog = blogRepository.save(blog);         return savedBlog;     }      @Override     public List getAllBlogs() {         return (List) blogRepository.findAll();     }      @Override     public Blog getBlogById(int id) throws BlogNotFoundException {         Blog blog;         if (blogRepository.findById(id).isEmpty()) {             throw new BlogNotFoundException();         } else {             blog = blogRepository.findById(id).become();         }         return blog;     } }        

The preceding BlogServiceImpl form implements the methods declared in the BlogService interface.

There are ii paths in exception handling. One is the code handles the exception using a attempt-grab block. The other is to propagate back a custom exception to the caller. The preceding service class uses the latter arroyo.

Line 12 – Line iii checks if the blog already exists in the database. If truthful the method throws a BlogAlreadyExistsException. Else, the method saves the Blog object.

Line 27 – Line 28 throws a BlogNotFoundException if the Blog with the specified Id is not nowadays in the database.

The Controller

The code for the BlogController is this.

BlogController.java

@RestController @RequestMapping("api/v1") public grade BlogController {     private BlogService blogService;      @Autowired     public BlogController(BlogService blogService) {         this.blogService = blogService;     }      @PostMapping("/blog")     public ResponseEntity saveBlog(@RequestBody Blog weblog) throws BlogAlreadyExistsException {         Blog savedBlog = blogService.saveBlog(blog);         render new ResponseEntity<>(savedBlog, HttpStatus.CREATED);      }      @GetMapping("/blogs")     public ResponseEntity<List> getAllBlogs() throws BlogNotFoundException {         return new ResponseEntity<List>((List) blogService.getAllBlogs(), HttpStatus.OK);     }      @GetMapping("weblog/{id}")     public ResponseEntity getBlogById(@PathVariable("id") int id) throws BlogNotFoundException {         return new ResponseEntity(blogService.getBlogById(id), HttpStatus.OK);     }        

The preceding controller class is not treatment the custom exceptions. Instead, it throws the exceptions back to the caller – which in our scenario is a REST client. This is not what nosotros want – straight sending back exceptions to clients.

Instead, we should handle the exception and send dorsum a brusk and meaningful exception message to the client. Nosotros tin use different approaches to accomplish this.

Approach 1: Traditional try-catch Block

The first approach is to use Coffee attempt-catch block to handle the exception in the controller methods. The code to handle BlogNotFoundException in the getBlogById() method is this.

          @GetMapping("web log/{id}") public ResponseEntity getBlogById(@PathVariable("id") int id)  {  attempt{     render new ResponseEntity(blogService.getBlogById(id), HttpStatus.OK);  } grab(BlogNotFoundException blogNotFoundException ){   return new ResponseEntity(blogNotFoundException.getMessage(), HttpStatus.CONFLICT);  }  }        

In the preceding code, the phone call to the BlogService.getBlogById() method is wrapped in a try block. If a method telephone call to getBlogById() throws BlogNotFoundException, the catch cake handles the exception. In the take hold of cake, the ResponseEntity object is used to send a custom error bulletin with a condition code every bit a response.

Approach 2: Spring @ExceptionHandler Annotation

Spring provides the @ExceptionHandlernotation to handle exceptions in specific handler classes or handler methods.

Jump configuration will discover this notation and register the method as an exception handler. The method will handle the exception and its subclasses passed to the annotation.

          @ExceptionHandler(value = BlogAlreadyExistsException.class)     public ResponseEntity handleBlogAlreadyExistsException(BlogAlreadyExistsException blogAlreadyExistsException) {         return new ResponseEntity("Blog already exists", HttpStatus.CONFLICT);     }        

When whatever method in the controller throws the BlogAlreadyExistsException exception, Jump invokes the handleBlogAlreadyExistsException() method. This method returns a ResponseEntity that wraps a custom fault message and a status lawmaking.

When you run the application and send a POST request to add an existing blog, you volition become this output.

@Exception Handler output for Blog already exists exception

Approach 3: Global Exception Handling with @ControllerAdvice

The @ExceptionHandler annotation is only active for that detail class where it is alleged. If you want a global exception handler y'all can use Spring AOP. A global exception handler provides a standard mode of handling exceptions throughout the application. In improver, it considerably reduces the corporeality of code written for exception treatment.

The Spring @ExceptionHandler forth with @ControllerAdvice of Spring AOP enables a mechanism to handle exceptions globally.

The code for the GlobalExceptionHandler class is this.

GlobalExceptionHandler.java

@ControllerAdvice public grade GlobalExceptionHandler {     @Value(value = "${information.exception.message1}")     private String message1;     @Value(value = "${data.exception.message2}")     private String message2;     @Value(value = "${data.exception.message3}")     private String message3;          @ExceptionHandler(value = BlogNotFoundException.class)     public ResponseEntity blogNotFoundException(BlogNotFoundException blogNotFoundException) {         return new ResponseEntity(message2, HttpStatus.NOT_FOUND);     }     @ExceptionHandler(value = Exception.course)     public ResponseEntity<> databaseConnectionFailsException(Exception exception) {         return new ResponseEntity<>(message3, HttpStatus.INTERNAL_SERVER_ERROR);     } }        

The @ControllerAdvice annotation in Line ane consolidates multiple @ExceptionHandlers  into a single, global exception handling component.

The @Value annotation injects exception messages specified in the application.backdrop file into the fields.

The application.properties file is this.

information.exception.message1=BlogAlreadyExists data.exception.message2=BlogNotFound data.exception.message3=DataConnectivityisLost        

Permit's send a GET Request tolocalhost:8080/api/v1/blog/2 to remember an unpublished blog. The response is shown in this Figure.

@Controller Advice Output

Yous can detect the source code of this postal service on Github

For in-depth cognition on the Spring Framework and Spring Boot, you can check my Udemy Best Seller Grade Spring Framework 5: Beginner to Guru

Spring Framework 5

Source: https://springframework.guru/exception-handling-in-spring-boot-rest-api/

Posted by: mcallisterhessium.blogspot.com

0 Response to "How To Handle Exceptions In Restful Web Service"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel