Unable to add an instance of HandleInterceptorAdapter - java

I am trying to intercept every HTTP request that comes into my Spring Boot application.
For this I have a LoggingInterceptor as follows:
#Component
public class LoggingInterceptor extends HandlerInterceptorAdapter {
private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);
public LoggingInterceptor() {
super();
logger.debug("LoggingInteceptor constructor");
}
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
logger.debug("LoggingInteceptor: Intercepted " + request.getRequestURI());
return true;
}
}
Then, I have an #Configuration class for adding the interceptor to the registry as follows:
#EnableWebMvc
#Configuration
public class LoggingConfig extends WebMvcConfigurerAdapter {
#Autowired
LoggingInterceptor loggingInterceptor;
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(loggingInterceptor);
}
}
However, I just cannot see any of the logger statements. Is there something more I need to do to get this going?

Your configuration looks fine. Also registry.addInterceptor(loggingInterceptor); call would fail if interceptor would be null, therefore it seems to be correctly wired.
Therefore I would verify:
if DEBUG level us enabled in logging framework
If both classes are included into your Spring context at all (put breakpoint addInterceptors method and start app)
EDIT:
OK, so comment confirmed that you your problem is my first point.
You need to find out logging configuration file (e.g. log4j.properties, log4j,xml or logback.xml) and change log level from INFO to DEBUG there.

Related

springboot java interceptor doesn't invoke TRACE commad

I define an interceptor in spring-boot.
I override the preHandle method.
the interceptor is invoking for all HTTP commands : GET/PUT/POST/PATCH/DELETE/HEAD/OPTIONS
but it doesn't invoked for TRACE command.
what am I miss?
the interceptor:
#Component
public class BlockingHttpInterceptor implements HandlerInterceptor {
private final Class<?> thisClass = this.getClass();
private String BASE_URL = "/subscribers";
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (HttpMethod.GET.matches(request.getMethod())
|| HttpMethod.POST.matches(request.getMethod())
|| (HttpMethod.DELETE.matches(request.getMethod()) && request.getRequestURI().startsWith(BASE_URL))
|| HttpMethod.PATCH.matches(request.getMethod())) {
return true;
} else {
response.sendError(HttpStatus.METHOD_NOT_ALLOWED.value());
return false;
}
}
}
the interceptor config:
#Configuration
public class InterceptorConfig implements WebMvcConfigurer {
#Autowired
private BlockingHttpInterceptor blockingHttpInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(blockingHttpInterceptor).addPathPatterns("/**");
}
}
As explained in the JavaDoc for the DispatcherServlet the TRACE request are by default not dispatched, hence they will never reach your controllers/interceptor.
Luckily you are using Spring Boot which makes configuring this quite easy through the spring.mvc.dispatch-trace-request property, which is by default false. Setting this to true in your application.properties will enable dispatching for TRACE request.
spring.mvc.dispatch-trace-request=true
Adding the above to your properties will enable it and will make things work as you expect.

How to let Interceptor work in springboot

I migrate the code to springboot and our API works well. Only interceptor can't be triggerred.
I googled related solutions and modify the code to right format which still failed to trigger the interceptor.
In our project, we also have the filter which extends OncePerRequestFilter and works.
It makes me confused.
They should be no big difference.
Btw, AOP is used in the project.
It's my code.
JerseyConfig.class
#Configuration
public class JerseyConfig extends ResourceConfig {
public JerseyConfig(){
packages("com.xxx");
}
}
VaultAuthorizationInterceptor.class
#Component
public class VaultAuthorizationInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(VaultAuthorizationInterceptor.class);
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
logger.info("test");
return true;
}
}
VaultAuthConfig.class
#Configuration
public class VaultAuthConfig implements WebMvcConfigurer {
#Bean
public VaultAuthorizationInterceptor getVaultInterceptor() {
return new VaultAuthorizationInterceptor();
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getVaultInterceptor()).addPathPatterns("/**");
}
}
When you are using the spring-boot-starter-jersey, you use jersey as your web stack. That means any requests will processed by jersey. So you have to register a jersey filter or interceptor. Take a look at the jersey documantation. There is described how to use filters and interceptors. I think you want to use a filter because interceptors in the jersey stack used to manipulate the input or output stream.

