Versions Compared

Key

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

...

Span
stylefont-size:2em;font-weight:bold
JAX-RS : Advanced Features

 



Table of Contents

JMS Support

...

CacheControlFeature parses the Cache-Control header and caches the Response payload if appropriate for the "max-age" attribute of Cache-Control (or the "Expires" HTTP header if max-age is not specified). The next time the client calls out to the remote service (only GET is supported for now), the Response payload is retrieved from the cache and returned instead (assuming it is not expired), thus avoiding an unnecessary round-trip. Here is an example:

Code Block
xml
xml
CacheControlFeature cacheControlFeature = new CacheControlFeature();
cacheControlFeature.setCacheResponseInputStream(true);
Client client = ClientBuilder.newBuilder()
                           .register(cacheControlFeature)
                           .build();
WebTarget target = client.target(endpointAddress);

// First call
Response response = target.request().get();
// Second call should be cached
target.request().get();

 

Server-side caching

Ehcache-Web and other similar frameworks can be used to provide an advanced support for the server-side caching.

For example, the only thing you need to do to interpose Ehcache-Web on top of CXF JAX-RS endpoints is to add the following declarations to the web.xml, assuming the name of the war is 'ehcache-cxf':

If the initial response from the service contains an "ETag" HTTP header, then once the message has expired, CXF will send this value to the service as the "If-None-Match" header. Similarly, "Last-Modified" is sent as "If-Modified-Since". The CXF client will also cache the expired payload. If the service responds with a 304 status code, then the old message payload is returned to the client.

Server-side caching

Ehcache-Web and other similar frameworks can be used to provide an advanced support for the server-side caching.

For example, the only thing you need to do to interpose Ehcache-Web on top of CXF JAX-RS endpoints is to add the following declarations to the web.xml, assuming the name of the war is 'ehcache-cxf':

Code Block
xml
xml
<context-param>
Code Block
xmlxml
<context-param>
    <param-name>webAppRootKey</param-name>
    <param-value>ehcache-name>webAppRootKey</param-name>
    <param-value>ehcache-cxf</param-value>
</context-param>
<filter>
    <filter-name>SimplePageCachingFilter</filter-name>
    <filter-class>net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter</filter-class>
    <init-param>
        <param-name>varyHeader</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
    
<filter-mapping>
    <filter-name>SimplePageCachingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

...

Code Block
java
java
public class JAXRSUserModelServlet extends CXFNonSpringJaxrsServlet  {

    @Override
    public void loadBus(ServletConfig servletConfig) throws ServletException {
        super.loadBus(servletConfig);

        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
        String address = servletConfig.getInitParameter(SERVICE_ADDRESS_PARAM); //jaxrs.address(servletConfig);

        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
        String address = servletConfig.getInitParameter(SERVICE_ADDRESS_PARAM); //jaxrs.address
        if (address == null) {
            address = "/";
        }
        sf.setAddress(address);

        // modelRef needs to start from 'classpath:', ex 'classpath:/WEB-INF/models/model1.xml
        String modelRef = servletConfig.getInitParameter("user.model");
        sf.setModelRef(modelRef);
        sf.create();
    }
} 

Query String Customization

CXF provides advanced capabilities with respect to query string parsing and expansion.

Collection/List

The typical way to manage collection/list query parameters is described in RFC-6570: URI Template (https://tools.ietf.org/html/rfc6570) and basically assumes the repetition of the name/value pairs, for example: http://localhost:8080/MovieDB/GetJson?name=Actor1&name=Actor2&name=Actor3&startDate=20120101&endDate=2012050

Since 3.1.8+, this behavior could be tweaked using server-side "parse.query.value.as.collection" property,  which adds support for collection/list parameters passed as comma-separated values, , for example: http://localhost:8080/MovieDB/GetJson?name=Actor1,Actor2,Actor3&startDate=20120101&endDate=2012050

The client support was lacking and was added in 3.3.4+ / 3.2.11+ / 3.4.0+ for all types of the clients (WebClient, JAX-RS Client Proxy and Microprofile Client). The matching property name is "expand.query.value.as.collection" and could be specified during the client instance creation, for example:

Code Block
java
java
MyClient client = JAXRSClientFactory
    .create("http://localhost:8080", MyClient.class,
        if (address == null) {
  Collections.singletonMap("expand.query.value.as.collection", "true"));


Code Block
java
java
WebClient client = WebClient.create("http://localhost:8080", 
    Collections.singletonMap("expand.query.value.as.collection", "true"));


Code Block
java
java
MyClient client = RestClientBuilder
    .newBuilder()
    .property("expand.query.value.as.collection", "true")
    .baseUri(new URI("http://localhost:8080"))
    .build(MyClient.class);


Code Block
java
java
WebTarget target = ClientBuilder
    .newClient()
    .property("expand.query.value.as.collection", "true")
    .target("http://localhost:8080");          address = "/";
        }
        sf.setAddress(address);

        // modelRef needs to start from 'classpath:', ex 'classpath:/WEB-INF/models/model1.xml
        String modelRef = servletConfig.getInitParameter("user.model");
        sf.setModelRef(modelRef);
        sf.create();
    }
}