Versions Compared

Key

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



{span:style=
Span
Wiki Markup
style
font-size:2em;font-weight:bold
} JAX-RS : Understanding the Basics {span}

 



Table of Contents

What is New in JAX-RS 2.

...

1

Filters

Server

ContainerRequestFilter and ContainerResponseFilter are new server-side request and response filters which can be used to customize various properties of a given request and response.

ContainerRequestFilter annotated with a PreMatching annotation will be run before the runtime has matched a request to a specific JAX-RS root resource and method. Prematching filters can be used to affect the matching process.

The request filters without the PreMatching annotation will run after the JAX-RS resource method has been selected.

ContainerRequestFilter can be used to block a request.

The filters can be bound to individual resource methods only with the help of custom NameBindings.

Multiple request and response filters can be executed in the specific order by using javax.annotation.Priority annotations. See Priorities for more information. Request filters are sorted in the ascending order, response filters - in the descending order.

Client

ClientRequestFilter and ClientResponseFilter are new client-side request and response filters which can be used to customize various properties of a given request and response.

ClientRequestFilter can be used to block a request.

Request filters are sorted in the ascending order, response filters - in the descending order. See Priorities for more information.

Interceptors

ReaderInterceptor and WriterInterceptor can be used in addition to filters or on its own to customize requests and responses on server and client sides.

Interceptors can be useful to customize the reading/writing process and block JAX-RS MessageBodyWriter or MessageBodyReader providers.

The interceptors used on the server side can be bound to individual resource methods only with the help of custom NameBindings.

All interceptors are sorted in the ascending order. See Priorities for more information.

Dynamic Features

Dynamic Feature is a server side feature that can be used to attach request and response filters as well as reader and writer interceptors to specific resource methods. It is an alternative approach to using the NameBindings and offer a finer-grained control over the binding process.

Exceptions

Dedicated exception classes representing various HTTP error or redirect conditions have been introduced, see the 'javax.ws.rs' Package Exceptions section.

For example, instead of throwing a "new WebApplicationException(404)" one is better to do "new NotFoundException()". The finer-grained exception hierarchy allows for a finer-grained support of exception mappers. It also opens a way to check WebApplicationException and all of its subclasses when catching the HTTP exceptions on the client side.

Note that on the client side, ProcessingException can be used to catch client-related exceptions while ResponseProcessingException can be used to narrow down the client side exceptions specifically related to processing the response message.

Suspended invocations

One of the best JAX-RS 2.0 features is the support for server-side asynchronous invocations. Please see the AsyncResponse documentation which provides a very good overview of this feature.

See also this test resource.

Typically, the resource method accepting AsyncResponse will either store it and start a new thread to finish the request, the method will return and the invocation will be suspended, then eventually another thread (either the one which initiated an internal job or some other thread) will resume the suspended call. Note in this case the invocation will be suspended indefinitely until it is resumed.

Another approach is to have AsyncResponse suspended for a limited period of time only and also register a TimeoutHandler. The latter will be invoked when the invocation is resumed by the container after the timeout has expired and the handler will either complete the invocation or suspend it again till it is ready to finish it.

CompletionCallback can be registered with AsyncResponse to receive the notifications when the async response has been sent back.

ConnectionCallback is supported starting from CXF 3.0.0-milestone2.

This feature can help developers write very sophisticated asynchronous applications.

Please also see the page about CXF Continuations API which JAX-RS 2.0 AsyncResponse implementation is based upon and
how to configure CXFServlet.

Parameter converters

ParamConverterProvider can be used to manage the conversion of custom Objects to String and vice versa on the server and client sides, when processing JAX-RS parameters representing URI parts or headers or form elements and when a default conversion mechanism does not work. For example, java.util.Date constructor accepting a String may have to be replaced a custom ParamConverter.

Bean parameters

BeanParam can be used to get JAX-RS parameters representing URI parts or headers or form elements and also contexts injected into a single bean container.

