Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

 

 

 

Wiki Markup
{span:style=font-size:2em;font-weight:bold} JAX-RS : Services Configuration {span}

 

 

 

Table of Contents

Configuring JAX-RS services programmatically

Code Block
java
java

import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
...

JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
sf.setResourceClasses(CustomerService.class);
sf.setAddress("http://localhost:9000/");
sf.create();

...

  • The JAXRSServerFactoryBean creates a Server inside CXF which starts listening for requests on the URL specified.
  • Check the JAXRSServerFactoryBean API for methods for adding multiple root resources
  • setResourceClasses() is for root resources only, use setProvider() or setProviders() for @Provider-annotated classes.
  • By default, the JAX-RS runtime is responsible for the lifecycle of resource classes, default lifecycle is per-request. You can set the lifecycle to singleton by using following line:

    Code Block
    java
    java
    
    sf.setResourceProvider(BookStore.class, new SingletonResourceProvider(new BookStore()));
    
  • If you prefer not to let the JAX-RS runtime handle the resource class lifecycle for you (for example, it might be the case that your resource class is created by other containers such as Spring), you can do the following:

    Code Block
    java
    java
    
    JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
    CustomerService cs = new CustomerService();
    sf.setServiceBeans(cs);
    sf.setAddress("http://localhost:9080/");
    sf.create();
    

...

The following example shows how to configure a JAX-RS endpoint in OSGI containers supporting Blueprint:

Code Block
xml
xml

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:jaxws="http://cxf.apache.org/blueprint/jaxws"
           xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
           xmlns:cxf="http://cxf.apache.org/blueprint/core"
           xsi:schemaLocation="
             http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
             http://cxf.apache.org/blueprint/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd
             http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
             ">

    <cxf:bus>
        <cxf:features>
            <cxf:logging/>
        </cxf:features>
    </cxf:bus>

     <jaxrs:server id="customerService" address="/customers">
        <jaxrs:serviceBeans>
           <ref component-id="serviceBean" />
        </jaxrs:serviceBeans>
     </jaxrs:server>

     <bean id="serviceBean" class="service.CustomerService"/>
</blueprint>

Spring

Code Block
xml
xml

<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:jaxrs="http://cxf.apache.org/jaxrs"
      xsi:schemaLocation="
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
         http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">

     <import resource="classpath:META-INF/cxf/cxf.xml" />
     <import resource="classpath:META-INF/cxf/osgi/cxf-extension-osgi.xml" />

     <jaxrs:server id="customerService" address="/customers">
        <jaxrs:serviceBeans>
           <ref bean="serviceBean"/>
        </jaxrs:serviceBeans>
     </jaxrs:server>
      
     <bean id="serviceBean" class="service.CustomerService"/> 
</beans>

...

Note that even though no Spring is explicitly used in the previous section, it is still used by default to have various CXF components registered with the bus such as transport factories. If no Spring libraries are available on the classpath then please follow the following example :

Code Block
java
java

JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
sf.setResourceClasses(CustomerService.class);
sf.setResourceProvider(CustomerService.class, new SingletonResourceProvider(new CustomerService()));
sf.setAddress("http://localhost:9000/");
BindingFactoryManager manager = sf.getBus().getExtension(BindingFactoryManager.class);
JAXRSBindingFactory factory = new JAXRSBindingFactory();
factory.setBus(sf.getBus());
manager.registerBindingFactory(JAXRSBindingFactory.JAXRS_BINDING_ID, factory);
sf.create();

...

Using Spring ContextLoaderListener

Code Block
xml
xml

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>WEB-INF/beans.xml</param-value>
	</context-param>

	<listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>

	<servlet>
		<servlet-name>CXFServlet</servlet-name>
		<display-name>CXF Servlet</display-name>
		<servlet-class>
			org.apache.cxf.transport.servlet.CXFServlet
		</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>CXFServlet</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
</web-app>

...

Using CXFServlet init parameters

