Red Hat Training

A Red Hat training course is available for Red Hat Fuse

Chapter 16. Configuring JAX-RS Endpoints

Abstract

This chapter explains how to instantiate and configure JAX-RS server endpoints in Blueprint XML and in Spring XML, and also how to instantiate and configure JAX-RS client endpoints (client proxy beans) in XML

16.1. Configuring JAX-RS Server Endpoints

16.1.1. Defining a JAX-RS Server Endpoint

Basic server endpoint definition

To define a JAX-RS server endpoint in XML, you need to specify at least the following:
  1. A jaxrs:server element, which is used to define the endpoint in XML. Note that the jaxrs: namespace prefix maps to different namespaces in Blueprint and in Spring respectively.
  2. The base URL of the JAX-RS service, using the address attribute of the jaxrs:server element. Note that there are two different ways of specifying the address URL, which affects how the endpoint gets deployed:
    • As a relative URL—for example, /customers. In this case, the endpoint is deployed into the default HTTP container, and the endpoint's base URL is implicitly obtained by combining the CXF servlet base URL with the specified relative URL.
      For example, if you deploy a JAX-RS endpoint to the JBoss Fuse container, the specified /customers URL would get resolved to the URL, http://Hostname:8181/cxf/customers (assuming that the container is using the default 8181 port).
    • As an absolute URL—for example, http://0.0.0.0:8200/cxf/customers. In this case, a new HTTP listener port is opened for the JAX-RS endpoint (if it is not already open). For example, in the context of JBoss Fuse, a new Jetty container would implicitly be created to host the JAX-RS endpoint. The special IP address, 0.0.0.0, acts as a wildcard, matching any of the hostnames assigned to the current host (which can be useful on multi-homed host machines).
  3. One or more JAX-RS root resource classes, which provide the implementation of the JAX-RS service. The simplest way to specify the resource classes is to list them inside a jaxrs:serviceBeans element.

Blueprint example

The following Blueprint XML example shows how to define a JAX-RS endpoint, which specifies the relative address, /customers (so that it deploys into the default HTTP container) and is implemented by the service.CustomerService resource class:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    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>

Blueprint XML namespaces

To define a JAX-RS endpoint in Blueprint, you typically require at least the following XML namespaces:
PrefixNamespace
(default)http://www.osgi.org/xmlns/blueprint/v1.0.0
cxfhttp://cxf.apache.org/blueprint/core
jaxrshttp://cxf.apache.org/blueprint/jaxrs

Spring example

The following Spring XML example shows how to define a JAX-RS endpoint, which specifies the relative address, /customers (so that it deploys into the default HTTP container) and is implemented by the service.CustomerService resource class:
<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">
 
     <jaxrs:server id="customerService" address="/customers">
        <jaxrs:serviceBeans>
           <ref bean="serviceBean"/>
        </jaxrs:serviceBeans>
     </jaxrs:server>
       
     <bean id="serviceBean" class="service.CustomerService"/> 
</beans>

Spring XML namespaces

To define a JAX-RS endpoint in Spring, you typically require at least the following XML namespaces:
PrefixNamespace
(default)http://www.springframework.org/schema/beans
cxfhttp://cxf.apache.org/core
jaxrshttp://cxf.apache.org/jaxrs

Auto-discovery in Spring XML

(Spring only) Instead of specifying the JAX-RS root resource classes explicitly, Spring XML enables you to configure auto-discovery, so that specific Java packages are searched for resource classes (classes annotated by @Path) and all of the discovered resource classes are automatically attached to the endpoint. In this case, you need to specify just the address attribute and the basePackages attribute in the jaxrs:server element.
For example, to define a JAX-RS endpoint which uses all of the JAX-RS resource classes under the a.b.c Java package, you can define the endpoint in Spring XML, as follows:
<jaxrs:server address="/customers" basePackages="a.b.c"/>
The auto-discovery mechanism also discovers and installs into the endpoint any JAX-RS provider classes that it finds under the specified Java packages.

