Versions Compared

Key

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

 

 

 

Span
stylefont-size:2em;font-weight:bold
JAX-RS : Services Configuration

...

 

...

 


Table of Contents

Configuring JAX-RS services programmatically

...

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>

...

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>

...

Spring Boot

Please see CXF SpringBoot documentation. 

Please see JAX-RS Spring Boot and JAX-RS Spring Boot Scan demos.

Please see JAXRSClientSpringBoot documentation on how CXF JAX-RS Clients can be used in a SpringBoot Application. 

 

Configuring JAX-RS endpoints programmatically without Spring

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();

...

Blueprint Web

This section describes how CXF JAX-RS

...

web.xml

In web.xml one needs to register one or more CXFServlet(s) and link to an application context configuration.

...

endpoints can be bootstrapped with CXFBlueprintServlet and Blueprint contexts.

This approach is recommended for developers building CXF JAX-RS endpoints to be deployed in OSGI and which will do RequestDispatcher-based forwards.

Additionally it allows to reuse the same Blueprint contexts between OSGI and non-OSGI deployments.

Both options below work with CXF 3.1.3:

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>

The application context configuration is shared between all the CXFServlets

...

<dependency>
  <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-rt-frontend-jaxrs</artifactId>
  <version>3.1.3</version>
</dependency>

 

Maven dependencies

OSGI

Code Block
xml
xml
<dependency>
  <groupId>org.apache.aries.blueprint</groupId>
  <artifactId>org.apache.aries.blueprint.webosgi</artifactId>
  <version>1.0.1</version>
</dependency>

In OSGI (Karaf) one should also install a 'war' feature.

Servlet Container

Code Block
xml
xml
<dependency>
  <groupId>org.apache.aries.blueprint</groupId>
  <artifactId>org.apache.aries.blueprint.web</artifactId>
  <version>1.1.1</version>
</dependency>

 

Common example

 

This web.xml shows how to setup CXFBlueprintServlet which processes this Blueprint context. It works exactly the same way in OSGI and non-OSGI environments.

Configuring JAX-RS services in container with Spring configuration file.

web.xml

In web.xml one needs to register one or more CXFServlet(s) and link to an application context configuration.

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>
	<servlet><context-param>
		<servlet<param-name>CXFServlet1<name>contextConfigLocation</servletparam-name>
		<display-name>CXF Servlet1</display-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>

The application context configuration is shared between all the CXFServlets

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>
        <init-param>
            <param-name>config-location</param-name>
                   <param<param-value>/WEB-INF/beans2beans1.xml</param-value>
                </init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

    <servlet>
		<servlet-mapping>name>CXFServlet2</servlet-name>
		<servlet<display-name>CXFServlet1<name>CXF Servlet2</servletdisplay-name>
		<url-pattern>/1/*</url-pattern>
	<servlet-class>
			org.apache.cxf.transport.servlet.CXFServlet
		</servlet-mapping>
class>
        <init-param>
        <servlet-mapping>
		<servlet-name>CXFServlet2</servlet-name>
		<url-pattern>/2    <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>
</web-app>

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

Each CXFServlet can Each CXFServlet can get a unique application context configuration. Note, no Spring ContextLoaderListener is registered in web.xml in this case.

...

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> name="serviceBeans">
      <ref bean="customerBean" />
    </property:serviceBeans>property>
  </jaxrs:server>bean>

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

...

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>

When service classes and providers are registered this way, the default life-cycle is 'singleton'. You can override it by setting a "jaxrs.scope" parameter with the value of 'prototype' (equivalent to per-request).
By default, the endpoint address is "/". One can provide a more specific value using a "jaxrs.address" parameter.

Note that multiple service  or providers class names are separated by a comma. Users may want to use a "class.parameter.split.char" servlet parameter with the value "space" when

migrating from the older CXF versions were the space was used to separate multiple class names.

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

...

Prototype beans will have their postconstruct and predestroy method called before a resource method is invoked and immediately after the invocation has returned but before the response has actually been serialized. You can indicate that the predestroy method has to be called after the request has completely gone out of scope (that is after the response body if any has been written to the output stream) by adding an "org.apache.cxf.jaxrs.service.scope" property with the value set to "request".

...

Code Block
xml
xml
<beans>
  
  <cxf:bus>
        <cxf:properties>
            <entry key="javax.ws.rs.ext.ExceptionMapper" value-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>

...

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" value-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="/service1">
    <jaxrs:serviceBeans>/service2">
    <jaxrs:serviceBeans>
      <bean class="org.apache.cxf.systest.jaxrs.CustomerService2"/>
    </jaxrs:serviceBeans>
  </jaxrs:server>
  
  </beans>

Dynamic servlets and a single JAX-RS endpoint

Note: this is not required by default starting from CXF 3.0.0-milestone1

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>
      <bean class="org.apache.cxf.systesttransport.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>

Dynamic servlets and a single JAX-RS endpoint

Note: this is not required by default starting from CXF 3.0.0-milestone1

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: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>
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>


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>

Note the above does not require Spring annotations such as @Component added to JAX-RS provider or resources.

If you prefer doing a pure Spring-based auto-discovery you can have @Component added to JAX-RS application classes and do

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"
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
xmlxml
<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:clientserver address="http://customers" basePackages/>
     <context:component-scan base-package="a.b.c,d.e.f"/>

      
< </beans>

 

Servlet and Application Container Configuration

Please see this page for more information.

Starting from CXF 3.1.0: org.apache.cxf.jaxrs.servlet.sci.JaxrsServletContainerInitializer implementing javax.servlet.ServletContainerInitializer is shipped in a cxf-rt-rs-http-sci module.

Adding this module will support  no-web.xml and other JAX-RS deployments depending on the container auto-discovery mechanism as described in a 2.3.2 section of JSR-339 (JAX-RS 2.0).