Spring Boot Service Components

Spring Boot Service Components

In this article, I am going to discuss Spring Boot Service Components with Examples. Please read our previous article where we discussed Spring Boot File Handling.

What are Spring Boot Service Components?

Service components are class files that have the @Service annotation. These class files are used to write business logic. This is the logic that makes the connection between the end-user and the database.

How to Implement Service Components in Spring Boot?

For this project, we shall create two extra classes, one is the interface, which contains abstract functions. Another class implements this interface and adds logic to the functions. For this exercise, we shall be using the same fruit project we have used before.

In one of our previous exercises, we added some files, such as FruitExceptionController.java and FruitNotFoundException.java. These classes may remain, because they shall not interfere with the service components. The current file structure should be:

How to Implement Service Components in Spring Boot?

Until now, we have implemented our business logic in the REST controller class itself. However, this is not a correct modularised programming practice. Hence, we shall create a new class to handle the business logic and make calls from the REST controller class to this class.

Step 1: Create a new interface with the name FruitService.java in the src/main/java/com/dotnet/restful folder.

Step 2: Modify the newly created file as follows:

How to Implement Service Components in Spring Boot?

We have performed the following modifications:

  1. Imported the Collection package
  2. Changed the type of file from class to interface. When initializing the class, VS Code automatically sets the type of file to the class. It can be changed manually by replacing the class keyword with the interface keyword.
  3. Added four prototype functions: these functions are able to create, update and delete fruits from the application. Also, there is a function to retrieve the list of fruits.

Step 3: Create a file called FruitServiceImpl.java in the src/main/java/com/dotnet/restful directory.

Step 4: Import the following packages into the newly created class:

How to Implement Service Components in Spring Boot?

Step 5: Add the @Service annotation to the class.

Step 6: Modify the code as follows:

How to Implement Service Components in Spring Boot?

The following modifications are performed:

  1. Created a new repository of fruits and initialized it.
  2. Coded all of the prototype functions from the interface.

Step 7: Update the FruitServiceController.java class to use the newly created methods.

The class should look as follows as of now:

How to Implement Service Components in Spring Boot?

Change it to the following:

Spring Boot Service Components with Examples

We have performed the following modifications:

  1. Created an autowired FruitService variable that will handle the business logic.
  2. Updated all functions to use the newly created functions.
  3. Removed the Map initialization in the ProductServiceController.java file.
  4. Removed packages that were no longer required.

Step 8: Save and compile the program. Ensure the compilation is successful.

Spring Boot Service Components with Examples

Step 9: Open Postman and test the functions that we have implemented. Try a GET, PUT, POST, and DELETE request. All of them should work as before.

The GET request URL is http://localhost:8080/products. This must send the reply:

Spring Boot Service Components with Examples

The PUT request URL is http://localhost:8080/products/<id>, where <id> must be populated with the id of the product which is to be updated. The body must contain the ID and new name of the fruit. The reply should be:

Spring Boot Service Components

The POST request URL is http://localhost:8080/products. The body must contain the ID and name of the new fruit. The reply should be:

Spring Boot Service Components

The DELETE request URL is http://localhost:8080/products/<id>. The body must be empty. The reply should be:

Spring Boot Service Components

Congratulations! You have now learned how to implement service components in Spring Boot!

The Complete Example Code
FruitExceptionController.java
package com.dotnet.restful;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class FruitExceptionController
{
    @ExceptionHandler(value = FruitNotFoundException.class)
    public ResponseEntity<Object> exception (FruitNotFoundException e)
    {
        return new ResponseEntity<>("Fruit not found!", HttpStatus.NOT_FOUND);
    }
}
FruitNotFoundException.java
package com.dotnet.restful;

public class FruitNotFoundException extends RuntimeException
{

}
Fruits.java
package com.dotnet.restful;

public class Fruits {
    private String id;
    private String name;
 
    public String getId()               {return id;}
    public void setId(String id)        {this.id = id;}
    public String getName()             {return name;}
    public void setName(String name)    {this.name = name;}

    public Fruits (String nid, String nname)
    {
        id = nid;
        name = nname;
    }
 }
FruitService.java
package com.dotnet.restful;

import java.util.Collection;

public interface FruitService
{
    public abstract void createFruit (Fruits fruits);
    public abstract void updateFruit (String id, Fruits fruits);
    public abstract void deleteFruit (String id);
    public abstract Collection<Fruits> getFruits();
}
FruitServiceController.java
package com.dotnet.restful;

