Versions Compared

Key

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



 

...

Span
stylefont-size:2em;font-weight:bold
JAX-RS: Understanding the Basics

...



Table of Contents

What is New in JAX-RS 2.1

...

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

...

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.

...

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 one .

Dealing with Parameters

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.
PathParam annotation is used to map a given Path template variable to a method parameter.
For example :

Code Block
java
java
@Path("/customer/{id}")
public class CustomerService {

    
    @PUT
    @Path("{name}")
    public Response updateCustomer(@PathParam("id") Long id, @PathParam("name") String name) {
        ...
    }
}

...

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.model.ClassResourceInfo;
import org.apache.cxf.jaxrs.model.OperationResourceInfo;
import org.apache.cxf.jaxrs.model.OperationResourceInfoComparatorOperationResourceInfoComparatorBase;
import org.apache.cxf.jaxrs.model.Parameter;
import org.apache.cxf.jaxrs.utils.HttpUtils;
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();
     }
} 

...