I'm looking for the way to handle pre & post processing of Controller in Spring Boot + thymeleaf - spring-boot

I have been looking for the way to handle pre & post processing of controller.
I want to add a procedure for every request & response.
For example:
Checking every requested header or adding hidden field include hash code in every form tags we response.
If there is sample, or any idea,give me please.

Thanks for advice.
I was able to find the result from this page.
http://www.concretepage.com/spring/spring-mvc/spring-handlerinterceptor-annotation-example-webmvcconfigureradapter
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(InterceptorRegistry registry) {
super.addInterceptors(registry);
registry.addInterceptor(new ControllerHandler());
TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
}
}
public class ControllerHandler implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("---Before Method Execution---");
return true;
}
#Override
public void postHandle( HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("---method executed---");
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("---Request Completed---");
}
}

I found another way to do,using #ControllerAdvice.
This annotaion seems to focus Error Handling.
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html1
#ControllerAdvice
public class ExceptionControllerAdvice {
#InitBinder
public void initBinder(WebDataBinder binder) {
System.out.println("controller advice: init binder");
}
#ExceptionHandler(Exception.class)
public String exception(Exception e) {
System.out.println("controller advice: exception Handler");
System.out.println(e.getMessage());
return "error";
}
#ModelAttribute
public void modelAttribute(){
System.out.println("controller advice:model Attribute");
}
}

Related

How do I get the rest path in a HandlerInterceptorAdapter without resolved path variables

I have a problem with my RestController interceptor.
My goal is to get the RestController path in a HandlerInterceptorAdapter and then use it to create metrics.
Via the interface HttpServletRequest I have access to the path, but it is resolved there.
Example of what I would like to get in my interceptor:
GET: object/123 // wrong
GET object/{id} // right
Is there any way to get the path without resolved variables?
Here is my implementation:
RestController:
#RestController
public class ObjectController
{
#GetMapping("object/{id}")
public String getObjectById(#PathVariable String id)
{
return id;
}
}
Config:
#Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter
{
#Override
public void addInterceptors(InterceptorRegistry registry)
{
registry.addInterceptor(new RequestInterceptor());
}
}
Interceptor:
public class RequestInterceptor extends HandlerInterceptorAdapter
{
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception
{
System.out.println(request.getRequestURI());
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
#Nullable ModelAndView modelAndView) throws Exception
{
System.out.println(request.getRequestURI());
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
#Nullable Exception ex) throws Exception
{
System.out.println(request.getRequestURI());
}
}

i am trying to add interceptors to spring project,my prehandle method is not getting called

I want my prehandle method to be called.On debugging i see the control going inside ProductServiceInterceptor class but none of the methods inside are getting called
#EnableWebMvc
#Configuration
public class ProductServiceInterceptorAppConfig extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new productServiceInterceptor()).addPathPatterns("/home/*"));
}
}
#Component
public class ProductServiceInterceptor implements HandlerInterceptor {
#Override
public boolean preHandle(
HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
#Override
public void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception exception) throws Exception {}
}

Spring Boot - Pass Exception object from ResponseEntityExceptionHandler to HandlerInterceptor?

I am working on Spring Boot Example and implemented GlobalExceptionHandler and trying to print all error messages in JSON - it's my custom method.
Also, I have ExceptionHandler there I am catching all the Exception. But is there any way to pass the exception object from ResponseEntityExceptionHandler to HandlerInterceptor?
HandlerInterceptor:
#Slf4j
public class GlobalExceptionHandler implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
............
.............
..............
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
ServletRequestAttributes attributes = (ServletRequestAttributes) request.getAttribute(REQUEST_ATTRIBUTES);
ServletRequestAttributes threadAttributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
............
.............
..............
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
if(ex != null) {
printJsonReq(request, response);
}
}
}
ExceptionHandler:
#ControllerAdvice
#Slf4j
public class ExceptionHandler extends ResponseEntityExceptionHandler{
#ExceptionHandler({ResponseStatusException.class})
protected ResponseEntity<Object> handleResStatusException(Exception e, WebRequest request, HttpServletRequest httpRequest) {
ResponseStatusException be = (ResponseStatusException) e;
ErrorResource error = ErrorResource.builder().code(AppConst.BAD_REQUEST)
.message(ExceptionUtils.getDetails(e.getCause())).build();
return handleExceptionInternal(e, error, getHeaders(), HttpStatus.BAD_REQUEST, request);
}
.........
..........
.........
}
You can set it as a request attribute in ExceptionHandler class (if you need it just to be sure you are going print log then instead of passing Exception object you can pass boolean param to not load your request object)
request.setAttribute("exception", e);
And use it in your HandlerInterceptor as
if(ex != null || request.getAttribute("exception") != null) {
printJsonReq(request, response);
}
You can configure the interceptors using WebMvcConfigurerAdapter
17.15.3 Configuring Interceptors
You can configure HandlerInterceptors or WebRequestInterceptors to be applied to all incoming requests or restricted to specific URL path patterns.
An example of registering interceptors in Java:
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new GlobalExceptionHandler());
}
}

