Persistent counter for every REST call - java

Is there any better way in spring boot that I can maintain a persistent counter in a DB(say, Redis or ES) for every kind of REST call with their corresponding timestamp? (WHAT I am not looking for is calling a function from within every REST call). Probably something like if I can do it before the control is passed to the function corresponding to the REST call, a common portion.

you can implement a custom interceptor.
public class MyInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// persist your counter here
return true;
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
super.afterCompletion(request, response, handler, ex);
// do what you need in the end of the call
}
to make spring-boot invoke your interceptor you should add a configuration class:
#Service
#EnableWebMvc
public class MyConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/*");
}
}

Related

Interceptor not working in Spring Boot GraphQL

Im using graphql-java-kickstart/graphql-spring-boot and I'd like to create an interceptor to add an HTTP header after processing the request.
When I'm sending a graphql request to the backend the the interceptor is not triggered. But some calls trigger the interceptor. For example when I'm opening /graphiql in my browser I see that the interceptor is triggered but when I send a graphql request from graphiql client it is not. Any idea why? Anybody got experience with this?
My config looks like this:
#Configuration
public class InterceptorConfig implements WebMvcConfigurer {
#Autowired
private TestInterceptor testInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(testInterceptor).addPathPatterns("/**");
}
}
Also my Interceptor:
#Slf4j
#Component
public class TestInterceptor extends HandlerInterceptorAdapter {
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
// post processing
log.info("hello there");
}
}
I have following interceptor that successfully works in my project:
My WebConfig:
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(requestInterceptor);
}
#Autowired
private ControllerExecInterceptor requestInterceptor;
}
Where ControllerExecInterceptor defined as:
#Component
public class ControllerExecInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws AccessDeniedException, Exception {
// ...
}
#Override
public boolean postHandle(HttpServletRequest request, HttpServletResponse
response, Object handler) throws {
// ...
}
}

Interceptor not getting invoke

Based on some business logic i need to add query parameters to the request before it reaches the controller. In order to achieve this i have use the HandlerInterceptorAdapter to intercept the request.
I have a common lib where I have defined an interceptor and the dependent project has the controllers.
The interceptor is getting registered but when i invoke any api call it does not get invoked.
Interceptor in common lib
#Component
public class RequestInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, java.lang.Object handler)
throws ServletException, IOException {
request.setAttribute("id", "123"); // this would be populated based on logic
return true;
}
}
Dependency
#Configuration
public class Resolver implements WebMvcConfigurer {
#Autowired
RequestInterceptor interceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(interceptor);
}
}
You don't have to annotate the RequestInterceptor. Please remove the #Component annotation from RequestInterceptor and #Autowired annotation from Resolver class to this dependency.
Instead of injecting, please instantiate it via default constructor.
public class RequestInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, java.lang.Object handler)
throws ServletException, IOException {
request.setAttribute("id", "123"); // this would be populated based on logic
return true;
}
}
#Configuration
#EnableWebMvc
public class Resolver implements WebMvcConfigurer {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new RequestInterceptor());
}
}

Java interceptor not getting called

I have a Spring boot application and I am implementing and interceptor in order to log some data.
The problem is that is not getting called, I have tried:
#Interceptor
public class LoggerInterceptor{
#AroundInvoke
public Object collectBasicLoggingInformation(InvocationContext context) throws Exception {
Logger logger = LoggerFactory.getLogger(context.getClass());
logger.info("Method Called: " + context.getMethod()
.getName());
logger.info("Parameters: " + Arrays.toString(context.getParameters()));
return context.proceed();
}
}
And then I've applied to methods or classes and in both of them doesn't work:
#GetMapping
#Interceptors(LoggerInterceptor.class)
public List getAllFilingNumber(){
logger.info("This is a test");
return filingNumberService.findAll();
}
Or
#RestController
#RequestMapping(FilingNumberController.BASE_URL)
#Interceptors(LoggerInterceptor.class)
public class FilingNumberController{
#GetMapping
public List getAllFilingNumber(){
logger.info("This is a test");
return filingNumberService.findAll();
}
}
Does someone knows what I am doing wrong?
Thanks
If you are having a springboot application in order to intercept the request to a controller , you have to take a different approach altogethor.
Interceptors are used in conjunction with Java EE managed classes to
allow developers to invoke interceptor methods on an associated target
class, in conjunction with method invocations or lifecycle events.
Common uses of interceptors are logging, auditing, and profiling.
Reference Doc
You are trying to use Java EE annotation with spring , which won't work.In spring-boot you will have to register the interceptors like :
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LocaleChangeInterceptor());
registry.addInterceptor(new ThemeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*");
}
}
The interceptor itself have to be a class which extends the HandlerInterceptorAdapter and implements the methods as follows.
From Spring DOCS :
All HandlerMapping implementations support handler interceptors that
are useful when you want to apply specific functionality to certain
requests — for example, checking for a principal. Interceptors must
implement HandlerInterceptor from the org.springframework.web.servlet
package with three methods that should provide enough flexibility to
do all kinds of pre-processing and post-processing:
preHandle(..): Before the actual handler is executed
postHandle(..): After the handler is executed
afterCompletion(..): After the complete request has finished
#Component
public class RequestInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object object) throws Exception {
System.out.println("we are Intercepting the Request");
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object object, ModelAndView model)
throws Exception {
System.out.println("request processing "
+ "completed by #RestController");
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object object, Exception arg3)
throws Exception {
System.out.println("afterCompletion Request Completed");
}
}

Spring MVC Interceptor pattern

I have an interceptor that is supposed to intercept urls with different patterns like:
myapp/something/add/whatever
myapp/something/add
myapp/something/addWhatever
myapp/something/somethingelse/add
etc...
I have to intercept all urls which contain "add". There are a lot of somethings and somethingelses...
I have tried different patterns but it seems that they are all wrong:
**/add/*
**/add*
**/add/ ** (I added a blank space before the last ** so it doesn't format it to bold)
The interceptor is something like
public class MyInterceptor implements HandlerInterceptor {
}
I configure it in
#Configuration
#EnableSpringDataWebSupport
#EnableWebMvc
class MvcConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(final InterceptorRegistry registry) {
registry.addInterceptor(getMyInterceptor()).addPathPatterns("**/add/*", "**/add/**", "**/add*");
}
#Bean
public MyInterceptor getMyInterceptor() {
return new MyInterceptor();
}
}
If I try to access
http://localhost:8080/myapp/something/add/somethingelse
my interceptor doesn't intercept it...
I had a similar issue. Here are my suggestions.
First use global interceptor and check the request uri:
public class MyInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String uri = request.getRequestURI();
if(uri.contains("/add")){
// do your job
}
return super.preHandle(request, response, handler);
}
}
In my case, alls add- methods are PUT, or POST requests. So I'm checking this in my global interceptor:
public class MyInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String method = request.getMethod();
if("PUT".equals(method) || "POST".equals(method)){
// do your job
}
return super.preHandle(request, response, handler);
}
}
configure it without addPathPatterns:
#Configuration
#EnableSpringDataWebSupport
#EnableWebMvc
class MvcConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(final InterceptorRegistry registry) {
registry.addInterceptor(getMyInterceptor());
}
#Bean
public MyInterceptor getMyInterceptor() {
return new MyInterceptor();
}
}
Apparently this can be fixed by Change the bean type to "Mapped Interceptor" and wrapping it; though people don't seem to know why its an issue in the first place.
Based on this solution: https://stackoverflow.com/a/35948730/857994

Spring Interceptor: how to populate model in preHandle method?

So basically question listed in title. Is there a way to populate org.springframework.ui.Model in preHandle method ?
public class SomeInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// need to populate Model here
return true;
}
}

Categories

Resources