Note the CXF extension supporting the injection of all the parameters of specific JAX-RS type (example, QueryParam("") MyBean) is different, it only allows to get all the query parameters injected, but it also does not require that bean properties are annotated with QueryParam/etc annotations.

ResourceInfo

ResourceInfo is a new JAX-RS context which can be injected into filters and interceptors and checked which resource class and method are about to be invoked.

Injection into subresources

Subresources can get JAX-RS contexts injected directly into their fields with the help of ResourceContext.

When possible, having a parent resource injecting the contexts into a given subresource instance via a setter or constructor can offer a much simpler alternative.

Updates to the matching algorithm

JAX-RS 2.0 supports a proper resource method selection in cases where multiple root resource classes have the same Path value, for example:

...

@Path("/")
public class Root1 {
   @Path("/1")
   @GET 
   public Response get() {...}
}

@Path("/")
public class Root2 {
   @Path("/2")
   @GET 
   public Response get() {...}
}

Reactive Client API

JAX-RS 2.1 introduces RxInvoker which can help with removing InvocationCallbacks from the asynchronous client code. 

CompletionStage

Default CompletionStageRxInvoker can be accessed via Invocation.rx().

RxJava

Custom RxInvokerProvider can be registered with the Client as a provider. CXF ships one three such custom providers, org.apache.cxf.jaxrs.rx.client.ObservableRxInvokerProvider (RxJava1),

org.apache.cxf.jaxrs.rx2.client.ObservableRxInvokerProvider (RxJava2) and org.apache.cxf.jaxrs.rx2.client.FlowableRxInvokerProvider (RxJava2).

Registering it with the Client allows for working with RxJava1 Observable or RxJava2 Observable or Flowable by doing Invocation.rx(Class<T> clazz), example,

Invocation.rx(org.apache.cxf.jaxrs.rx2.client.FlowableRxInvoker.class), etc.

Please see JAX-RS RxJava for more information.

RxJava2

RxJava2 can be used as a rx type when registered.  Please see JAX-RS RxJava for full information.

Project Reactor

Project Reactor can be used as a rx type when registered.  Please see JAX-RS Project Reactor Support for full information.

CompletableFuture as a method return value

In JAX-RS 2.1 one can return CompletableFuture (or CompletionStage) from a resource method without having to deal directly with JAX-RS AsyncResponse API. 

Please see JAX-RS RxJava for more information about returning RxJava Observable.

Server Sent Events

JAX-RS 2.1 provides a comprehensive support for SSE.

org.apache.cxf/cxf-rt-rs-sse/3.2.0 dependency will need to be added. CXF SSE implementation currently depends on Atmosphere.

SubResources as Classes

Sometimes subresource may need to have the request context information available to them. One valid and simple approach is to pass these contexts to them from the parent class which instantiates a subresource - but sometimes this approach does not work.

In JAX-RS 2.0 one can use ResourceContext to instantiate a subresource instance with the runtime taking care of injecting the contexts if needed. JAX-RS 2.1 introduces a shortcut where returning a subresource class from a subresource locator method, with the runtime istantiating the class and injecting the contexts if needed

CXF NIO Extension

Please see JAX-RS NIO for more information about this CXF 3.2.0 extension which is based on the early JAX-RS 2.1 API prototype.

What is New in JAX-RS 2.0

Filters

Server

ContainerRequestFilter and ContainerResponseFilter are new server-side request and response filters which can be used to customize various properties of a given request and response.

ContainerRequestFilter annotated with a PreMatching annotation will be run before the runtime has matched a request to a specific JAX-RS root resource and method. Prematching filters can be used to affect the matching process.

The request filters without the PreMatching annotation will run after the JAX-RS resource method has been selected.

ContainerRequestFilter can be used to block a request.

The filters can be bound to individual resource methods only with the help of custom NameBindings.

Multiple request and response filters can be executed in the specific order by using javax.annotation.Priority annotations. See Priorities for more information. Request filters are sorted in the ascending order, response filters - in the descending order.

Client

ClientRequestFilter and ClientResponseFilter are new client-side request and response filters which can be used to customize various properties of a given request and response.

