Uploaded image for project: 'CXF'
  1. CXF
  2. CXF-5448

Spring integration via @Configuration & @ComponentScan annotations

    Details

    • Type: Improvement
    • Status: Open
    • Priority: Minor
    • Resolution: Unresolved
    • Affects Version/s: 2.6.11
    • Fix Version/s: None
    • Component/s: Integration
    • Labels:
      None
    • Estimated Complexity:
      Unknown

      Description

      Hi,

      as per dev mailing list thread started by me http://mail-archives.apache.org/mod_mbox/cxf-dev/201312.mbox/%3c1386597934463-5737561.post@n5.nabble.com%3e I would like to share my solution to get rid of XML file with CXF services definition.

      My case is rather simple (read: uncomplete) as I just want to automatically register in CXF @WebService and @WebServiceProvider annotated classes, so that they are exposed via CXFServlet.

      The end developer just needs to annotate her services with e.g. @WebService annotation and also needs to add a following Spring configuration (application code):

      SampleAppConfig.java
      import javax.jws.WebService;
      import javax.xml.ws.WebServiceProvider;
      
      import org.springframework.context.annotation.ComponentScan;
      import org.springframework.context.annotation.ComponentScan.Filter;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.context.annotation.Import;
      
      @Configuration
      @Import(JaxWsConfig.class)
      @ComponentScan(value = { "package filters" },
          includeFilters = { 
            @Filter(WebService.class), 
            @Filter(WebServiceProvider.class) 
          })
      public class SampleAppConfig {
      }
      

      where JaxWsConfig is a reference to CXF Spring configuration (it should be a part of CXF):

      JaxWsConfig.java
      @Configuration
      @ImportResource({ 
        "classpath:META-INF/cxf/cxf.xml", 
        "classpath:META-INF/cxf/cxf-servlet.xml" 
        })
      public class JaxWsConfig {
      }
      

      The crucial part is Spring bean post processor (that should be also a part of CXF distribution):

      JaxWsBeanPostProcessor.java
      @Named
      public class JaxWsBeanPostProcessor implements BeanPostProcessor {
      
        @Inject
        ListableBeanFactory beanFactory;
        
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
          return bean;
        }
      
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (isWebService(bean)) {
              Bus bus = beanFactory.getBean(Bus.DEFAULT_BUS_ID, Bus.class);
              SpringEndpointImpl endpoint = new SpringEndpointImpl(bus, bean);
              // capitalization is just a nice feature - totally optional
              endpoint.setAddress("/" + StringUtils.capitalize(beanName));
              // adds ALL features registered / discovered by Spring
              Map<String, AbstractFeature> featureMap = beanFactory.getBeansOfType(AbstractFeature.class);
              endpoint.getFeatures().addAll(featureMap.values());
              endpoint.publish();
            }
            
            return bean;
        }
      
        boolean isWebService(Object bean) {
          Class<?> beanClass = bean.getClass();
          return beanClass.getAnnotation(WebService.class) != null
              || beanClass.getAnnotation(WebServiceProvider.class) != null;
        }
      }
      

      And then if you also want to configure / inject your features using CDI (Spring) you do stuff like this (application code):

      MyFeature.java
      @Named
      public class MyFeature extends AbstractFeature {
        
        @Inject
        MyInInterceptor inInterceptor;
      
        @Inject
        MyOutInterceptor outInterceptor;
      
        @Override
        protected void initializeProvider(InterceptorProvider provider, Bus bus) {
          bus.getInInterceptors().add(inInterceptor);
          bus.getOutInterceptors().add(outInterceptor);
        }
      

      Does that make sense?

      Please note that my implementation is simplified but works for me. You should probably add all other possible customizations in JaxWsBeanPostProcessor class.

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                Unassigned
                Reporter:
                pbielicki Przemyslaw Bielicki
              • Votes:
                1 Vote for this issue
                Watchers:
                5 Start watching this issue

                Dates

                • Created:
                  Updated: