Back to: Spring Boot Tutorials
Spring Boot AOP Other Implementations
In this article, I am going to discuss Spring Boot AOP Other Implementations. Please read our previous article where we discussed Spring Boot AOP Before Implementation.
Spring Boot AOP Other Implementations
In the previous article, we implemented the before AOP aspect. Here we shall implement the following aspects:
- After Advice
- Around Advice
- Returning Advice
- Throwing Advice
Step 1: Open the project from the previous project in VS Code. The file structure must be as follows:
Step 2: Modify FruitServiceAspect.java class to add the After Advice aspect:
This method shall execute after the advice has been sent.
Step 3: Modify FruitServiceAspect.java class to add the Around Advice aspect:
This method shall execute when the advice is being sent, i.e., when the getFruits() method is executing.
Step 4: Modify the FruitServiceAspect.java class to add the After Returning Advice aspect:
This method shall execute after the getFruits() method finishes execution.
Step 5: Modify the FruitServiceAspect.java class to add the After Throwing Advice aspect:
This method shall execute when the getFruits() method throws an error.
Step 6: Compile and execute the application. Ensure compilation is successful:
Step 7: Go to the webpage http://localhost:8080/view-products from your browser. The following output must be visible:
In the VS Code terminal, the following output must be visible:
We can see from the output that all the functions execute, except for the afterThrowing() method. As mentioned above, the afterThrowing() method executes only when the getFruits() throws an exception. In this case, getFruits() does not throw an exception. Congratulations! You now know how to implement AOP in Spring Boot!
The Complete Example Code:
Fruits.java – The POJO class
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 – The class responsible for handling the CRUD operations.
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(); }
FruitServiceAspect.java – The file containing the AOP code.
package com.dotnet.restful; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect @Component public class FruitServiceAspect { //Before AOP for getFruits(); @Before(value = "execution(* com.dotnet.restful.FruitService.*(..)) and args()") public void beforeAdvice(JoinPoint joinPoint) { System.out.println("Before advice: " + joinPoint.getSignature()); } @After(value = "execution(* com.dotnet.restful.FruitService.*(..)) and args()") public void afterAdvice(JoinPoint joinPoint) { System.out.println("After method: " + joinPoint.getSignature()); } @Around(value = "execution(* com.dotnet.restful.FruitService.*(..)) and args()") public void aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("Around advice (before invoking method): " + joinPoint.getSignature().getName()); try { joinPoint.proceed(); } finally { } System.out.println("Around advice (after invoking method): " + joinPoint.getSignature().getName()); } @AfterReturning(value = "execution(* com.dotnet.restful.FruitService.*(..))", returning = "fruits") public void afterReturningAdvice(JoinPoint joinPoint) { System.out.println("After returning method: " + joinPoint.getSignature()); } @AfterThrowing(value = "execution(* com.dotnet.restful.FruitService.*(..))", throwing = "ex") public void afterThrowingAdvice(JoinPoint joinPoint, Exception ex) { System.out.println("After throwing exception in method: " + joinPoint.getSignature()); System.out.println("The exception is: " + ex.getMessage()); } }
FruitServiceController.java – The class responsible for providing the REST API.
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 – The class in which the CRUD operations occur.
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); } }
RestfulApplication.java – The class containing the main() function.
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 – The class responsible for providing web services.
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 Introduction to Spring Boot JPA. Here, in this article, I try to explain Spring Boot AOP Other Implementations with Examples. I hope you enjoy this Spring Boot AOP Other Implementations article.