ClientRequestFilter can be used to block a request.

Request filters are sorted in the ascending order, response filters - in the descending order. See Priorities for more information.

Interceptors

ReaderInterceptor and WriterInterceptor can be used in addition to filters or on its own to customize requests and responses on server and client sides.

Interceptors can be useful to customize the reading/writing process and block JAX-RS MessageBodyWriter or MessageBodyReader providers.

The interceptors used on the server side can be bound to individual resource methods only with the help of custom NameBindings.

All interceptors are sorted in the ascending order. See Priorities for more information.

Dynamic Features

Dynamic Feature is a server side feature that can be used to attach request and response filters as well as reader and writer interceptors to specific resource methods. It is an alternative approach to using the NameBindings and offer a finer-grained control over the binding process.

Exceptions

Dedicated exception classes representing various HTTP error or redirect conditions have been introduced, see the 'javax.ws.rs' Package Exceptions section.

For example, instead of throwing a "new WebApplicationException(404)" one is better to do "new NotFoundException()". The finer-grained exception hierarchy allows for a finer-grained support of exception mappers. It also opens a way to check WebApplicationException and all of its subclasses when catching the HTTP exceptions on the client side.

Note that on the client side, ProcessingException can be used to catch client-related exceptions while ResponseProcessingException can be used to narrow down the client side exceptions specifically related to processing the response message.

Suspended invocations

One of the best JAX-RS 2.0 features is the support for server-side asynchronous invocations. Please see the AsyncResponse documentation which provides a very good overview of this feature.

See also this test resource.

Typically, the resource method accepting AsyncResponse will either store it and start a new thread to finish the request, the method will return and the invocation will be suspended, then eventually another thread (either the one which initiated an internal job or some other thread) will resume the suspended call. Note in this case the invocation will be suspended indefinitely until it is resumed.

Another approach is to have AsyncResponse suspended for a limited period of time only and also register a TimeoutHandler. The latter will be invoked when the invocation is resumed by the container after the timeout has expired and the handler will either complete the invocation or suspend it again till it is ready to finish it.

CompletionCallback can be registered with AsyncResponse to receive the notifications when the async response has been sent back.

ConnectionCallback is supported starting from CXF 3.0.0-milestone2.

This feature can help developers write very sophisticated asynchronous applications.

Please also see the page about CXF Continuations API which JAX-RS 2.0 AsyncResponse implementation is based upon and
how to configure CXFServlet.

Parameter converters

ParamConverterProvider can be used to manage the conversion of custom Objects to String and vice versa on the server and client sides, when processing JAX-RS parameters representing URI parts or headers or form elements and when a default conversion mechanism does not work. For example, java.util.Date constructor accepting a String may have to be replaced a custom ParamConverter.

Bean parameters

BeanParam can be used to get JAX-RS parameters representing URI parts or headers or form elements and also contexts injected into a single bean container.

Note the CXF extension supporting the injection of all the parameters of specific JAX-RS type (example, QueryParam("") MyBean) is different, it only allows to get all the query parameters injected, but it also does not require that bean properties are annotated with QueryParam/etc annotations.

ResourceInfo

ResourceInfo is a new JAX-RS context which can be injected into filters and interceptors and checked which resource class and method are about to be invoked.

Injection into subresources

Subresources can get JAX-RS contexts injected directly into their fields with the help of ResourceContext.

When possible, having a parent resource injecting the contexts into a given subresource instance via a setter or constructor can offer a much simpler alternative.

Updates to the matching algorithm

JAX-RS 2.0 supports a proper resource method selection in cases where multiple root resource classes have the same Path value, for example:

Code Block
java
java
@Path("/")
public class Root1 {
   @Path("/1")
   @GET 
   public Response get() {...}
}

@Path("/")
public class Root2 {
   @Path("/2")
   @GET 
   public Response get() {...}
}

In JAX-RS 1.1 a request with URI such as "/1" is not guaranteed to be matched and in CXF 2.7.x or earlier the use of CXF specific ResourceComparator is required to ensure Root1 and its get() method gets selected. In CXF 3.0.0 Root1 get() will always be correctly selected. Note ResourceComparator may still be of help in some cases even in CXF 3.0.0.

Link is a utility class for building HTTP links as HTTP Link headers or application data links.
UriInfo, UriBuilder, Response and ResponseBuilder classes have been enhanced to support Link.

Client API

JAX-RS 2.0 Client API has been completely implemented in CXF 3.0.0, please see the Client API page for more information.

Resource class

A resource class is a Java class annotated with JAX-RS annotations to represent a Web resource. Two types of resource classes are available: root resource classes and subresource classes. A root resource class is annotated with at least a @Path annotation, while subresource classes typically have no root @Path values. A typical root resource class in JAX-RS looks like this below:

Code Block
java
java
package demo.jaxrs.server;

import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;

@Path("/customerservice/")
@Produces("application/xml")
public class CustomerService {

    public CustomerService() {
    }

    @GET
    public Customers getCustomers() {
        ......
    }

    @GET
    @Path("/customers/{id}")
    @Produces("application/json")
    public Customer getCustomer(@PathParam("id") String id) {
        ......
    }

    @PUT
    @Path("/customers/{id}")
    @Consumes("application/xml")
    public Response updateCustomer(@PathParam("id") Long id, Customer customer) {
        ......
    }

    @POST
    @Path("/customers")
    public Response addCustomer(Customer customer) {
        ......
    }

    @DELETE
    @Path("/customers/{id}/")
    public Response deleteCustomer(@PathParam("id") String id) {
        ......
    }

    @Path("/orders/{orderId}/")
    public Order getOrder(@PathParam("orderId") String orderId) {
       ......
    }
}

Customer resource class can handle requests starting from /customerservice. When /customerservice requests are matched to this class, its getCustomers() method will be selected. updateCustomer(), deleteCustomer() and addCustomer() are used to serve POST, PUT and DELETE requests starting from /customerservice/customer, while getOrder() method delegates the handling of requests like /customerservice/orders/1 to a subresource locator Order.

The @Produces annotation is used to specify the format of the response. When not available on the resource method, it's inherited from a class, and if it's not available on the class then it's inherited from a corresponding message body writer, if any. Default value is */*, but it's recommended that some definite value is specified. The same applies to @Consumes, except that it's the message body readers that are checked as the last resort.

For example, getCustomers() method inherits @Produces annotation from its class, while getCustomer() method overrides it with its own value.

@Path

The @Path annotation is applied to resource classes or methods. The value of @Path annotation is a relative URI path and follows the URI Template format and may include arbitrary regular expressions. When not available on the resource method, it's inherited from a class. For example:

Code Block
java
java
@Path("/customers/{id}")
public class CustomerResource {

    @GET
    public Customer getCustomer(@PathParam("id") Long id

In JAX-RS 1.1 a request with URI such as "/1" is not guaranteed to be matched and in CXF 2.7.x or earlier the use of CXF specific ResourceComparator is required to ensure Root1 and its get() method gets selected. In CXF 3.0.0 Root1 get() will always be correctly selected. Note ResourceComparator may still be of help in some cases even in CXF 3.0.0.

Link is a utility class for building HTTP links as HTTP Link headers or application data links.
UriInfo, UriBuilder, Response and ResponseBuilder classes have been enhanced to support Link.

Client API

JAX-RS 2.0 Client API has been completely implemented in CXF 3.0.0, please see the Client API page for more information.

Resource class

A resource class is a Java class annotated with JAX-RS annotations to represent a Web resource. Two types of resource classes are available: root resource classes and subresource classes. A root resource class is annotated with at least a @Path annotation, while subresource classes typically have no root @Path values. A typical root resource class in JAX-RS looks like this below:

Code Block
javajava
package demo.jaxrs.server;

import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;

@Path("/customerservice/")
@Produces("application/xml")
public class CustomerService {

    public CustomerService() {
    }

    @GET
    public Customers getCustomers() {
        ......
    }

    @GET
    @Path("/customersorder/{idorderid}")
    public @ProducesOrder getOrder(@PathParam("application/jsonid")
    public Customer getCustomer(Long customerId, @PathParam("idorderid") StringLong idorderId) {
        ......
    }

    @PUT@GET
    @Path("/customersorder/{id}")
    @Consumes("application/xmlorderid}/{search:.*}")
    public ResponseItem updateCustomerfindItem(@PathParam("id") Long idcustomerId, Customer customer) {
        ......
    }

    @POST
    @Path("/customers")
    public Response addCustomer(Customer customer) {@PathParam("orderid") Long orderId,
        ......
    }

    @DELETE
    @Path("/customers/{id}/")
    public Response deleteCustomer(@PathParam("idsearch") String id) {
searchString,
           ......
    }

    @Path("/orders/{orderId}/")
    public Order getOrder(@PathParam("orderIdsearch") StringList<PathSegment> orderIdsearchList) {
        ......
    }
}

Customer resource class can handle requests starting from /customerservice. When /customerservice requests are matched to this class, its getCustomers() method will be selected. updateCustomer(), deleteCustomer() and addCustomer() are used to serve POST, PUT and DELETE requests starting from /customerservice/customer, while getOrder() method delegates the handling of requests like /customerservice/orders/1 to a subresource locator Order.

The @Produces annotation is used to specify the format of the response. When not available on the resource method, it's inherited from a class, and if it's not available on the class then it's inherited from a corresponding message body writer, if any. Default value is */*, but it's recommended that some definite value is specified. The same applies to @Consumes, except that it's the message body readers that are checked as the last resort.

For example, getCustomers() method inherits @Produces annotation from its class, while getCustomer() method overrides it with its own value.

@Path

The @Path annotation is applied to resource classes or methods. The value of @Path annotation is a relative URI path and follows the URI Template format and may include arbitrary regular expressions. When not available on the resource method, it's inherited from a class. For example:



This example is similar to the one above it, but it also shows that an {id} template variable specified as part of the root @Path expression is reused by resource methods and a custom regular expression is specified by a findItem() method (note that a variable name is separated by ':' from an actual expression).

In this example, a request like 'GET /customers/1/order/2/price/2000/weight/2' will be served by the findItem() method.
List<PathSegment> can be used to get to all the path segments in 'price/2000/weight/2' captured by the regular expression.

More information about Path annotations can be found from JAX-RS spec section 2.3.

HTTP Method

The JAX-RS specification defines a number of annotations such as @GET, @PUT, @POST and @DELETE. Using an @HttpMethod designator, one can create a custom annotation such as @Update or @Patch. For example :

Code Block
java
java
package org.apache.cxf.customverb;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("PATCH")
public @interface PATCH { 
}

Default Http Method

CXF 3.0.4 introduces a new extension, a org.apache.cxf.jaxrs.ext.DefaultMethod annotation. It can be used to match arbitrary HTTP methods on a single resource method. This can be used in some advanced scenarious for integrating the CXF JAX-RS runtime into non-JAX-RS environments as well as in cases where it is awkward/difficult to have every HTTP method listed for a given path segment. CXF users need to be aware using this option will lead to a non-portable JAX-RS code.


Return types

Either javax.ws.rs.core.Response or custom type can be returned. javax.ws.rs.core.Response can be used to set the HTTP response code, headers and entity. JAX-RS MessageBodyWriters (see below) are in charge of serializing the response entities, those which are returned directly or as part of javax.ws.rs.core.Response.

Response Streaming 

JAX-RS StreamingOutput

StreamingOutput can be used to stream the data to the client, for example:

Code Block
java
java
@GET
@Path("/books/pdf")
@Produces("application/pdf")
public StreamingOutput getPdf() {
    return new StreamingOutput(
Code Block
javajava
@Path("/customers/{id}")
public class CustomerResource {

    @GET
    public Customer getCustomer(@PathParam("id") Long id) {
        ......
    }

    @GET
    @Path("/order/{orderid}")
    public Order getOrder(@PathParam("id") Long customerId, @PathParam("orderid") Long orderId) {
        ......
    }

    @GET
    @Path("/order/{orderid}/{search:.*}")
    public Item findItem(@PathParam("id") Long customerId, 
                         @PathParam("orderid") Long orderId,
                         @PathParam("search") String searchString,
                         @PathParam("search") List<PathSegment> searchList) {
        ......
    }
}

This example is similar to the one above it, but it also shows that an {id} template variable specified as part of the root @Path expression is reused by resource methods and a custom regular expression is specified by a findItem() method (note that a variable name is separated by ':' from an actual expression).

In this example, a request like 'GET /customers/1/order/2/price/2000/weight/2' will be served by the findItem() method.
List<PathSegment> can be used to get to all the path segments in 'price/2000/weight/2' captured by the regular expression.

More information about Path annotations can be found from JAX-RS spec section 2.3.

HTTP Method

The JAX-RS specification defines a number of annotations such as @GET, @PUT, @POST and @DELETE. Using an @HttpMethod designator, one can create a custom annotation such as @Update or @Patch. For example :

...

package org.apache.cxf.customverb;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("PATCH")
public @interface PATCH { 
}
public void write(final OutputStream os) {
           // read chunks of data from PDF and write to OutputStream
        }  
    };
}

CXF StreamingResponse

CXF 3.0.0 introduces StreamingResponse extension. It can be used with the WebSocket transport or as a possible replacement for the code working with StreamingOutput.

For example, consider that a number of resources need to be returned as they become available:

Code Block
java
java
@GET
@Path("/books")
@Produces("application/xml")
public StreamingResponse<Book> getBooks() {
    return new StreamingResponse<Book>() {
        public void writeTo(final Writer<Book> writer) {
           writer.getEntityStream().write("<Books>".getBytes());
           writer.write(new Book("CXF"));
           writer.write(new Book("JAX-RS"));
           writer.getEntityStream().write("</Books>".getBytes());
        }  
    };
}

Return types

...

Exception handling

One can either throw an unchecked WebApplicationException or return Response with a proper error code set.
The former option may be a better one when no JAX-RS types can be added to method signatures.

...

A simple text error message can also be optionally reported, by setting an 'addMessageToResponse' property to 'true', example:

Code Block
languagexml
<bean id="exceptionMapper" class="org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper">
   <property name="addMessageToResponse" value="true" />
</bean>


Note that the custom WebApplicationException mapperWebApplicationExceptionMapper, if registered, will be preferred to the default oneto the default one in normal cases. However, the default WebApplicationExceptionMapper will win over custom WebApplicationExceptionMapper which are less specific (ex, RuntimeException mappers) but which expect to catch WebApplicationException.  And there is a property "default.wae.mapper.least.specific" is introduced to ensure a CXF custom WebApplicationExceptionMapper can still win over in this specific case.

Dealing with Parameters

PathParam annotation is used to map a given Path template variable to a method parameter.
For example :

...

In this case a template variable id available from a root class annotation is mapped to a parameter of type Long, while a name variable is mapped to a parameter of type String.

@QueryParam, @HttpHeader@HeaderParam, @MatrixParam, @FormParam and @CookieParam annotations are also supported.

Note that the parameters, marked with @FormParam annotation, can take the values from the query parameters in case, if request body is already consumed. This is defined in JAX-RS specification due to the filters (Spring security, etc) consuming the body and thus JAX-RS form parameters becoming empty. User can optionally deactivate standard behavior through setting "set.form.parameters.from.http.parameters" message property to false.

Parameters can be of type String or of any type that have constructors accepting a String parameter or static stat ic valueOf(String s) methods.
Additionally CXF JAXRS checks for static fromString(String s) method, so types with no valueOf(String) factory methods can also be dealt with:

...

Code Block
java
java
@Path("/")
public class Test1 {

 @Path("/bar")
 @POST 
 @Consumes({"application/json", "application/xml"})
 @Produces({"application/json", "application/xml"})
 public Order addOrder(OrderDetails details) {...}

}

Custom selection between multiple resources or operations

The JAX-RS selection algorithm has been designed with a lot of attention being paid to various possible cases, as far as the selection between multiple matching resource classes or methods is concerned.

...

Code Block
java
java
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.MultivaluedMap;

import org.apache.cxf.jaxrs.ext.ResourceComparator;
import org.apache.cxf.jaxrs.extmodel.ResourceComparatorClassResourceInfo;
import org.apache.cxf.jaxrs.model.ClassResourceInfoOperationResourceInfo;
import org.apache.cxf.jaxrs.model.OperationResourceInfoOperationResourceInfoComparatorBase;
import org.apache.cxf.jaxrs.model.OperationResourceInfoComparatorParameter;
import org.apache.cxf.jaxrs.modelutils.ParameterHttpUtils;
import org.apache.cxf.jaxrs.util.JAXRSUtils;
import org.apache.cxf.message.Message;

public class QueryResourceInfoComperatorQueryResourceInfoComparator extends OperationResourceInfoComparatorOperationResourceInfoComparatorBase implements
         ResourceComparator {

     public QueryResourceInfoComperatorQueryResourceInfoComparator() {
         super(null, null);
     }

     @Override
     public int compare(ClassResourceInfo cri1, ClassResourceInfo cri2, Message message) {
         // Leave Class selection to CXF
         return 0;
     }

     @Override
     public int compare(OperationResourceInfo oper1, OperationResourceInfo oper2, Message message) {
         // HTTP method
         final String httpMethod = HttpUtils.getProtocolHeader(message, Message.HTTP_REQUEST_METHOD, HttpMethod.POST, true);
        
         // Check if CXF can make a decision
         final int cxfResult = super.compare(oper1, oper2, httpMethod);
         if (cxfResult != 0) {
             return cxfResult;
         }

         int op1Counter = getMatchingRate(oper1, message);
         int op2Counter = getMatchingRate(oper2, message);

         return op1Counter == op2Counter
                 ? 0
                 : op1Counter<  op2Counter
                         ? 1
                         : -1;
     }

     /**
      * This method calculates a number indicating a good or bad match between
      * values provided within the request and expected method parameters. A
      * higher number means a better match.
      *
      * @param operation
      *            The operation to be rated, based on contained parameterInfo
      *            values.
      * @param message
      *            A message containing query from user request
      * @return A positive or negative number, indicating a good match between
      *         query and method
      */
     protected int getMatchingRate(OperationResourceInfo operation, Message message) {

         List<Parameter>  params = operation.getParameters();
         if (params == null || params.size() == 0)
             return 0;

         // Get Request QueryParams
         Set<String>  qParams = getParams((String) message.get(Message.QUERY_STRING));

         int rate = 0;
         for (Parameter p : params) {
             switch (p.getType()) {
             case QUERY:
                 if (qParams.contains(p.getName()))
                     rate += 2;
                 else if (p.getDefaultValue() == null)
                     rate -= 1;
                 break;
             // optionally support other parameter types such as headers, etc
             // case HEADER:
             //  break;
             default:
                 break;
             }
         }
         return rate;
     }

     /**
      * @param query
      *            URL Query Example: 'key=value&key2=value2'
      * @return A Set of all keys, contained within query.
      */
     protected Set<String>  getParams(String query) {
         Set<String>  params = new HashSet<String>();
         if (query == null || query.length() == 0)
             return params;

         MultivaluedMap<String, String> allQueries =
             JAXRSUtils.getStructuredParams(query, "&", false, false);
         return allQueries.keySet();
     }
} 

...

The core part of the solution is to inject the UriInfo object into method "getCustomers". This helper object allows for extracting useful information about the current URI context, but more importantly allows for getting the UriBuilder object. UriBuilder has multiple appender methods for building the URI for each object; in our case to the stem URI we can append path in multiple ways, providing it as a string (which we actually want to avoid here) or a resource (class or method) to extract the @Path value. Finally UriBuilder must have values bound to its template variables to render the actual URI. This case in action looks like this:

...