How to use Spring Autowired in a custom cxf interceptor?
Solution 1
You can't mix @InInterceptors
(a CXF annotation) and @Component
(a Spring annotation). That will create two separate instances of your interceptor: the one whose dependencies are getting injected by Spring, and one created by CXF. (You are providing class names in the @InInterceptors
annotation, not a bean ID, so CXF has no way of knowing that you already created an instance in the Spring context.)
Remove the @InInterceptors
annotation and, in addition to the component scan:
<context:component-scan base-package="org.example.config"/>
You also need something like this in your application context:
<jaxws:endpoint id="myWebService" address="/MyWebService">
<jaxws:inInterceptors>
<ref bean="myInInterceptor" />
</jaxws:inInterceptors>
</jaxws:endpoint>
Solution 2
I know this is an old question, but Jonathan W's answer helped me and I would like to add to it.
This is how I got custom interceptors and @Autowired
to work with Spring Boot 1.3.1:
http://cxf.apache.org/docs/jax-ws-configuration.html
import java.util.Arrays;
import javax.jws.WebService;
import org.apache.cxf.Bus;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
@Configuration
@EnableAutoConfiguration
@ImportResource({ "classpath:META-INF/cxf/cxf.xml" })
public class Application extends SpringBootServletInitializer {
@Autowired
private ApplicationContext applicationContext;
@Autowired
private MyInterceptor myInterceptor;
@Autowired
private HelloWorldImpl helloWorldImpl;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
// Replaces the need for web.xml
@Bean
public ServletRegistrationBean servletRegistrationBean(ApplicationContext context) {
return new ServletRegistrationBean(new CXFServlet(), "/api/*");
}
// Replaces cxf-servlet.xml
@Bean
// <jaxws:endpoint id="helloWorld" implementor="demo.spring.service.HelloWorldImpl" address="/HelloWorld"/>
public EndpointImpl helloService() {
Bus bus = (Bus) applicationContext.getBean(Bus.DEFAULT_BUS_ID);
EndpointImpl endpoint = new EndpointImpl(bus, helloWorldImpl);
// Set interceptors here
endpoint.setInInterceptors(Arrays.asList(myInterceptor));
endpoint.publish("/hello");
return endpoint;
}
// Used when deploying to a standalone servlet container, i.e. tomcat
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
// Web service endpoint
@WebService(endpointInterface = "demo.spring.service.HelloWorld")
//@InInterceptors not defined here
public static class HelloWorldImpl {
}
public static class MyInterceptor extends LoggingInInterceptor {
// @Autowired works here
}
}
Marco
Happy coder, system architect, software geek, cloud believer, tech guy, open-source enthusiasts, wannabe cooking chef, likes to travel, meet new people, share knowledge, and watch movies/series.
Updated on June 12, 2022Comments
-
Marco almost 2 years
i seem to run into a small issue when using @Autowired into a custom cxf interceptor. My use case is that i want to log soap messages and send these using AMQP to another system. This process works for normal services etc. But whatever i do, the needed properties do not get autowired and stay null.
I checked the Spring DI log and the context is scanned and pickedup, so what am i missing?
Is this even possible in CXF interceptors?
@Component public class LogInInterceptor extends AbstractSoapInterceptor { private @Value("#{rabbitMQProperties['rabbitmq.binding.log.soap']}") String binding; @Autowired AmqpTemplate amqpTemplate; public LogInInterceptor() { super(Phase.RECEIVE); } @Override public void handleMessage(SoapMessage soapMessage) throws Fault { logIt(soapMessage); } private void logIt(SoapMessage message) throws Fault { // rest of the code omitted...!!! amqpTemplate.convertAndSend(binding, buffer.toString()); } }
-
Jonathan W almost 12 yearsBy "picked up" you mean that your LogInInterceptor is being found and is eligible for injection from the Spring container? Has it reported any other problems with the injection (such as failing at the @Value parameter)?
-
Biju Kunjummen almost 12 yearsCan you please share the configuration for this interceptor with CXF also. The reason for this issue may be that the interceptor may have been instantiated by CXF and a separate autowired instance may have been created by Spring.
-
Marco almost 12 yearsI have implemented the interceptor as above and added it to my webservice via the @org.apache.cxf.interceptor.InInterceptors (interceptors = {"org.apache.cxf.interceptor.LoggingInInterceptor","mypackagenames.ws.interceptor.LogInInterceptor"}) I performed no addtional configuration at all.
-
Jonathan W almost 12 yearsMarco, that's why. CXF is creating the object and using that one, not Spring.
-
-
Marco almost 12 yearsThe component scan is successfull, the correct package name is in the spring xml file. Still the properties are not injected.. Any other clue?
-
Marco almost 12 yearsIts working! Thanks for the clear explanation and help implementing this.