Spring Boot 2.0 Intercepting the HandlerMethod of a Request

I am midway through upgrading from Spring Boot 1.x to Spring Boot 2.0 and have noticed I have started getting class cast errors in my HandlerInterceptors.
For example, in one HandlerInterceptor I look if the controller method/endpoint is annotated with #AdminOnly to restrict access to certain endpoints.
#Component
public class AdminOnlyInterceptor implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest httpRequest, HttpServletResponse httpResponse, Object handler) {
HandlerMethod hm = (HandlerMethod) handler;
Method method = hm.getMethod();
if (method.getDeclaringClass().isAnnotationPresent(RestController.class) && (method.isAnnotationPresent(AdminOnly.class) || method.getDeclaringClass().isAnnotationPresent(AdminOnly.class))) {
// Some Logic returning true or false
}
return true;
}
}
This worked in Spring Boot 1.5.x.
After upgrading I now get the following exception:
java.lang.ClassCastException: org.springframework.web.servlet.resource.ResourceHttpRequestHandler cannot be cast to org.springframework.web.method.HandlerMethod
I couldn't find anything relevant in the migration guide. How can I upgrade but keep the interceptor above working?
It appears Spring Boot 2.x Interceptors now also process Static Resource requests, so these now need to be manually excluded when registering the interceptor like below:
#Configuration
public class ControllerConfiguration implements WebMvcConfigurer {
private final AdminOnlyInterceptor adminInterceptor;
#Autowired
public ControllerConfiguration(AdminInterceptor adminInterceptor) {
this.adminInterceptor = adminInterceptor;
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(adminInterceptor)
.addPathPatterns("/rest-api-root/**"); // White list paths
//.excludePathPatterns("/static-resource-root/**"); // Black list paths
}
}

Spring Boot HandlerInterceptor not firing when Jersey Configured?

I have a Spring Boot v1.4.0 application configured with Jersey for delivery of RESTful services.
I have a working app, but I'm now trying to enhance it with a multi-tenancy SCHEMA awareness strategy. I was hoping to set a TenantContext based on client auth headers using a Spring's HandlerInterceptor framework...
BUT, there seems to be an issue with the Interceptors being fired with Jersey. I can hit the APIs fine, ( i.e. curl -i -H "Accept: application/json" -X GET http://localhost:8080/api/products ), but the interceptors just won't fire. If I wire up a more basic app without Jersey for resource management, they fire fine?
Here is the current application set-up:
#SpringBootApplication
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).run(args);
}
}
Registering the Interceptor
#Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
#Autowired
HandlerInterceptor tenantInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(tenantInterceptor);
}
}
The Interceptor itself
#Component
public class TenantInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
// FIXME: Put in a Logger impl
System.out.println("++++++++++++=======+++++++++ TenantInterceptor.preHandle() Checking for Tenant Routing");
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
TenantContext.clear();
// FIXME: Put in a Logger impl
System.out.println("++++++++++++=======+++++++++ TenantInterceptor.postHandle() Reset Tenant to " + TenantContext.getCurrentTenant());
}
}
The JerseyConfig
#Component
#ApplicationPath("api")
public class JerseyConfig extends ResourceConfig {
#PostConstruct
private void init() {
registerClasses(TenantsResource.class);
registerClasses(UsersResource.class);
registerClasses(ProductsResource.class);
}
}
I played around with the JerseyConfig #ApplicationPath("api") and the WebMvcConfig registry.addInterceptor(tenantInterceptor).addPathPatterns("patterns");. Tried the following one after the other, but no joy.
registry.addInterceptor(tenantInterceptor).addPathPatterns("/*");
registry.addInterceptor(tenantInterceptor).addPathPatterns("/**");
registry.addInterceptor(tenantInterceptor).addPathPatterns("/api/**");
registry.addInterceptor(tenantInterceptor).addPathPatterns("/api/*");
registry.addInterceptor(tenantInterceptor).addPathPatterns("/api/products");
registry.addInterceptor(tenantInterceptor).addPathPatterns("/api/products/");
Any help - much appreciated, or else I'll be resorting to hacking the Resource Controllers with smelly code :(.
Thanks - Derm
As mentioned by M.Deinum, HandlerInterceptor is not for Jersey, and it not some "underversal" interceptor. It is only for Spring MVC. For Jersey, you can use a ContainerRequestFilter. You would register it with you ResourceConfig.
See also:
Jersey docs for Filters and Interceptors