Lifecycle management in Spring XML

(Spring only) Spring XML enables you to control the lifecycle of beans by setting the scope attribute on a bean element. The following scope values are supported by Spring:
singleton
(Default) Creates a single bean instance, which is used everywhere and lasts for the entire lifetime of the Spring container.
prototype
Creates a new bean instance every time the bean is injected into another bean or when a bean is obtained by invoking getBean() on the bean registry.
request
(Only available in a Web-aware container) Creates a new bean instance for every request invoked on the bean.
session
(Only available in a Web-aware container) Creates a new bean for the lifetime of a single HTTP session.
globalSession
(Only available in a Web-aware container) Creates a new bean for the lifetime of a single HTTP session that is shared between portlets.
For more details about Spring scopes, please consult the Spring framework documentation on Bean scopes.
Note that Spring scopes do not work properly, if you specify JAX-RS resource beans through the jaxrs:serviceBeans element. If you specify the scope attribute on the resource beans in this case, the scope attribute is effectively ignored.
In order to make bean scopes work properly within a JAX-RS server endpoint, you require a level of indirection that is provided by a service factory. The simplest way to configure bean scopes is to specify resource beans using the beanNames attribute on the jaxrs:server element, as follows:
<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>
Where the preceding example configures two resource beans, customerBean1 and customerBean2. The beanNames attribute is specified as a space-separated list of resource bean IDs.
For the ultimate degree of flexibility, you have the option of defining service factory objects explicitly, when you configure the JAX-RS server endpoint, using the jaxrs:serviceFactories element. This more verbose approach has the advantage that you can replace the default service factory implementation with your custom implementation, thus giving you ultimate control over the bean lifecycle. The following example shows how to configure the two resource beans, customerBean1 and customerBean2, using this approach:
<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>
Note
If you specify a non-singleton lifecycle, it is often a good idea to implement and register a org.apache.cxf.service.Invoker bean (where the instance can be registered by referencing it from a jaxrs:server/jaxrs:invoker element).

Attaching a WADL document

You can optionally associate a WADL document with the JAX-RS server endpoint using the docLocation attribute on the jaxrs:server element. For example:
<jaxrs:server address="/rest" docLocation="wadl/bookStore.wadl">
   <jaxrs:serviceBeans>
      <bean class="org.bar.generated.BookStore"/> 
   </jaxrs:serviceBeans>
</jaxrs:server>

Schema validation

If you have some external XML schemas, for describing message content in JAX-B format, you can associate these external schemas with the JAX-RS server endpoint through the jaxrs:schemaLocations element.
For example, if you have associated the server endpoint with a WADL document and you also want to enable schema validation on incoming messages, you can specify associated XML schema files as follows:
<jaxrs:server address="/rest"
              docLocation="wadl/bookStore.wadl">
   <jaxrs:serviceBeans>
     <bean class="org.bar.generated.BookStore"/> 
   </jaxrs:serviceBeans>
   <jaxrs:schemaLocations>
     <jaxrs:schemaLocation>classpath:/schemas/a.xsd</jaxrs:schemaLocation>
     <jaxrs:schemaLocation>classpath:/schemas/b.xsd</jaxrs:schemaLocation>
   </jaxrs:schemaLocations>
</jaxrs:server>
Alternatively, if you want to include all of the schema files, *.xsd, in a given directory, you can just specify the directory name, as follows:
<jaxrs:server address="/rest"
              docLocation="wadl/bookStore.wadl">
   <jaxrs:serviceBeans>
     <bean class="org.bar.generated.BookStore"/> 
   </jaxrs:serviceBeans>
   <jaxrs:schemaLocations>
     <jaxrs:schemaLocation>classpath:/schemas/</jaxrs:schemaLocation>
   </jaxrs:schemaLocations>
</jaxrs:server>
Specifying schemas in this way is generally useful for any kind of functionality that requires access to the JAX-B schemas.

