I am trying to add custom interceptor in my spring boot web service project. I follow this example and created this config:
package org.example;
import java
Here's another possibility to solve this issue. This relates to following Stack overflow question: Spring WS interceptors with injected DAO's @Transactional not working. In short the issue comes from the fact that the method
@Override
public void addInterceptors(List interceptors) {
gets called before Spring dependency injection has time to register Spring AOP beans. In my case it was @Transactional that was ignored by Spring-WS but it could be anything.
Fortunately for us Spring-WS uses mutable collections instead of immutable. When the addInterceptors()
method
gets called, we can just save the collection and thus we have a reference to the same collection instance that is used by Spring-WS. Later on you can initialize your interceptor bean properly and add it to the collection.
You also have to get around the fact that if you use @Autowired
the bean gets prepared before the annotations can take place. Thus you have to create it manually by calling ApplicationContext.getBean()
method.
@EnableWs
@Configuration
// The magic is to implement both ApplicationContextAware
// that injects the applicationContext for us
// and BeanPostProcessor that gives us postProcessBeforeInitialization()
// where we initialize our interceptor correctly
// and add it to the collection
public class WebServiceConfig extends WsConfigurerAdapter implements ApplicationContextAware, BeanPostProcessor {
// This is the interceptor that uses dependencies with @Transactional annotation.
// It will not work with @Autowired
private MyInterceptorThatHasTransactionalDependencies myInterceptorThatHasTransactionalDependencies;
// Fortunately Spring WS uses mutable collections so we can fill
// this list later on as long as we just initialize it with
private List interceptors;
// This is our application context where all the beans are defined
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// save application context for later use
this.context = applicationContext;
}
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// This method gets called multiple times so initialize interceptor just once
if(myInterceptorThatHasTransactionalDependencies == null){
myInterceptorThatHasTransactionalDependencies = context.getBean(MyInterceptorThatHasTransactionalDependencies.class);
interceptors.add(myInterceptorThatHasTransactionalDependencies);
}
return bean;
}
@Override
public void addInterceptors(List interceptors) {
// Save the list of interceptors so we can modify it later on
this.interceptors = interceptors;
if (myInterceptorThatHasTransactionalDependencies == null) {
System.out.println("myInterceptorThatHasTransactionalDependencies was null like we expected");
} else {
interceptors.add(myInterceptorThatHasTransactionalDependencies);
}
}
}
Just to let you know that I am not Spring bean lifecycle expert, so there might be a better place to situate the interceptor initialization than postProcessBeforeInitialization()
. That said, this works for me.