Why does the spring boot controller not invoked after calling request.getReader in preHandle

I am implementing an interceptor for logging purposes. I know once i called the getReader method on HttpServletRequest will loose the body data, but i was experimenting. So i ran the below code, and realized the controller is never invoked (Debug point is not activated) and there was no errors.
#Component
public class IncomingRequestInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String requestPayload = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
System.out.println(requestPayload);
return super.preHandle(request, response, handler);
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
super.afterCompletion(request, response, handler, ex);
}
}
And the controller
#PostMapping("/test")
public String test(#Valid #RequestBody CredentialsVo credentials) {
credentials.getUsername();
.............
return "test";
}
Filter Registration
#Configuration
public class MyConfig implements WebMvcConfigurer {
#Autowired
IncomingRequestInterceptor incomingRequestInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(incomingRequestInterceptor)
.addPathPatterns("/**");
}
}
if i do not call getReader() method, the controller is invoked. I was actually expecting the controller is called but i would get a null pointer or something like that.
Could anyone tell me how spring acts in this scenario ?

PreAuthorize error handling

I'm using Spring Oauth2 and Spring Pre-post Annotations With Spring-boot
I Have a service class MyService. one of MyService methods is:
#PreAuthorize("#id.equals(authentication.principal.id)")
public SomeResponse getExampleResponse(String id){...}
can i control in some manner the json that is returned by the caller Controller?
the json that is returned by default is:
{error : "access_denied" , error_message: ".."}
I Want to be able to control the error_message param. I'm looking for something similar to:
#PreAuthorize(value ="#id.equals(authentication.principal.id)", onError ="throw new SomeException("bad params")")
public SomeResponse getExampleResponse(String id){...}
One way i thought of doing it is by Using ExceptionHandler
#ExceptionHandler(AccessDeniedException.class)
public Response handleAccessDeniedException(Exception ex, HttpServletRequest request){
...
}
but i can't control the message of the exception. and also i can't be sure that this Exception will be thrown in future releases
Spring Boot docs on error handling: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-error-handling. One way you can control the JSON is by adding a #Bean of type ErrorAttributes.
#Bean
ErrorAttributes errorAttributes() {
return new MyErrorAttributes();
}
Implement AccessDeniedHandler
#Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
try {
ObjectMapper mapper = new ObjectMapper();
SomeJsonModel jsonResponse =new SomeJsonModel();
mapper.writeValue(response.getOutputStream(), jsonResponse);
} catch (Exception e) {
throw new ServletException();
}
}
SomeJsonModel will be your own POJO/model class which you can control
And add that access denied handler in Resource Server Configuration
#Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers()
.antMatchers(SECURED_PATTERN).and().authorizeRequests()
.antMatchers(HttpMethod.POST,SECURED_PATTERN).access(SECURED_WRITE_SCOPE)
.anyRequest().access(SECURED_READ_SCOPE).and()
.exceptionHandling().authenticationEntryPoint(newAuthExceptionEntryPoint())
.accessDeniedHandler(new MyAccessDeniedHandler());
}
It was not working for me when I implemented AccessDeniedHandler. So I created a ExceptionHandler function inside AuthenticationEntryPoint and marked the class as
#ControllerAdvice.
Please find the code below
#ControllerAdvice
#Component
public class EmrExceptionHandler implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(EmrExceptionHandler.class);
#Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
AuthenticationException authException) throws IOException, ServletException {
logger.error("Unauthorized error: {}", authException.getMessage());
httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
httpServletResponse.getWriter().write(convertObjectToJson(new ErrorResponse(ResponseMessages.NOT_AUTHORIZED)));
}
#ExceptionHandler(value = {AccessDeniedException.class})
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
AccessDeniedException accessDeniedException) throws IOException {
logger.error("AccessDenied error: {}", accessDeniedException.getMessage());
httpServletResponse.setStatus(HttpStatus.FORBIDDEN.value());
httpServletResponse.getWriter().write(convertObjectToJson(new ErrorResponse(ResponseMessages.NOT_PERMITTED)));
}
public String convertObjectToJson(Object object) throws JsonProcessingException {
if (object == null) {
return null;
}
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(object);
}
}

Resources