JAX-RS 2.0 behavior changes
As a part of Java EE 7, Liberty supports JAX-RS 2.0. Before beginning to use JAX-RS in Liberty, you might need to know the following differences between JAX-RS 1.1 and JAX-RS 2.0.
The following items are the differences between JAX-RS 1.1 and JAX-RS 2.0 in Liberty:
- In JAX-RS 1.1 and Jersey, if an EJB or CDI class creates a new instance that is returned by the
JAX-RS application.getSingletons() method, the engine uses the returned instance and does not try to
access the instance from the EJB or CDI container. In JAX-RS 2.0, for the same scenario, the engine
tries to access the instance from the EJB or CDI container. If the instance can be accessed, the
retrieved instance is used. But if the instance cannot be accessed, the returned instance from the
getSingletons() method is used. For
example:
@Override public Set<Object> getSingletons() { Set<Object> objs = new HashSet<Object>(); objs.add(new CDIInjectResource()); objs.add(new EJBInjectResource()); return objs; }
- JAX-RS 2.0 includes many API changes when it handles the MultiPart file. For example, in JAX-RS
1.1, the
@FormParam
annotation can be used to handle the MultiPart file, but in JAX-RS 2.0, onlyIMultipartBody
orIAttachment
objects can be used to handle the MultiPart file. For more information, see Configuring a resource to receive multipart/form-data parts from an HTML form submission in JAX-RS 2.0.
The following items apply to JAX-RS 2.0 in Liberty:
- The Jackson packages as a third-party API in JAX-RS 1.1 are no longer exposed in JAX-RS 2.0. If
you want to use any
org.codehaus.jackson
API in your application, you need to compress Jackson packages in your application. To handle Jackson annotations in Java object with JAX-RS 2.0, you must overridegetSingletons()
in your application class to return Jackson's JSON provider.@Override public Set<Object> getSingletons() { Set<Object> singletons = new HashSet<Object>(); singletons.add(new JacksonJaxbJsonProvider()); return singletons; }
- If you specify
javax.ws.rs.core.Application
as the servlet-name in the web.xml file, thegetClasses
method in the Application object, which is injected by@Context
, might not return the resource classes.<servlet> <servlet-name>javax.ws.rs.core.Application</servlet-name> </servlet> <servlet-mapping> <servlet-name>javax.ws.rs.core.Application*</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
- The JAX-RS 2.0 specification states that a provider is a class that implements one or more
JAX-RS interfaces and that can be annotated with
@Provider
for automatic discovery. In the scenario, a class has@Local
annotation that refers to a provider interface, but it does not implement any POJO provider interface, and then it is an invalid provider. For example:@Stateless @Local(OneLocalInterfaceMyOtherStuffMessageBodyWriter.class) public class OneLocalInterfaceMyOtherStuffProvide
- If you use the MessageBodyReader and MessageBodyWriter
@Consumes
and@Produces
annotations, some supported media types might be restricted. Use theisReadable
method orisWriteable
method to check the media type. For example:@Provider @Consumes("<custom/type>") @Produces("<custom/type>") @Singleton public class MyMessageBodyReaderAndWriter implements MessageBodyReader,MessageBodyWriter { public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { if (mediaType.toString().equals("<custom/type>")) return true; return false; } public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { if (mediaType.toString().equals("<custom/type>")) return true; return false; } ... }
- You can use the asynchronous processing technique in JAX-RS 2.0 to process threads. For more information, see Asynchronous processing.
- None of the Wink APIs that are displayed as third-party APIs in JAX-RS 1.1 are supported in
JAX-RS 2.0. Here is a partial list:
org.apache.wink.common.model.atom.AtomEntry
. For more information about integrating JAX-RS 2.0 with Atom, see JAX-RS 2.0 integration with Atom.org.apache.wink.client.handlers.BasicAuthSecurityHandler
. If you want to use basic authentication in JAX-RS 2.0, see the following code snippets:- Use ClientRequestFilter through the JAX-RS 2.0 standard Client API as shown in the code example:
import java.io.IOException; import java.io.UnsupportedEncodingException; import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientRequestFilter; import javax.ws.rs.core.MultivaluedMap; import javax.xml.bind.DatatypeConverter; public class BasicAuthFilter implements ClientRequestFilter { private final String usr; private final String pwd; public BasicAuthFilter(String usr, String pwd) { this.usr = user; this.pwd = pwd; } public void filter(ClientRequestContext requestContext) throws IOException { MultivaluedMap<String, Object> headers = requestContext.getHeaders(); String token = this.usr + ":" + this.pwd; final String basicAuthentication ="Basic " + DatatypeConverter.printBase64Binary(token.getBytes("UTF-8")); headers.add("Authorization", basicAuthentication); } }
- Register to the ClientBuilder:
ClientBuilder cb = ClientBuilder.newBuilder(); cb.register(new BasicAuthFilter("user","password"));
- Use ClientRequestFilter through the JAX-RS 2.0 standard Client API as shown in the code example:
org.apache.wink.client.handlers.LtpaAuthSecurityHandler
. If you want to use the LTPA-based security client to secure downstream resources, see Configuring a resource to receive multipart/form-data parts from an HTML form submission in JAX-RS 2.0.org.apache.wink.server.internal.providers.exception.EJBAccessExceptionMapper
. This API is no longer supported because it is the Wink-specified ExceptionMapper. You can define your own ExceptionMapper to map the EJBAccessException.com.ibm.websphere.jaxrs.server.IBMRestFilter
. This API is no longer supported because it is based on Wink Filter.
Note: Detect if there are wink jar packages in your application. If there are any wink packages in your application, you must do the following steps:- Make sure that there is Application subclass defined.
- At least one of
getClasses
andgetSingletons
must not return null.
- If you want to see the supported client property that can be used in JAX-RS 2.0 client, see Configuring JAX-RS 2.0 client.
- If you want to use the Secure Sockets Layer (SSL) function in JAX-RS 2.0, you need to
enable the transportSecurity-1.0 or appSecurity-2.0 feature. For the LTPA token function, the
appSecurity-2.0 feature is must.Note: The transportSecurity-1.0 feature is a subfeature of the appSecurity-2.0 feature. If you enable the jaxrsClient-2.0 feature and the transportSecurity-1.0 feature, the appSecurity-2.0 feature is enabled automatically.
- If you want to use the Wink Client in the JAX-RS 2.0 server run time, do the following steps:
- Download the following files that can enable Wink Client in the JAX-RS 2.0 server run time.
- Download the Apache Wink and related JAR files from http://wink.apache.org/downloads.html.
- Download the Apache HTTP and related JAR files from http://hc.apache.org/.
Note: If the JAX-RS 2.0 feature is not enabled, you must also download and add the JAX-RS API to the third-party lib. Download the JAX-RS API from https://jax-rs-spec.java.net/nonav/. - Save all JAR files into the <third-party lib> directory.
- Add the location of <third-party lib> to the
server.xml file:
<library id="thirdPartyLib"> <fileset dir=" <third-party lib>" includes="*.jar" scanInterval="5s"/> </library> <enterpriseApplication id="<Your Ear ID>" location="<Your Ear Name>" name="<Your Ear Name>"> <classloader commonLibraryRef="thirdPartyLib"/> </enterpriseApplication>
- Download the following files that can enable Wink Client in the JAX-RS 2.0 server run time.
- In JAX-RS 1.1 multiple URL patterns can be specified for each JAX-RS servlet, as shown in the
following example:
<servlet id="Servlet_1"> <servlet-name>HelloWorldServlet</servlet-name> <servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>com.test.HelloWorldApplication</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping id="ServletMapping_1"> <servlet-name>HelloWorldServlet</servlet-name> <url-pattern>/rest/*</url-pattern> <url-pattern>/rest2/*</url-pattern> </servlet-mapping>
However, in JAX-RS 2.0, each servlet definition can define only a single URL pattern. Multiple URL pattern definitions require multiple servlet definitions, as shown in the following example:<servlet id="Servlet_1"> <servlet-name>HelloWorldServlet</servlet-name> <servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>com.test.HelloWorldApplication</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet id="Servlet_2"> <servlet-name>HelloWorldServlet2</servlet-name> <servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>com.test.HelloWorldApplication</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping id="ServletMapping_1"> <servlet-name>HelloWorldServlet</servlet-name> <url-pattern>/rest/*</url-pattern> </servlet-mapping> <servlet-mapping id="ServletMapping_2"> <servlet-name>HelloWorldServlet2</servlet-name> <url-pattern>/rest2/*</url-pattern> </servlet-mapping>
Note: For more information about asynchronous processing in Client and Server APIs, see Chapter
8 of JSR 339:
JAX-RS 2.0: The Java API for RESTful Web Services (the
"Specification").