Here is a comprehensive JAX-RS Cheatsheet to help you code your REST Services.
JAX RS-Annotations
@Path: Path to annotate a method or a Class with the resource path it represents. For instance:
@Path("/hello")
public class CustomerEndpoint {
}
@Produces: To specify the output type that the resource produces, or in a narrower scope the type of output that a method in a resource. For example:
@Produces(MediaType.TEXT_PLAIN) @Produces(MediaType.APPLICATION_XML) @Produces(MediaType.APPLICATION_JSON)
@Consumes: To specify the type of input that the resource consumes, or in a narrower scope the type of input that a method in a resource consumes. For instance:
@Consumes(MediaType.TEXT_PLAIN) @Consumes(MediaType.APPLICATION_XML) @Consumes(MediaType.APPLICATION_JSON)
@ApplicationPath: Identifies the application path that serves as the base URI for all resource URIs provided by path. For example:
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("/rest")
public class RestActivator extends Application {
}
@Context: lets you inject contextual objects such as UriInfo, which provides contextual request-specific information about the request URI. For instance:
@Path("/")
public class DemoResource {
private final @Context HttpHeaders httpHeaders;
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getHeaders(){
// Code here that uses httpHeaders
}
}
HTTP Operations: JAX-RS defines five annotations that map to specific HTTP operations:
- @javax.ws.rs.GET: To map an HTTP GET Request
- @javax.ws.rs.PUT: To map an HTTP PUT Request
- @javax.ws.rs.POST: To map an HTTP POST Request
- @javax.ws.rs.DELETE: To map an HTTP DELETE Request
- @javax.ws.rs.HEAD: To map an HTTP HEAD Request
JAX RS Parameters
@QueryParam allows to inject Query Parameters in your Endpoint. For example:
public Response getParams(
@QueryParam("param1") @DefaultValue("") String myStr,
@QueryParam("param2") @DefaultValue("-1") int myInt) {
String s = "param1=" + myStr + ", param2=" + myInt;
return Response.ok(s).build();
}
$ curl 'http://localhost:8080/queryParam?param=Hi¶m2=123'
@MatrixParam applies to a particular path element while query parameters apply to the request as a whole. For example:
@GET
@Path("matrixParam")
public Response getMatrixParam(
@MatrixParam("height") int height,
@MatrixParam("width") int width) {
return Response.ok("height=" + height + ", width=" + width).build();
}
$ curl http://localhost:8080/matrixParam;height=1;width=2
@PathParam
@GET
@Path("pathParam/{p}")
public Response getParams(@PathParam("p") String v) {
return Response.ok(v).build();
}
$ curl http://localhost:8080/pathParam/foo
@HeaderParam
@GET
@Path("headerParam")
public Response getHeaderParam(@HeaderParam("p") String v) {
return Response.ok(v).build();
}
$ curl -v -H 'p: foo' http://localhost:8080/headerParam
@CookieParam
@GET
@Path("cookieParam")
public Response getCookieParam(@CookieParam("p") String v) {
return Response.ok(v).build();
}
$ curl -v -H 'Cookie: p=foo' http://localhost:8080/cookieParam
@FormParam
@POST
@Path("formParam")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response postFormParam(@FormParam("p") String v) {
return Response.ok(v).build();
}
$ curl -v -d 'p=foo' http://localhost:8080/formParam
@BeanParam
@POST
@Path("beanParam")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response postBeanParam(@BeanParam Image image) {
String s = "height=" + image.getHeight();
s += ", width=" + image.getWidth();
return Response.ok(s).build();
}
import javax.ws.rs.FormParam;
public class Image {
@FormParam("height")
private int height;
@FormParam("width")
private int width;
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
}
$ curl -d 'height=1' -d 'width=2' http://localhost:8080/beanParam
How to produce a Response
Response with status OK. For example:
String message = "This is a text response"; return Response .status(Response.Status.OK) .entity(message) .build();
Response in custom format. For example:
String json = //convert entity to json return Response.ok(json, MediaType.APPLICATION_JSON).build();
Throwing Exception
@GET
@Path("{id}")
@Produces("application/xml")
public Customer getCustomer(@PathParam("id") int id) {
Customer cust = findCustomer(id);
if (cust == null) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
return cust;
}
JAX WS Client API
Client client = ClientBuilder.newClient();
SimpleProperty p1 = new SimpleProperty("mykey","value");
WebTarget myResource = client.target(BASE_URL+"/param/add");
Response rs = myResource.request(MediaType.APPLICATION_XML)
.post(Entity.xml(p1), Response.class);
assertEquals(rs.getStatus(),200);
String out = rs.readEntity(String.class);
assertEquals(out,"Success");
Async API
Sample Async method:
@GET
@Path("/xmlasync/{id}")
@Produces(MediaType.APPLICATION_XML)
public void asyncGet(final @Suspended AsyncResponse asyncResp,
final @PathParam("id") int id) {
asyncResp.setTimeout(10, TimeUnit.SECONDS);
asyncResp.setTimeoutHandler(new MyTimeoutHandler());
new Thread(new Runnable() {
public void run() {
SimpleProperty p = ejb.getList().get(id);
asyncResp.resume(p);
}
}).start();
}
public class MyTimeoutHandler implements TimeoutHandler {
public void handleTimeout(AsyncResponse asyncResp) {
Response r = Response.serverError().status( HttpURLConnection.
HTTP_UNAVAILABLE).build( );
asyncResp.resume( r );
}
}
Filters: Used to modify Request or Response Headers
Server side filters: Decorate Request:
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerRequestContext;
@Provider
@PreMatching
public class HttpMethodOverride implements ContainerRequestFilter {
public void filter(ContainerRequestContext ctx) throws IOException {
String methodOverride = ctx.getHeaderString("X-Http-Method-Override");
if (methodOverride != null) ctx.setMethod(methodOverride);
}
}
Server side filters: Decorate Response:
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerRequestContext;
@Provider
@PreMatching
public class HttpMethodOverride implements ContainerRequestFilter {
public void filter(ContainerRequestContext ctx) throws IOException {
String methodOverride = ctx.getHeaderString("X-Http-Method-Override");
if (methodOverride != null) ctx.setMethod(methodOverride);
}
}
Client side filters: Decorate Request:
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.client.ClientRequestContext;
public class ClientCacheRequestFilter implements ClientRequestFilter {
private Cache cache;
public ClientCacheRequestFilter(Cache cache) {
this.cache = cache;
}
public void filter(ClientRequestContext ctx) throws IOException {
if (!ctx.getMethod().equalsIgnoreCase("GET")) return;
CacheEntry entry = cache.getEntry(request.getUri());
if (entry == null) return;
if (!entry.isExpired()) {
ByteArrayInputStream is = new ByteArrayInputStream(entry.getContent());
Response response = Response.ok(is)
.type(entry.getContentType()).build();
ctx.abortWith(response);
return;
}
String etag = entry.getETagHeader();
String lastModified = entry.getLastModified();
if (etag != null) {
ctx.getHeaders.putSingle("If-None-Match", etag);
}
if (lastModified != null) {
ctx.getHeaders.putSingle("If-Modified-Since", lastModified);
}
}
}
Client side filters: Decorate Response:
public class CacheResponseFilter implements ClientResponseFilter {
private Cache cache;
public CacheResponseFilter(Cache cache) {
this.cache = cache;
}
public void filter(ClientRequestContext request,
ClientResponseContext response)
throws IOException {
if (!request.getMethod().equalsIgnoreCase("GET")) return;
if (response.getStatus() == 200) {
cache.cacheResponse(response, request.getUri());
} else if (response.getStatus() == 304) {
CacheEntry entry = cache.getEntry(request.getUri());
entry.updateCacheHeaders(response);
response.getHeaders().clear();
response.setStatus(200);
response.getHeaders().putSingle("Content-Type", entry.getContentType());
ByteArrayInputStream is = new ByteArrayInputStream(entry.getContent());
response.setInputStream(is);
}
}
}
Interceptors: Reader and Writer Interceptors are used to control the Message Body
Writer Interceptor:
@Provider
public class GZIPEncoder implements WriterInterceptor {
public void aroundWriteTo(WriterInterceptorContext ctx)
throws IOException, WebApplicationException {
GZIPOutputStream os = new GZIPOutputStream(ctx.getOutputStream());
ctx.getHeaders().putSingle("Content-Encoding", "gzip");
ctx.setOutputStream(os);
ctx.proceed();
return;
}
}
Reader Interceptor:
@Provider
public class GZIPDecoder implements ReaderInterceptor {
public Object aroundReadFrom(ReaderInterceptorContext ctx)
throws IOException {
String encoding = ctx.getHeaders().getFirst("Content-Encoding");
if (!"gzip".equalsIgnoreCase(encoding)) {
return ctx.proceed();
}
GZipInputStream is = new GZipInputStream(ctx.getInputStream());
ctx.setInputStream(is);
return ctx.proceed(is);
}
}
JAX-RS Dependency for WildFly
<dependency>
<groupId>org.jboss.spec.javax.ws.rs</groupId>
<artifactId>jboss-jaxrs-api_2.1_spec</artifactId>
<scope>provided</scope>
</dependency>
JAX-RS Cheatsheet by mastertheboss.com – All rights reserved