Logging interceptor is not working - spring-boot

The issue is that it seems like interceptor is not called.
#Component
public class LoggingInterceptor extends HandlerInterceptorAdapter {
private static final Logger LOGGER = LogManager.getLogger(MethodHandles.lookup().lookupClass());
#Overridegre
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception arg3)
throws Exception {
LOGGER.info("Request Completed!");
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView model)
throws Exception {
LOGGER.info("Method executed");
}
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
LOGGER.info("Before process request");
return true;
}
}
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Autowired
LoggingInterceptor loggingInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loggingInterceptor);
}
}
I've found examples but they are not working !
I'm trying to add start and end log and also performance log. Any idea please ?
#SpringBootApplication(scanBasePackages = { "com.sofelite.proj.controllers" })
public class ProjApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(GrentyApplication.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(GrentyApplication.class, args);
}
}
This is the Application class
Please note that in com.sofelite.proj I have all application packages such as controllers and interceptors.

Mine is working:
#Configuration
public class LoggingConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoggingInterceptor());
}
}
and the LoggingInterceptor class:
#Component
public class LoggingInterceptor extends HandlerInterceptorAdapter {
private static final Logger LOGGER =
LoggerFactory.getLogger(LoggingInterceptor.class);
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler)
throws Exception {
long startTime = System.currentTimeMillis();
LOGGER.info("Request URL: " + request.getRequestURL());
LOGGER.info("Start Time: " + System.currentTimeMillis());
request.setAttribute("startTime", startTime);
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
StringBuilder sb = new StringBuilder();
sb.append("!Status: "+response.getStatus()+"\n");
sb.append("!URL: "+ request.getRequestURL());
sb.append("!Method: " + request.getMethod() + "\n");
LOGGER.info(sb.toString());
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
long endTime = System.currentTimeMillis();
System.out.println("URL Request Completed. End Time: "+ endTime);
}
}

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 Interceptor is not compatible with #RepositoryRestResource

#Component
public class TestInterceptor implements HandlerInterceptor {
#Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception {
System.out.println("afterCompletion");
}
#Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception {
System.out.println("postHandle");
}
#Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
System.out.println("preHandle");
return true;
}
}
and
#SpringBootConfiguration
public class AnnotationSecurityConfiguration implements WebMvcConfigurer {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TestInterceptor()).addPathPatterns("/api/**");
}
}
finally the entity is presented as REST using a #RepositoryRestController as follows:
#RepositoryRestResource(excerptProjection = UserSummaryProjection.class)
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
}
Then calling
curl -X GET https://localhost:8080/api/v1/users
but the interceptor is not called.
Because the REST resource is managed Spring Data Rest with #RepositoryRestController the interceptor is not called. But if I write the REST resource with #RestController it will work.
How can I make interceptors work with #RepositoryRestController?
I got it working (on / context path, and a simple User class, spring-boot v2.4.2) with the following config/spring-boot app:
...
import org.springframework.web.servlet.handler.MappedInterceptor
...
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Bean
public org.springframework.web.servlet.handler.MappedInterceptor myInterceptor() {
return new MappedInterceptor(
new String[]{"/users/**"}, // null => maps to any repository/path
new MyInterceptorImpl()
);
}
private class MyInterceptorImpl implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
}
I used a simplified:
#RepositoryRestResource
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> { }
you have to add TestInterceptor as a bean and anotate it with #Autowired just add these changes to register the Interceptor into Interceptor Registry :
#Configuration
#SpringBootApplication
public class DemoApplication extends WebMvcConfigurerAdapter {
#Autowired
private TestInterceptor testInterceptor;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(testInterceptor).addPathPatterns("/api/**");
}
HandlerInterceptor :
#Component
public class TestInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(TestInterceptor.class);
#Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception {
System.out.println("afterCompletion");
long startTime = Instant.now().toEpochMilli();
logger.info("Request URL::" + arg0.getRequestURL().toString() +
":: Start Time=" + Instant.now());
arg0.setAttribute("startTime", startTime);
}
#Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception {
System.out.println("postHandle");
}
#Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
System.out.println("preHandle");
return true;
}
}
as a sample i have changed the '/api/' to '/' and here a log sample as the below :
2021-02-13 00:36:31.075 INFO 14340 --- [on(2)-127.0.0.1] o.s.web.servlet.DispatcherServlet : Completed initialization in 22 ms
preHandle
postHandle
afterCompletion
2021-02-13 00:36:35.300 INFO 14340 --- [nio-8080-exec-1] com.example.demo.TestInterceptor : Request URL::http://localhost:8080/time:: Start Time=2021-02-12T22:36:35.289832Z
It only worked for me, using Spring Boot 2.6.7, by adding a MappedInterceptor.
#Bean
public MappedInterceptor loggingMappedInterceptor(TestInterceptor testInterceptor) {
return new MappedInterceptor(
null, // => maps to any repository
testInterceptor);
}

Custom Spring Security Filter Test with MockMvc always returns 404

I am trying to test a custom filter using MockMvc and it always returns status 404 instead of the actual status returned from the filter class.
The filter class looks as follows:
public class CustomFilter extends GenericFilterBean {
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
// some logic
chain.doFilter(servletRequest, servletResponse);
}
}
This is registered in with the SpringBootApplication using FilterRegistrationBean
#SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
try {
ConfigurableApplicationContext ctx = SpringApplication.run(MyApplication.class, args);
} catch (Throwable e) {
}
#Bean
public FilterRegistrationBean<CustomFilter> customFilter() {
FilterRegistrationBean<CustomFilter> filterRegistration = new FilterRegistrationBean<>();
filterRegistration.setFilter(new CustomFilter());
filterRegistration.addUrlPatterns("/test/*");
return filterRegistration;
}
}
The test for this is written as follows:
#RunWith(SpringRunner.class)
#SpringBootTest(CustomFilter.class)
#EnableAutoConfiguration
#WebAppConfiguration
public class CustomFilterTest {
#Autowired
private CustomFilter filter;
#Autowired
private WebApplicationContext context;
private MockMvc mvc;
#Before
public void setup() {
this.mvc = MockMvcBuilders.webAppContextSetup(context)
.addFilters(filter)
.build();
}
#Test
public void testCustomFilter() throws Throwable {
MockHttpServletRequestBuilder request = MockMvcRequestBuilders
.request(HttpMethod.POST, "/resource/abc")
.header("SomeHeader", "xxx")
.content("{}");
MockHttpServletResponse response = mvc.perform(request).andReturn().getResponse();
assertEquals(response.getStatus(), HttpServletResponse.SC_CONTINUE);
}
}
The assertion always returns the status value of 404.
Am I missing something here?
Add urlPatterns to the addFilter(filter, "/resource/abc") and add a test controller for the above code snippet as follows:
#RestController
public class TestController {
#PostMapping("/resource/abc")
public void testSecureEndpoint() {
}
}

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

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");
}
}

Resources