Handling Errors in a Spring Boot Controller - java

I want to process an error in the controller, I looked at how it is done, but the error is not processed, tell me what's wrong.
Controller
#ControllerAdvice
public class ErrorController {#ExceptionHandler(ResourceNotFoundException.class)
public String notFound(){
System.out.println("Hello");
return "error/not_found";
}
}
Exeption
public final class ResourceNotFoundException extends RuntimeException {
ResourceNotFoundException(String message){
super(message);
}
}
Filter where I return an error
package com.example.demo.HttpErrorConfig;
import com.example.demo.Controllers.web.ErrorController;
import com.example.demo.Exception.ResourceNotFoundException;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HttpStatusFilter extends GenericFilterBean {
private final HttpStatusProvider httpStatusProvider =
new HttpStatusProvider();
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
int status = httpStatusProvider.getStatus((HttpServletResponse) servletResponse);
filterChain.doFilter(servletRequest,servletResponse);
if (status==404){
System.out.println(404);
throw new ResourceNotFoundException("e");
}
}
}

Related

Spring boot Interceptor dont show #ControllerAdvice errorhandler?

Implemetation: Im trying to implementin project with Interceptor but the Error handling in showing only in Terminal which is good but i need also to show in restapi in postman and its showing empty.
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class WebInterceptor implements HandlerInterceptor {
private Logger logger = LoggerFactory.getLogger(WebInterceptor.class);
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
logger.error("WebInterceptor preHandle is now logged");
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
logger.error("WebInterceptor posthandle is now logged");
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
logger.error("WebInterceptor afterCompletion is now logged");
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#Configuration
public class AppConfig implements WebMvcConfigurer{
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new WebInterceptor()).addPathPatterns("/cart/**").order(1);
registry.addInterceptor(new WebInterceptor()).addPathPatterns("/product/**").order(2);
}
}
import com.kongapigateway.KongAPIgateway.ModelException.DATE_FORMAT_ERROR;
import com.kongapigateway.KongAPIgateway.ModelException.ProductExecption;
import com.kongapigateway.KongAPIgateway.ModelException.ProductIDnotFound;
import com.kongapigateway.KongAPIgateway.ModelException.ProductValueNotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
#RestControllerAdvice
public class WEbAspectExceptionConfig {
private Logger logger = LoggerFactory.getLogger(WEbAspectExceptionConfig.class);
#ExceptionHandler(ProductValueNotNull.class)
#ResponseStatus
public void handle(ProductValueNotNull e) {
logger.error(e.getMessage());
}
#ExceptionHandler(DATE_FORMAT_ERROR.class)
#ResponseStatus
public void handle2(DATE_FORMAT_ERROR e) {
logger.error(e.getMessage());
}
#ExceptionHandler(ProductExecption.class)
#ResponseStatus
public void handle2(ProductExecption e) {
logger.error(e.getMessage());
}
#ExceptionHandler(ProductIDnotFound.class)
#ResponseStatus
public void handle2(ProductIDnotFound e) {
logger.error(e.getMessage());
}
}
Terminal Output:
This is the error handling message: Please input all field
kongapigateway | 2022-06-07 11:21:33.149 INFO 1 --- [nio-8095-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
kongapigateway | 2022-06-07 11:21:33.161 ERROR 1 --- [nio-8095-exec-1] c.k.K.Interceptor.WebInterceptor : WebInterceptor preHandle is now logged
kongapigateway | 2022-06-07 11:21:33.277 ERROR 1 --- [nio-8095-exec-1] c.k.K.AOP.WEbAspectExceptionConfig : Please input all field
kongapigateway | 2022-06-07 11:21:33.277 ERROR 1 --- [nio-8095-exec-1] c.k.K.Interceptor.WebInterceptor : WebInterceptor afterCompletion is now logged
Postman api error handler is Empty
Shown here
Kindly disregard this Post Question.
I used Spring AOP #Around for customize exception.
Thank you.

How to log MDC while using filter

I am using filter for MDC logging to print the attributes in all layers(controller and service) but I was only able to print them in filter(MyHandlerInterceptor) only below is code I am using.
can anyone please help me with this how to get the attributes in all layers where we using logger message.
=================================================================
The code below is setting them before the request has been handled and I was unable to pull the data here.
Any help is appreciated.
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.util.ContentCachingRequestWrapper;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
#Component
public class MyHandlerInterceptor implements Filter {
private static final Logger logger = LoggerFactory.getLogger(MyHandlerInterceptor.class);
private ObjectMapper objectMapper;
#Autowired
public MyHandlerInterceptor(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
Map<String, Object> pathParams = (Map<String, Object>) wrappedRequest
.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
Map<String, Object> treeMapOfParam = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
if(pathParams!=null){
treeMapOfParam.putAll(pathParams);
}
String body = new String(wrappedRequest.getContentAsByteArray(), StandardCharsets.UTF_8);
Map<String, Object> objectBody = !body.isEmpty() ? objectMapper.readValue(body, Map.class) : new HashMap<>();
Map<String, Object> treeMapOfBody = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
treeMapOfBody.putAll(objectBody);
try {
if (HttpMethod.POST.toString().equals(wrappedRequest.getMethod())) {
MDC.put("ID", treeMapOfBody.containsKey("ID") ? treeMapOfBody.get("ID").toString() : null);
System.out.println(treeMapOfBody.get("ID"));
logger.info("hellopost");
} else if (HttpMethod.GET.toString().equals(wrappedRequest.getMethod())
&& treeMapOfParam.containsKey("ID")) {
MDC.put("ID", treeMapOfParam.get("ID").toString());
logger.info("helloget");
}
filterChain.doFilter(wrappedRequest, servletResponse);
} finally {
MDC.clear();
}
}
}

How to disallow TRACE http method in spring boot actuator

I have a server on port = 8078 and spring boot actuator on port = 8081.I want to disable TRACE Http method on both. I already create customizer bean(see below). But with this bean I disallowed only Trace on 8078. It's looks like actuator doesn't see this bean. How to disable TRACE http method on management server?
#ManagementContextConfiguration
public class CustomUndertowCustomizer {
#Bean
public WebServerFactoryCustomizer<UndertowServletWebServerFactory> undertowCustomizer() {
return (factory) ->
factory.addDeploymentInfoCustomizers(deploymentInfo ->
deploymentInfo.addInitialHandlerChainWrapper(handler -> {
HttpString[] disallowedHttpMethods = {HttpString.tryFromString("TRACE"),
HttpString.tryFromString("TRACK")};
return new DisallowedMethodsHandler(handler, disallowedHttpMethods);
}));
}
}
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
#Component
public class Filter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain)
{
try {
if (req.getMethod().equals("TRACE")) {
res.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
} else {
filterChain.doFilter(req, res);
}
} catch(Exception e){}
}
}

