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