import org.springframework.beans.factory.annotation.Autowired;
//Required web classes
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FruitServiceController
{
   @Autowired
   FruitService fruitService;

   @RequestMapping(value = "/products")
   public ResponseEntity<Object> getProduct() {
      return new ResponseEntity<>(fruitService.getFruits(), HttpStatus.OK);
   }

   @RequestMapping(value = "/products/{id}", method = RequestMethod.PUT)
   public ResponseEntity<Object> updateProduct(@PathVariable("id") String id, @RequestBody Fruits fruits)
   { 
      fruitService.updateFruit(id, fruits);
      return new ResponseEntity<>("Fruit is updated!", HttpStatus.OK);
   }
   
   @RequestMapping(value = "/products/{id}", method = RequestMethod.DELETE)
   public ResponseEntity<Object> delete(@PathVariable("id") String id)
   {
      fruitService.deleteFruit(id);
      return new ResponseEntity<>("Fruit is deleted!", HttpStatus.OK);
   }
   
   @RequestMapping(value = "/products", method = RequestMethod.POST)
   public ResponseEntity<Object> createProduct(@RequestBody Fruits product)
   {
      fruitService.createFruit(product);
      return new ResponseEntity<>("Fruit is created!", HttpStatus.CREATED);
   }
}
FruitServiceImpl.java
package com.dotnet.restful;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Service;

@Service
public class FruitServiceImpl implements FruitService
{
    private static Map<String,Fruits> database = new HashMap<>();
    static {
        Fruits apple = new Fruits("1","Apple");
        database.put(apple.getId(), apple);
  
        Fruits banana = new Fruits("2","Banana");
        database.put(banana.getId(), banana);
  
        Fruits chiku = new Fruits("3","Chiku");
        database.put(chiku.getId(), chiku);
  
        Fruits dragon = new Fruits("4","Dragon Fruit");
        database.put(dragon.getId(), dragon);
     }

    @Override
    public void createFruit(Fruits fruits)  {database.put(fruits.getId(), fruits);}
    @Override
    public void deleteFruit(String id)      {database.remove(id);}
    @Override
    public Collection<Fruits> getFruits()   {return database.values();}

    @Override
    public void updateFruit(String id, Fruits fruits)
    {
        database.remove(id);
        fruits.setId(id);
        database.put(id, fruits);
    }
}
FruitServiceInterceptor.java
package com.dotnet.restful;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@Component
public class FruitServiceInterceptor implements HandlerInterceptor
{
    @Override
    public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
    {
        System.out.println("In the preHandle() method: Before sending request to controller.");
        return true;
    }

    @Override
    public void postHandle (HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception
    {
        System.out.println("In the postHandle() method: Before sending response to client.");
    }

    @Override
    public void afterCompletion (HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) throws Exception
    {
        System.out.println("In the afterCompletion() method: After sending response to client.");
    }
}
FruitServiceInterceptorAppConfig.java
package com.dotnet.restful;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Component
public class FruitServiceInterceptorAppConfig implements WebMvcConfigurer
{
   @Autowired
   FruitServiceInterceptor fruitServiceInterceptor;

   @Override
   public void addInterceptors (InterceptorRegistry registry)
   {
      registry.addInterceptor(fruitServiceInterceptor);
   }
}
RestfulApplication.java
package com.dotnet.restful;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class RestfulApplication {

    public static void main(String[] args) {
        SpringApplication.run(RestfulApplication.class, args);
    }

    @Bean
    public RestTemplate getRestTemplate ()
    {
        return new RestTemplate();
    }
}
WebController.java
package com.dotnet.restful;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class WebController
{
    @RequestMapping(value = "/view-products")
    public String viewProducts()    {return "view-products";}

    @RequestMapping(value = "/add-products")
    public String addProducts()    {return "add-products";}
}
add-products.html
<!DOCTYPE html>
<html>
   <head>
      <title>Add Products</title>
      <script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
      
      <script>
         $(document).ready(function() {
            $("button").click(function() {
               var productmodel = {
                  id : "5",
                  name : "Fig"
               };
               var requestJSON = JSON.stringify(productmodel);
               $.ajax({
                  type : "POST",
                  url : "http://localhost:8080/products",
                  headers : {
                     "Content-Type" : "application/json"
                  },
                  data : requestJSON,
                  success : function(data) {
                     alert(data);
                  },
                  error : function(data) {
                  }
               });
            });
         });
      </script>
   </head>
   
   <body>
      <button>Click here to submit the form</button>
   </body>
</html>
view-products.html
<!DOCTYPE html>
<html>
   <head>
      <title>View Products</title>
      <script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

      <script>
         $(document).ready(function(){
            $.getJSON("http://localhost:8080/products", function(result){
               $.each(result, function(key,value) {
                  $("#productsJson").append(value.id+" "+value.name+" ");
               }); 
            });
         });
      </script>
   </head>
   
   <body>
        <h1>Fruits: </h1>
        <div id = "productsJson"> </div>
   </body>
</html>

In the next article, I am going to discuss Spring Boot Thymeleaf with Examples. Here, in this article, I try to explain Spring Boot Service Components with Examples. I hope you enjoy this Spring Boot Service Components article.

Leave a Reply

Your email address will not be published. Required fields are marked *