Specifying the data binding

You can use the jaxrs:dataBinding element to specify the data binding that encodes the message body in request and reply messages. For example, to specify the JAX-B data binding, you could configure a JAX-RS endpoint as follows:
<jaxrs:server id="jaxbbook" address="/jaxb">
  <jaxrs:serviceBeans>
    <ref bean="serviceBean" />
  </jaxrs:serviceBeans>	   
  <jaxrs:dataBinding>
    <bean class="org.apache.cxf.jaxb.JAXBDataBinding"/>
  </jaxrs:dataBinding>
</jaxrs:server>>
Or to specify the Aegis data binding, you could configure a JAX-RS endpoint as follows:
<jaxrs:server id="aegisbook" address="/aegis">
  <jaxrs:serviceBeans>
    <ref bean="serviceBean" />
  </jaxrs:serviceBeans>		   
  <jaxrs:dataBinding> 
    <bean class="org.apache.cxf.aegis.databinding.AegisDatabinding">
      <property name="aegisContext">
        <bean class="org.apache.cxf.aegis.AegisContext">
          <property name="writeXsiTypes" value="true"/>
        </bean>
      </property>    
    </bean> 
  </jaxrs:dataBinding> 
</jaxrs:server>

Using the JMS transport

It is possible to configure JAX-RS to use a JMS messaging library as a transport protocol, instead of HTTP. Because JMS itself is not a transport protocol, the actual messaging protocol depends on the particular JMS implementation that you configure.
For example, the following Spring XML example shows how to configure a JAX-RS server endpoint to use the JMS transport protocol:
<?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:jms="http://cxf.apache.org/transports/jms"
       xmlns:jaxrs="http://cxf.apache.org/jaxrs"
       xsi:schemaLocation="
http://cxf.apache.org/transports/jms http://cxf.apache.org/schemas/configuration/jms.xsd
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">

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
    <bean id="ConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://localhost:${testutil.ports.EmbeddedJMSBrokerLauncher}" />
    </bean>

    <jaxrs:server xmlns:s="http://books.com" 
    	serviceName="s:BookService" 
    	transportId= "http://cxf.apache.org/transports/jms" 
    	address="jms:queue:test.jmstransport.text?replyToName=test.jmstransport.response">
        <jaxrs:serviceBeans>
            <bean class="org.apache.cxf.systest.jaxrs.JMSBookStore"/>
        </jaxrs:serviceBeans>
    </jaxrs:server>

</beans>
Note the following points about the preceding example:
  • JMS implementation—the JMS implementation is provided by the ConnectionFactory bean, which instantiates an Apache ActiveMQ connection factory object. After you instantiate the connection factory, it is automatically installed as the default JMS implementation layer.
  • JMS conduit or destination object—Apache CXF implicitly instantiates a JMS conduit object (to represent a JMS consumer) or a JMS destination object (to represent a JMS provider). This object must be uniquely identified by a QName, which is defined through the attribute setttings xmlns:s="http://books.com" (defining the namespace prefix) and serviceName="s:BookService" (defining the QName).
  • Transport ID—to select the JMS transport, the transportId attribute must be set to http://cxf.apache.org/transports/jms.
  • JMS address—the jaxrs:server/@address attribute uses a standardized syntax to specify the JMS queue or JMS topic to send to. For details of this syntax, see https://tools.ietf.org/id/draft-merrick-jms-uri-06.txt.

Extension mappings and language mappings

A JAX-RS server endpoint can be configured so that it automatically maps a file suffix (appearing in the URL) to a MIME content type header, and maps a language suffix to a language type header. For example, consider a HTTP request of the following form:
GET /resource.xml
You can configure the JAX-RS server endpoint to map the .xml suffix automatically, as follows:
<jaxrs:server id="customerService" address="/">
  <jaxrs:serviceBeans>
    <bean class="org.apache.cxf.jaxrs.systests.CustomerService" />
  </jaxrs:serviceBeans>
  <jaxrs:extensionMappings>
    <entry key="json" value="application/json"/>
    <entry key="xml" value="application/xml"/>
  </jaxrs:extensionMappings>
