Reputation: 165
I've just started to use spring boot for my services. I have few controllers that use same code in their bodies. for example in every controller I have to check if request object obtained from request is null or not:
if (request == null){
throw new InvalidRequestException("the request object is null");
}
I know that repeating code in several controllers is not a good approach, so I was wondering if there is a way to prevent code repetition, or if spring boot has a solution for the mentioned problem.
Upvotes: 3
Views: 1489
Reputation: 689
Better to use @Valid to check the payload, without checking it manually. Please follow the below explanation.
You can use "import org.springframework.validation.Errors;" and @Valid as below.
@PostMapping("/test")
public ResponseEntity<String> editStatus(@Valid @RequestBody Person person, Errors errors) {
String responseMessage;
if(errors.hasErrors()) {
responseMessage = "'" + errors.getFieldError().getField() + "' " + errors.getFieldError().getDefaultMessage();
} else {
// You can do ur logic here
responseMessage = "result";
}
return ResponseEntity.accepted().body(responseMessage);
}
Person payload you can validate as below.
public class Person {
@NotNull
private String firstName;
@NotNull
private String lastName;
private String city;
//Getter
//Setter
}
In this explanation, I used Person payload. @Valid check the payload content. Once you receive payload without mandatory fields, you can handle the situation using errors.
Upvotes: 0
Reputation: 976
I agree to @Niraj Sonawane to use the @Validated annotation to deal with the specific case given in the post.
To add to that, using filters may be another option to deal with the cases that fall into "pre-requisite-to-perform-controller-actions". We were using a complex logic to resolve access permissions which were required by all the controllers we had in the design. And, we used a filter to handle that.
Upvotes: 0
Reputation: 574
Spring AOP?
create a Aspect class like this:
@Aspect
class AopDemo{
@Around("execution(* com.demo.controller.*(..))")
public Object release(JoinPoint jp){
try{
Object[] args = jp.getArgs();
for(Object arg: args){
if(arg == null){
throw new InvalidRequestException("the request object is null");
}
}
return jp.proceed(args);
}catch(InvalidRequestException ire){
// handle InvalidRequestException
}catch(Exception ex){
// handle Exception
}
}
}
Upvotes: 0
Reputation: 3059
You are using SpringBoot, so in your application, where you define @SpringBootApplication
annotation, you can specify the next @Bean
:
@Bean
public HttpRequestHandler httpRequestHandler () {
return new MyHttpRequestHandler();
}
Also create MyHttpRequestHandler
class, where you can make any your logic with that:
public class MyHttpRequestHandler implements HttpRequestHandler {
@Override
public void handleRequest (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (request == null) {
throw new InvalidRequestException("the request object is null");
}
}
}
Upvotes: 4
Reputation: 11115
Basically what you are doing is parameter validation. This is is kind of cross cutting concerns and perfect use case for using AOP approach.
Spring provide very nice way of doing this
you can simply use @validate
like this
@PostMapping
public ResponseEntity<Void> someMEthod(@Validated(CustomChecks.class) @RequestBody request yourRequest)
Then you can put all your validation logic inside CustomChecks class. (You can find number of examples)
if you have very small and general purpose validations then you can also use annotations.
in your case simply put @NotNull annotation on your request class. Check this example
hope this helps
Upvotes: 1
Reputation: 977
One approach is to create an abstract class that will contain a wrapping method that will be called by the extending controller.
public abstract class CoreController {
protected void validateRequest(MyRequest request) {
if (request == null) throw new InvalidRequestException("the request object is null");
}
}
Extend your controllers with this class and call the validateRequest
method
public class MyController extends CoreController {
@PostMapping("/some_endpoint")
public MyResponse endpointMethod (@RequestBody MyRequest request) {
validateRequest(request);
...
return new MyResponse();
}
}
Upvotes: 0
Reputation: 591
Make your service layer throw custom exceptions according to your conditions and use a @ControllerAdvice in your Controller to handle the output when exceptions are thrown.
Upvotes: 0
Reputation: 3393
Just wrap that code in a method:
protected void checkRequest(Object request){
if (request == null){
throw new InvalidRequestException("the request object is null");
}
}
and declare it in an AbstractController
class. Let your controllers extend this class.
Upvotes: 0