How to use Spring Autowired in a custom cxf interceptor?

10,257

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
    }

}
Share:
10,257
Marco
Author by

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, 2022

Comments

  • Marco
    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
      Jonathan W almost 12 years
      By "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
      Biju Kunjummen almost 12 years
      Can 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
      Marco almost 12 years
      I 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","mypackag‌​enames.ws.intercepto‌​r.LogInInterceptor"}‌​) I performed no addtional configuration at all.
    • Jonathan W
      Jonathan W almost 12 years
      Marco, that's why. CXF is creating the object and using that one, not Spring.
  • Marco
    Marco almost 12 years
    The component scan is successfull, the correct package name is in the spring xml file. Still the properties are not injected.. Any other clue?
  • Marco
    Marco almost 12 years
    Its working! Thanks for the clear explanation and help implementing this.