</jaxrs:server>
When the preceding server endpoint receives the HTTP request, it automatically creates a new content type header of type, application/xml, and strips the .xml suffix from the resource URL.
For the language mapping, consider a HTTP request of the following form:
GET /resource.en
You can configure the JAX-RS server endpoint to map the .en suffix automatically, as follows:
<jaxrs:server id="customerService" address="/">
  <jaxrs:serviceBeans>
    <bean class="org.apache.cxf.jaxrs.systests.CustomerService" />
  </jaxrs:serviceBeans>
  <jaxrs:languageMappings>
     <entry key="en" value="en-gb"/>  
  </jaxrs:languageMappings>
</jaxrs:server>
When the preceding server endpoint receives the HTTP request, it automatically creates a new accept language header with the value, en-gb, and strips the .en suffix from the resource URL.

16.1.2. jaxrs:server Attributes

Attributes

Table 16.1, “JAX-RS Server Endpoint Attributes” describes the attributes available on the jaxrs:server element.

Table 16.1. JAX-RS Server Endpoint Attributes

AttributeDescription
id Specifies a unique identifier that other configuration elements can use to refer to the endpoint.
address Specifies the address of an HTTP endpoint. This value will override the value specified in the services contract.
basePackages(Spring only) Enables auto-discovery, by specifying a comma-separated list of Java packages, which are searched to discover JAX-RS root resource classes and/or JAX-RS provider classes.
beanNamesSpecifies a space-separated list of bean IDs of JAX-RS root resource beans. In the context of Spring XML, it is possible to define a root resource beans' lifecycle by setting the scope attribute on the root resource bean element.
bindingId Specifies the ID of the message binding the service uses. A list of valid binding IDs is provided in Appendix C, Apache CXF Binding IDs.
bus Specifies the ID of the Spring bean configuring the bus used to manage the service endpoint. This is useful when configuring several endpoints to use a common set of features.
docLocationSpecifies the location of an external WADL document.
modelRefSpecifies a model schema as a classpath resource (for example, a URL of the form classpath:/path/to/model.xml). For details of how to define a JAX-RS model schema, see Section 16.3, “Defining REST Services with the Model Schema”.
publishSpecifies if the service should be automatically published. If set to false, the developer must explicitly publish the endpoint.
publishedEndpointUrlSpecifies the URL base address, which gets inserted into the wadl:resources/@base attribute of the auto-generated WADL interface.
serviceAnnotation(Spring only) Specifies the service annotation class name for auto-discovery in Spring. When used in combination with the basePackages property, this option restricts the collection of auto-discovered classes to include only the classes that are annotated by this annotation type.
serviceClass Specifies the name of a JAX-RS root resource class (which implements a JAX-RS service). In this case, the class is instantiated by Apache CXF, not by Blueprint or Spring. If you want to instantiate the class in Blueprint or Spring, use the jaxrs:serviceBeans child element instead.
serviceName Specifies the service QName (using the format ns:name) for the JAX-RS endpoint in the special case where a JMS transport is used. For details, see the section called “Using the JMS transport”.
staticSubresourceResolutionIf true, disables dynamic resolution of static sub-resources. Default is false.
transportIdFor selecting a non-standard transport layer (in place of HTTP). In particular, you can select the JMS transport by setting this property to http://cxf.apache.org/transports/jms. For details, see the section called “Using the JMS transport”.
abstract (Spring only) Specifies if the bean is an abstract bean. Abstract beans act as parents for concrete bean definitions and are not instantiated. The default is false. Setting this to true instructs the bean factory not to instantiate the bean.
depends-on (Spring only) Specifies a list of beans that the endpoint depends on being instantiated before the endpoint can be instantiated.

16.1.3. jaxrs:server Child Elements

Child elements