Spring MVC - Interceptor never called

I am trying to configure an interceptor in my application and I am not being able to make it work.
In my application configuration class, I have configured in the following way:
#Configuration
#EnableWebMvc
public class AppContextConfiguration extends WebMvcConfigurerAdapter {
...
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor());
}
...
}
And the interceptor:
public class MyInterceptor extends HandlerInterceptorAdapter{
private static final Logger logger = LoggerFactory.getLogger(MyInterceptor.class);
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
logger.debug("MyInterceptor - PREHANDLE");
}
}
Does anybody know why is not being invoked?
I'm using Spring Boot and was having the same problem where addInterceptors() was being called to register the interceptor, but the interceptor never fired during a request. Yet XML configuration worked no problem.
Basically, you don't need the WebMvcConfigurerAdapter class. You just need to declare an #Bean of type MappedInterceptor:
#Bean
public MappedInterceptor myInterceptor()
{
return new MappedInterceptor(null, new MyInterceptor());
}
Interceptor classes must be declared in spring context xml configuration file within the tag <mvc:interceptors>. Did you do that?
From the Documentation
An example of registering an interceptor applied to all URL paths:
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
</mvc:interceptors>
An example of registering an interceptor limited to a specific URL path:
<mvc:interceptors>
<mvc:interceptor>
<mapping path="/secure/*"/>
<bean class="org.example.SecurityInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
So, you would need to configure MyInterceptor class in the spring context xml file
Can someone please mark Theos answer as the correct one? I had the situation of a perfectly working Spring Boot app using i18n and Thymeleaf (with a layout interceptor) as long as the app was running localhost with the following config:
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
registry.addInterceptor(thymeleafLayoutInterceptor());
}
As soon as I deployed the app to an Elasticbeanstalk instance, both interceptors were not fired anymore. Although added once. When I changed the setting to
#Bean
public MappedInterceptor localeInterceptor() {
return new MappedInterceptor(null, localeChangeInterceptor());
}
#Bean
public MappedInterceptor thymeleafInterceptor() {
return new MappedInterceptor(null, thymeleafLayoutInterceptor());
}
everything was working fine on all environments. There must be an issue with firing interceptors added with addInterceptor, it might depend on the URL that is used to invoke the request - I don't know.
Thanks for your answer, Theo, I just wanted to add this here if some else stumbles upon this nice feature.
If it´s possible. Use this approach:
public class Application extends WebMvcConfigurerAdapter{
...
#Bean
public MyInterceptor myInterceptor() {
return new MyInterceptor();
}
public #Override void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor());
}
}
instead of:
#Bean
public MappedInterceptor myInterceptor()
{
return new MappedInterceptor(null, new MyInterceptor());
}
because with the first you can use injection features (like #Autowired, etc...)
Maybe you should add componentscan annotation in the file where the main class is present.
#ComponentScan("package where the interceptor is placed.")
Worked for me.
This approach worked with me
#Configuration
public class WebConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor());
}
}
Using XML configuration, ensure you defined the interceptors in the correct context.
Moving config from servlet context(*-servlet) to main context (web.xml) made it work.
Even if the URL was a call to the servlet.

Categories