Code Block
xml
xml

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
	<servlet>
		<servlet-name>CXFServlet1</servlet-name>
		<display-name>CXF Servlet1</display-name>
		<servlet-class>
			org.apache.cxf.transport.servlet.CXFServlet
		</servlet-class>
                <init-param>
                   <param-name>config-location</param-name>
                   <param-value>/WEB-INF/beans1.xml</param-value>
                </init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

        <servlet>
		<servlet-name>CXFServlet2</servlet-name>
		<display-name>CXF Servlet2</display-name>
		<servlet-class>
			org.apache.cxf.transport.servlet.CXFServlet
		</servlet-class>
                <init-param>
                   <param-name>config-location</param-name>
                   <param-value>/WEB-INF/beans2.xml</param-value>
                </init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>


	<servlet-mapping>
		<servlet-name>CXFServlet1</servlet-name>
		<url-pattern>/1/*</url-pattern>
	</servlet-mapping>

        <servlet-mapping>
		<servlet-name>CXFServlet2</servlet-name>
		<url-pattern>/2/*</url-pattern>
	</servlet-mapping>
</web-app>

...

beans.xml

Code Block
xml
xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:jaxrs="http://cxf.apache.org/jaxrs"
  xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">

  <!-- do not use import statements if CXFServlet init parameters link to this beans.xml --> 

  <import resource="classpath:META-INF/cxf/cxf.xml" />
  <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

  <jaxrs:server id="customerService" address="/service1">
    <jaxrs:serviceBeans>
      <ref bean="customerBean" />
    </jaxrs:serviceBeans>
  </jaxrs:server>

  <bean id="customerBean" class="demo.jaxrs.server.CustomerService" />
</beans>

...

If you need to do Spring configuration and get an error to do with a missing NamespaceHandler then, as a workaround, consider configuring jaxrs endpoints using CXF beans which actually handle the creation of jaxrs:server endpoints. This is marginally more complex, but overall, the configuration ends up being quite similar, for example, the above jaxrs:server endpoint can be configured like this instead:

Code Block
xml
xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

  <import resource="classpath:META-INF/cxf/cxf.xml" />
  <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

  <bean class="org.apache.cxf.jaxrs.JAXRSServerFactoryBean" init-method="create">
    <property name="address" value="/service1"/>
    <property:serviceBeans>
      <ref bean="customerBean" />
    </property:serviceBeans>
  </jaxrs:server>

  <bean id="customerBean" class="demo.jaxrs.server.CustomerService" />
</beans>

...

CXF JAX-RS is capable of working with AOP interceptors applied to resource classes from Spring.
For example:

Code Block
xml
xml


<beans xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:aop="http://www.springframework.org/schema/aop" 
  xsi:schemaLocation=" http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/aop  
  http://www.springframework.org/schema/aop/spring-aop.xsd 
  http://cxf.apache.org/jaxrs 
  http://cxf.apache.org/schemas/jaxrs.xsd">
  <import resource="classpath:META-INF/cxf/cxf.xml"/>
  <import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml"/>
  <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>

  <jaxrs:server id="bookservice" address="/">
	<jaxrs:serviceBeans>
          <ref bean="bookstore"/>
          <ref bean="bookstoreInterface"/>
        </jaxrs:serviceBeans>
   </jaxrs:server>
   <bean id="bookstore" class="org.apache.cxf.systest.jaxrs.BookStore"/>
   <bean id="bookstoreInterface" class="org.apache.cxf.systest.jaxrs.BookStoreWithInterface"/>

   <aop:config>
	<aop:aspect id="loggingAspect" ref="simpleLogger">
          <aop:before method="logBefore" 
              pointcut="execution(* org.apache.cxf.systest.jaxrs.BookStore*.*(..))"/>
          <aop:after-returning method="logAfter" 
              pointcut="execution(* org.apache.cxf.systest.jaxrs.BookStore*.*(..))"/>
        </aop:aspect>
   </aop:config>
   <bean id="simpleLogger" 
         class="org.apache.cxf.systest.jaxrs.SimpleLoggingAspect"/>
</beans>

...

For example, here's how org.apache.cxf.systest.jaxrs.BookStoreWithInterface looks like:

Code Block
java
java


public interface BookInterface {
    @GET
    @Path("/thosebooks/{bookId}/")
    @Produces("application/xml")
    Book getThatBook(Long id) throws BookNotFoundFault;
}

public class BookStoreWithInterface extends BookStoreStorage 
    implements BookInterface {

    public Book getThatBook(@PathParam("bookId") Long id) 
        throws BookNotFoundFault {
        return doGetBook(id);
    }

    @Path("/thebook")
    public Book getTheBook(@PathParam("bookId") Long id) 
        throws BookNotFoundFault {
        return doGetBook(id);
    }
}

...

The other method, getTheBook() can not be dispatched to by a JAX-RS runtime as it's not possible to discover it through a JDK proxy. If this method also needs to be invoked then this method should either be added to the interface or CGLIB proxies have to be explicitly enabled (consult Spring AOP documentation for more details). For example:

Code Block
xml
xml

<aop:config proxy-target-class="true"/>

...

If you prefer, you can register JAX-RS endpoints without depending on Spring with the help of CXFNonSpringJaxrsServlet :

Code Block
xml
xml

<servlet>
 <servlet-name>CXFServlet</servlet-name>
 <display-name>CXF Servlet</display-name>
 <servlet-class>
   org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet
 </servlet-class>
 <init-param>
  <param-name>jaxrs.serviceClasses</param-name>
  <param-value>
    org.apache.cxf.systest.jaxrs.BookStore1
    org.apache.cxf.systest.jaxrs.BookStore2		      
  </param-value>
 </init-param>
 <init-param>
  <param-name>jaxrs.providers</param-name>
  <param-value>
    org.apache.cxf.systest.jaxrs.BookStoreProvider1
    org.apache.cxf.systest.jaxrs.BookStoreProvider2		      
  </param-value>
 </init-param>
 <!-- enables schema validation -->
 <init-param>
  <param-name>jaxrs.schemaLocations</param-name>
  <param-value>
    classpath:/WEB-INF/schemas/schema1.xsd
    classpath:/WEB-INF/schemas/schema2.xsd		      
  </param-value>
 </init-param> 
 <!-- registers CXF in interceptors -->
 <init-param>
  <param-name>jaxrs.inInterceptors</param-name>
  <param-value>
    org.apache.cxf.systest.jaxrs.CustomInInterceptor
  </param-value>
 </init-param> 
 <!-- registers CXF out interceptors -->
 <init-param>
  <param-name>jaxrs.outInterceptors</param-name>
  <param-value>
    org.apache.cxf.systest.jaxrs.CustomOutInterceptor
  </param-value>
 </init-param>
 <!-- registers extension mappings -->
 <init-param>
  <param-name>jaxrs.extensions</param-name>
  <param-value>
    xml=application/xml
    json=application/json
  </param-value>
 </init-param>
 <!-- registers contextual properties -->
 <init-param>
  <param-name>jaxrs.properties</param-name>
  <param-value>
    property1=value
    property2=value
  </param-value>
 </init-param>
<load-on-startup>1</load-on-startup>
</servlet>

...

If the referenced service classes are not annotated with JAX-RS annotations then an external user model can also be linked to :

Code Block
xml
xml

<servlet>
 <servlet-name>CXFServlet</servlet-name>
 <display-name>CXF Servlet</display-name>
 <servlet-class>
   org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet
 </servlet-class>
 <init-param>
  <param-name>jaxrs.serviceClasses</param-name>
  <param-value>
    org.apache.cxf.systest.jaxrs.BookStore
  </param-value>
 </init-param>
 <!-- link to the user model -->
 <init-param>
  <param-name>user.model</param-name>
  <param-value>
    classpath:/models/resources.xml
  </param-value>
 </init-param> 
 <load-on-startup>1</load-on-startup>
</servlet>

A more portable way to register resource classes and providers with CXFNonSpringJaxrsServlet is to use a JAX-RS Application implementation :

Code Block
xml
xml

<servlet>
 <servlet-name>CXFServlet</servlet-name>
 <display-name>CXF Servlet</display-name>
 <servlet-class>
   org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet
 </servlet-class>
 <init-param>
  <param-name>javax.ws.rs.Application</param-name>
  <param-value>
    org.apache.cxf.systest.jaxrs.BookApplication	      
  </param-value>
 </init-param>
 <!-- 
    This parameter is recognized only starting from CXF 2.3.1
    @ApplicationPath value will be ignored if this parameter is set to true
 -->
 <init-param>
  <param-name>jaxrs.application.address.ignore</param-name>
  <param-value>true</param-value>
 </init-param>
<load-on-startup>1</load-on-startup>
</servlet>

...

Starting from CXF 2.3.7/2.4.3/2.5.0 it is possible to simple properties for resource and Application classes, providers and interceptors:

Code Block
xml
xml

<servlet>
 <servlet-name>CXFServlet</servlet-name>
 <display-name>CXF Servlet</display-name>
 <servlet-class>
   org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet
 </servlet-class>
 <init-param>
  <param-name>javax.ws.rs.Application</param-name>
  <param-value>
    org.apache.cxf.systest.jaxrs.BookApplication
    (name=1 id=2)	      
  </param-value>
 </init-param>
 <load-on-startup>1</load-on-startup>
</servlet>

...

Note that having the web-app_2_3.dtd DTD referenced from web.xml will likely prevent 'param-value' containing spaces and make it difficult to specify multiple providers like this:

Code Block
xml
xml

 <init-param>
  <param-name>jaxrs.providers</param-name>
  <param-value>
    mypackage.Provider1 
    mypackage.Provider2	      
  </param-value>
 </init-param>
 <load-on-startup>1</load-on-startup>
</servlet>

...

Here is a code fragment showing how it can be done with the help of CxfNonSpringJaxrsServlet :

Code Block
java
java

CXFNonSpringJAXRSServlet cxf = new CXFNonSpringJaxrsServlet();

...

ServletHolder servlet = new ServletHolder(cxf);
servlet.setInitParameter("javax.ws.rs.Application", "com.acme.MyServiceImpl");
servlet.setName("services");
servlet.setForcedPath("services");
root.addServlet(servlet, "/*");

...

If you have a JAX-RS Application implementation available and would like to minimize the interaction with the CXF JAX-RS specific API, you may want to use the JAX-RS RuntimeDelegate :

Code Block
java
java


import javax.ws.rs.ext.RuntimeDelegate;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;

RuntimeDelegate delegate = RuntimeDelegate.getInstance();
JAXRSServerFactoryBean bean = delegate.createEndpoint(new CustomApplication(), JAXRSServerFactoryBean.class);

// before CXF 2.3.1 :
// bean.setAddress("http://localhost:8080/services");

bean.setAddress("http://localhost:8080/services" + bean.getAddress());

Server server = bean.create();
server.start();
// and finally
server.stop();

...

When using Spring explicitly in your code, you may want to follow this example :

Code Block
java
java

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]
                      {"/org/apache/cxf/jaxrs/spring/servers.xml"});

// 'simple' is the id of the jaxrs server bean
JAXRSServerFactoryBean sfb = (JAXRSServerFactoryBean)ctx.getBean("simple");
sfb.create();

Note that in in this case your Spring configuration file should import cxf-extension-http-jetty.xml instead of cxf-servlet.xml :

Code Block
xml
xml

<!--
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
-->
<import resource="classpath:META-INF/cxf/cxf-extension-http-jetty.xml" />

...

By default, the service beans which are referenced directly from the jaxrs:server endpoint declarations are treated by the runtime as singleton JAX-RS root resources. For example:

Code Block
xml
xml

<beans>
  <jaxrs:server id="customerService" address="/service1">
    <jaxrs:serviceBeans>
      <ref bean="customerBean" />
    </jaxrs:serviceBeans>
  </jaxrs:server>
  <!--
    The scope attribute, if any, will be ignored. For example, adding the scope attribute with the value
    "request", "prototype", etc, won't have any effect, the customerBean will still be treated as 
    a JAX-RS singleton by the runtime.
  --> 
  <bean id="customerBean" class="demo.jaxrs.server.CustomerService" />
</beans>

...

For example, the serviceFactories element can reference one or more beans of type 'org.apache.cxf.jaxrs.spring.SpringResourceFactory' which in turn reference the actual service beans.

Code Block
xml
xml

<beans>
  <jaxrs:server id="customerService" address="/service1">
    <jaxrs:serviceFactories>
      <ref bean="sfactory1" />
      <ref bean="sfactory2" /> 
    </jaxrs:serviceFactories>
  </jaxrs:server>
  
  <bean id="sfactory1" class="org.apache.cxf.jaxrs.spring.SpringResourceFactory">
     <property name="beanId" value="customerBean1"/>
  </bean>
  <bean id="sfactory2" class="org.apache.cxf.jaxrs.spring.SpringResourceFactory">
     <property name="beanId" value="customerBean2"/>
  </bean>

  <bean id="customerBean1" class="demo.jaxrs.server.CustomerRootResource1" scope="prototype"/> 
  <bean id="customerBean2" class="demo.jaxrs.server.CustomerRootResource2"  scope="prototype"/> 
</beans>

...

If using the jaxrs:serviceFactories element seems a bit verbose then the 'beanNames' attribute can be used instead:

Code Block
xml
xml

<beans>
  <jaxrs:server id="customerService" address="/service1"
    beanNames="customerBean1 customerBean2"/>
  
  <bean id="customerBean1" class="demo.jaxrs.server.CustomerRootResource1" scope="prototype"/> 
  <bean id="customerBean2" class="demo.jaxrs.server.CustomerRootResource2"  scope="prototype"/> 
</beans>

...

Another approach toward supporting complex scopes in Spring is to use Spring AOP. For example, the following fragment shows how to have the Spring "request" scope supported:

Code Block
xml
xml

<beans
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:jaxrs="http://cxf.apache.org/jaxrs"
	xmlns:cxf="http://cxf.apache.org/core"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/aop     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
		http://cxf.apache.org/jaxrs                   http://cxf.apache.org/schemas/jaxrs.xsd
		http://cxf.apache.org/core                    http://cxf.apache.org/schemas/core.xsd">

	<import resource="classpath:META-INF/cxf/cxf.xml"/>
	<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>

	<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>

	<jaxrs:server id="example" address="/">
       	    <jaxrs:serviceBeans>
   	        <bean class="org.apache.cxf.systest.jaxrs.CustomerService" scope="request"><aop:scoped-proxy /></bean>
	    </jaxrs:serviceBeans>
	</jaxrs:server>
</beans>

in addition, the following servlet listener has to be added to the web.xml:

Code Block
xml
xml

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

The request-scoped service bean instances (example, org.apache.cxf.systest.jaxrs.CustomerService instances) are not actually available at the initialization time thus one limitation of the above configuration is that it is not possible to inject JAX-RS contexts into these service beans. This is not a show-stopper because contexts such as UriInfo can be passed in as resource method parameters. However, if the injection into the fields or via method setters is required then a little customization of the org.apache.cxf.jaxrs.spring.SpringResourceFactory will do the trick. Particularly, the Spring ApplicationContext reports that a request-scoped bean is a singleton but the JAX-RS runtime can not inject thread-local proxies given that the actual instance is not available as explained above; in fact, the request-scoped beans are not really JAX-RS singletons. Thus a simple custom factory like this one is needed and it has to be used the following way:

Code Block
xml
xml

<beans>
  <jaxrs:server id="customerService" address="/service1">
    <jaxrs:serviceFactories>
       <bean class="org.apache.cxf.systest.jaxrs.RequestScopeResourceFactory">
          <property name="beanId" value="customerBean"/>
       </bean> 
    </jaxrs:serviceFactories>
  </jaxrs:server>
  
  <bean id="customerBean" class="org.apache.cxf.systest.jaxrs.CustomerService" scope="request"><aop:scoped-proxy /></bean>
</beans>

...

CXFNonSpringJaxrsServlet can support singleton scopes for classes with constructors expecting JAXRS contexts, at the moment it can only inject ServletContext or ServletConfig contexts :

Code Block
java
java

@Path("/")
public class SingletonResourceClass {
   public SingletonResourceClass(@Context ServletContext context, @Context ServletConfig context2) {}
}

Programmatically

Code Block
java
java

JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
sf.setResourceClass(CustomerService.class);
sf.setResourceProvider(new SingletonResourceProvider(new CustomerService()));
sf.setResourceClass(CustomerService2.class);
sf.setResourceProvider(new PerRequestResourceProvider(CustomerService.class));

...

One way to share multiple providers between multiple endpoints is to refer to the same provider bean from within jaxrs:provider sections:

Code Block
xml
xml

<beans>
  <jaxrs:server id="customerService" address="/service1">
    <jaxrs:serviceBeans>
      <bean class="org.apache.cxf.systest.jaxrs.CustomerService"/>
    </jaxrs:serviceBeans>
    <jaxrs:providers>
      <bean ref="customProvider"/>
    </jaxrs:providers>

  </jaxrs:server>

  <jaxrs:server id="customerService" address="/service2">
    <jaxrs:serviceBeans>
      <bean class="org.apache.cxf.systest.jaxrs.CustomerService2"/>
    </jaxrs:serviceBeans>
    <jaxrs:providers>
      <bean ref="customProvider"/>
    </jaxrs:providers>
  </jaxrs:server>
  
  <bean id="customProvider" class="org.apache.cxf.systest.jaxrs.CustomerProvider"/>
</beans>

Starting from CXF 2.7.2 it is possible to register provider directly on the bus as the bus properties and share them between all the providers using this bus:

Code Block
xml
xml

<beans>
  
  <cxf:bus>
        <cxf:properties>
            <entry key="javax.ws.rs.ext.ExceptionMapper" ref="exceptionMapper"/>
        </cxf:properties>
  </cxf:bus

  <bean id="exceptionMapper" class="org.apache.cxf.systest.jaxrs.RuntimeExceptionMapper"/>

  <jaxrs:server id="customerService" address="/service1">
    <jaxrs:serviceBeans>
      <bean class="org.apache.cxf.systest.jaxrs.CustomerService"/>
    </jaxrs:serviceBeans>
  </jaxrs:server>

  <jaxrs:server id="customerService" address="/service2">
    <jaxrs:serviceBeans>
      <bean class="org.apache.cxf.systest.jaxrs.CustomerService2"/>
    </jaxrs:serviceBeans>
  </jaxrs:server>
  
  </beans>

...

Alternatively, one can have all the providers (JAX-RS and CXF-specific) registered with a bus using "org.apache.cxf.jaxrs.bus.providers" list property:

Code Block
xml
xml

<beans xmlns:util="http://www.springframework.org/schema/util">
  
  <cxf:bus>
        <cxf:properties>
            <entry key="org.apache.cxf.jaxrs.bus.providers" ref="busProviders"/>
        </cxf:properties>
  </cxf:bus

  <util:list id="busProviders">
    <ref bean="exceptionMapper"/>
    <ref bean="customMessageBodyReader"/>
    <ref bean="customMessageBodyWriter"/>
  </util:list>

  <bean id="exceptionMapper" class="org.apache.cxf.systest.jaxrs.RuntimeExceptionMapper"/>
  <bean id="customMessageBodyReader" class="org.apache.cxf.systest.jaxrs.CustomReader"/>
  <bean id="customMessageBodyWriter" class="org.apache.cxf.systest.jaxrs.CustomWriter"/> 

  <jaxrs:server id="customerService" address="/service1">
    <jaxrs:serviceBeans>
      <bean class="org.apache.cxf.systest.jaxrs.CustomerService"/>
    </jaxrs:serviceBeans>
  </jaxrs:server>

  <jaxrs:server id="customerService" address="/service2">
    <jaxrs:serviceBeans>
      <bean class="org.apache.cxf.systest.jaxrs.CustomerService2"/>
    </jaxrs:serviceBeans>
  </jaxrs:server>
  
  </beans>

...

In some advanced cases you may want to dynamically add new servlets (CXFServlet or CXFNonSpringJaxrsServlet) with all of them serving the same JAX-RS endpoints. In this case you most likely want to configure servlets so that the CXF endpoint address is not overridden :

Code Block
xml
xml

{code:xml}
<servlet>
 <servlet-name>CXFServlet</servlet-name>
 <display-name>CXF Servlet</display-name>
 <servlet-class>
     org.apache.cxf.transport.servlet.CXFServlet
 </servlet-class>
 <init-param>
    <param-name>config-location</param-name>
    <param-value>/WEB-INF/beans1.xml</param-value>
 </init-param>
 <init-param>
    <param-name>disable-address-updates</param-name>
    <param-value>true</param-value>
 </init-param>
 <load-on-startup>1</load-on-startup>
</servlet>
Code Block
 

Auto-discovery of root resources and providers

Starting from CXF 3.0.0 it is possible to enable the auto-discovery of JAX-RS roots and providers with the regular CXF JAX-RS endpoint declarations done in XML . Currently it is only possible with Spring. Patch supporting it for Blueprint is available and will be dealt with asap.

 

Spring

Code Block
xml
xml
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:jaxrs="http://cxf.apache.org/jaxrs"
      xsi:schemaLocation="
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
         http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">

     <import resource="classpath:META-INF/cxf/cxf.xml" />
     
     <!-- 
         Discover all root resources and providers in packages starting from "a.b.c" 
     -->
     <jaxrs:server address="/customers" basePackages="a.b.c"/>

     <!-- 
       Discover a root resource and providers in packages starting from "a.b.c" and "d.e.f",
       Note that in case of jaxrs:client, having multiple discoverable root resources can lead to
       unexpected results, as only the single root can be recognized 
     -->
     <jaxrs:client address="http://customers" basePackages="a.b.c,d.e.f"/>

      
</beans>

Servlet and Application Container Configuration

...