Table 16.2, “JAX-RS Server Endpoint Child Elements” describes the child elements of the jaxrs:server element.

Table 16.2. JAX-RS Server Endpoint Child Elements

ElementDescription
jaxrs:executor Specifies a Java Executor (thread pool implementation) that is used for the service. This is specified using an embedded bean definition.
jaxrs:features Specifies a list of beans that configure advanced features of Apache CXF. You can provide either a list of bean references or a list of embedded beans.
jaxrs:binding Not used.
jaxrs:dataBinding Specifies the class implementing the data binding used by the endpoint. This is specified using an embedded bean definition. For more details, see the section called “Specifying the data binding”.
jaxrs:inInterceptors Specifies a list of interceptors that process inbound requests. For more information see Part VII, “Developing Apache CXF Interceptors”.
jaxrs:inFaultInterceptors Specifies a list of interceptors that process inbound fault messages. For more information see Part VII, “Developing Apache CXF Interceptors”.
jaxrs:outInterceptors Specifies a list of interceptors that process outbound replies. For more information see Part VII, “Developing Apache CXF Interceptors”.
jaxrs:outFaultInterceptors Specifies a list of interceptors that process outbound fault messages. For more information see Part VII, “Developing Apache CXF Interceptors”.
jaxrs:invoker Specifies an implementation of the org.apache.cxf.service.Invoker interface used by the service. [a]
jaxrs:serviceFactoriesProvides you with the maximum degree of control over the lifecycle of the JAX-RS root resources associated with this endpoint. The children of this element (which must be instances of org.apache.cxf.jaxrs.lifecycle.ResourceProvider type) are used to create JAX-RS root resource instances.
jaxrs:propertiesSpecifies a Spring map of properties that are passed along to the endpoint. These properties can be used to control features like enabling MTOM support.
jaxrs:serviceBeansThe children of this element are instances of (bean element) or references to (ref element) JAX-RS root resources. Note that in this case the scope attribute (Spring only), if present in the bean element, is ignored.
jaxrs:modelBeansConsists of a list of references to one or more org.apache.cxf.jaxrs.model.UserResource beans, which are the basic elements of a resource model (corresponding to jaxrs:resource elements). For details, see Section 16.3, “Defining REST Services with the Model Schema”.
jaxrs:modelDefines a resource model directly in this endpoint (that is, this jaxrs:model element can contain one or more jaxrs:resource elements). For details, see Section 16.3, “Defining REST Services with the Model Schema”.
jaxrs:providersEnables you to register one or more custom JAX-RS providers with this endpoint. The children of this element are instances of (bean element) or references to (ref element) JAX-RS providers.
jaxrs:extensionMappingsWhen the URL of a REST invocation ends in a file extension, you can use this element to associate it automatically with a particular content type. For example, the .xml file extension could be associated with the application/xml content type. For details, see the section called “Extension mappings and language mappings”.
jaxrs:languageMappingsWhen the URL of a REST invocation ends in a language suffix, you can use this element to map this to a particular language. For example, the .en language suffix could be associated with the en-GB language. For details, see the section called “Extension mappings and language mappings”.
jaxrs:schemaLocationsSpecifies one or more XML schemas used for validating XML message content. This element can contain one or more jaxrs:schemaLocation elements, each specifying the location of an XML schema file (usually as a classpath URL). For details, see the section called “Schema validation”.
jaxrs:resourceComparatorEnables you to register a custom resource comparator, which implements the algorithm used to match an incoming URL path to a particular resource class or method.
jaxrs:resourceClasses(Blueprint only) Can be used instead of the jaxrs:server/@serviceClass attribute, if you want to create multiple resources from class names. The children of jaxrs:resourceClasses must be class elements with a name attribute set to the name of the resource class. In this case, the classes are instantiated by Apache CXF, not by Blueprint or Spring.
[a] The Invoker implementation controls how a service is invoked. For example, it controls whether each request is handled by a new instance of the service implementation or if state is preserved across invocations.