14

Is it possible with Apache CXF (2.7.0) to automatically discover JAX-RS resources in the classpath? That is, classes annotated with @Path.

I am using CXF in a Spring application and I have to manually declare the resources with the following XML, even if the resources are successfully discovered by Spring <context:component-scan ...>.

<jaxrs:server id="myService" address="/myService">
    <jaxrs:serviceBeans>
        <ref bean="myResource1" />
        <ref bean="myResource2" />
        <ref bean="myResource3" />
    </jaxrs:serviceBeans>
</jaxrs:server>

I would like to avoid it (as I can do with other JAX-RS implementations such as resteasy) because in my case it is harder to maintain, and it forces me to declare my bean dependencies in the Spring XML configuration file.

Guido
  • 46,642
  • 28
  • 120
  • 174
  • FWIW, I find it very useful to declare things explicitly. But then I have multiple `` declarations in the same application, each with a different configuration (e.g., different XML serializers). The RESTeasy approach isn't as flexible… – Donal Fellows Dec 05 '12 at 22:29

4 Answers4

9

Tested and working in cxf 3.0.4.

<jaxrs:server address="/" basePackages="a.b.c"/>

Dont forget to mention the cxf-servlet in web.xml

jaks
  • 4,407
  • 9
  • 53
  • 68
  • How do I do this with spring boot? I found a newer class/code but I am having some other issues: JAXRSServerFactoryBeanDefinitionParser.SpringJAXRSServerFactoryBean bean = new JAXRSServerFactoryBeanDefinitionParser.SpringJAXRSServerFactoryBean(); bean.setBasePackages(Collections.singletonList(SimulationController.class.getPackage().getName())); return bean.create(); – Christian Bongiorno Feb 18 '16 at 01:00
  • @ChristianBongiorno Here is the link to cxf docs. There is good description to Spring Boot setup. http://cxf.apache.org/docs/jaxrs-services-configuration.html#JAXRSServicesConfiguration-SpringBoot – Alex Amorales Feb 23 '16 at 14:42
  • @AlexAmorales I was already there. These examples don't work. That configuration bean does nothing but import the xml. I want it to add each Path bean into the service. – Christian Bongiorno Feb 24 '16 at 00:38
  • Thanks for explaining. It’s the same answer as [the one-year-older one](https://stackoverflow.com/a/23013913/2171120) from @SergeyBeryozkin but with more detail. • It’s a bit trickier than this, though, especially if you need Jackson as JSON provider. I [eventually figured this out](https://stackoverflow.com/a/53362844/2171120). – mirabilos Nov 18 '18 at 16:09
8

This code does the trick:

@Configuration
@ComponentScan
@ImportResource({"classpath:META-INF/cxf/cxf.xml"})
public class Context {
    @Autowired
    private ApplicationContext ctx;

    @Bean
    public Server jaxRsServer() {
        LinkedList<ResourceProvider> resourceProviders = new LinkedList<>();
        for (String beanName : ctx.getBeanDefinitionNames()) {
            if (ctx.findAnnotationOnBean(beanName, Path.class) != null) {
                SpringResourceFactory factory = new SpringResourceFactory(beanName);
                factory.setApplicationContext(ctx);
                resourceProviders.add(factory);
            }
        }

        JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();
        factory.setBus(ctx.getBean(SpringBus.class));
        factory.setProviders(Arrays.asList(new JacksonJsonProvider()));
        factory.setResourceProviders(resourceProviders);
        return factory.create();
    }
}

Just remember to put CXFServlet into your web.xml and you are done.

lightoze
  • 121
  • 1
  • 3
6

It doesn't look like there's a way to do this with Spring configuration at this time in CXF 2.7. If you look at resteasy they've implemented a BeanFactoryPostProcessor SpringBeanProcessor.java that looks for @Path and @Provider. Something similar could be probably be done in CXF but it doesn't appear to be implemented yet. Looks like you're not the only one interested CXF-3725

pmartin8
  • 1,545
  • 1
  • 20
  • 36
Bob Paulin
  • 1,088
  • 8
  • 13
3

In addition to what has been suggested: it works indeed in 3.0.0-milestone2, one would just do a top level jaxrs server declaration only and set basePackages attribute which may have one or more space separated package names.

Sergey Beryozkin
  • 688
  • 1
  • 4
  • 9