How to set up filter chain in spring boot?

I have come across spring-boot and intend to add a filter chain for incoming request.
Here is the Application:
package example.hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
}
Here is the Controller:
package example.hello;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.atomic.AtomicLong;
#RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#RequestMapping("/greeting")
public Greeting greeting(#RequestParam(value="name", defaultValue="World") String name) {
return new Greeting(counter.incrementAndGet(),
String.format(template, name));
}
}
Here is the Filter Config:
package example.hello;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class WebConfig {
#Bean
public FilterRegistrationBean greetingFilterRegistrationBean() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setName("greeting");
GreetingFilter greetingFilter = new GreetingFilter();
registrationBean.setFilter(greetingFilter);
registrationBean.setOrder(1);
return registrationBean;
}
#Bean
public FilterRegistrationBean helloFilterRegistrationBean() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setName("hello");
HelloFilter helloFilter = new HelloFilter();
registrationBean.setFilter(helloFilter);
registrationBean.setOrder(2);
return registrationBean;
}
}
Here is the HelloFilter and Greeting Filter:
package example.hello;
import javax.servlet.*;
import java.io.IOException;
public class HelloFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("HelloFilter!");
}
#Override
public void destroy() {
}
}
package example.hello;
import javax.servlet.*;
import java.io.IOException;
public class GreetingFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Greetings from filter!");
}
#Override
public void destroy() {
}
}
When I start the application and run curl localhost:8080/greeting, Only "Greetings from filter" is received and the HelloFilter is not invoked.
Besides there is no response from Greeting Controller. It seems that the GreetingFilter blocks the procedure.
So how to set the filter chain in Spring boot. Are there any bugs in the code above?
Adding following line of code in GreetingFilter works
filterChain.doFilter(servletRequest, servletResponse);
I would just like to clarify a little more on what Gangadhar suggested. You can try adding :
filterChain.doFilter(servletRequest, servletResponse);
in doFilter method of your filter classes.This will create chaining of the filters.

Spring Cache not working in doFilter

Spring Cache not working if called from doFilter.
Note that Spring cache is working if NOT called from doFilter() (e.g if called from rest service)
How can I enable cache in doFilter() ? (maybe cache is not allowed in doFilter?)
#Configuration
#EnableCaching
public class CredentialsInjectionFilter implements javax.servlet.Filter {
#Bean
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Arrays.asList(
new ConcurrentMapCache("tenants")
));
return cacheManager;
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
display(5);
filterChain.doFilter(servletRequest, servletResponse);
}
#Cacheable("tenants")
public void display(int number) {
// if cache working properly, code below will not execute after the first calling
for(int i=0; i<50; i++) {
System.out.println("ramon called" +number);
}
}
How about extending org.springframework.web.filter.GenericFilterBean, and moving the caching details into a separate service class
CacheService
import java.util.Arrays;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
#Component
public class CacheService{
#Bean
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Arrays.asList(
new ConcurrentMapCache("tenants")
));
return cacheManager;
}
#Cacheable("tenants")
public void display(int number) {
// if cache working properly, code below will not execute after the first calling
for(int i=0; i<50; i++) {
System.out.println("ramon called" +number);
}
}
}
CredentialsInjectionFilter
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.filter.GenericFilterBean;
#Component
public class CredentialsInjectionFilter extends GenericFilterBean {
#Autowired
private CacheService cacheService;
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
cacheService.display(5);
filterChain.doFilter(servletRequest, servletResponse);
}
}

Categories