RESTful Web Services with Jersey

60
Scott Leberknight RESTful Web Services with Jersey

description

Slides from a mini-talk I recently gave on the Jersey framework for creating/consuming RESTful web services in Java, without hassle.

Transcript of RESTful Web Services with Jersey

Page 1: RESTful Web Services with Jersey

Scott Leberknight

RESTful Web Services with

Jersey

Page 2: RESTful Web Services with Jersey

"Jersey RESTful Web Services framework is [an] open source, production quality framework for developing RESTful Web Services in Java..."

Page 3: RESTful Web Services with Jersey

Jersey...

Page 4: RESTful Web Services with Jersey

...produces & consumes RESTful web services

(in Java, mostly pain-free)

Page 5: RESTful Web Services with Jersey

...is the JAX-RS reference implementation

(and extends JAX-RS with additional features)

Page 6: RESTful Web Services with Jersey

JAX-RS?

Java API for RESTful Services

Page 7: RESTful Web Services with Jersey

It's about the Resources,

stupid...

Page 8: RESTful Web Services with Jersey

"A JAX-RS resource is an annotated POJO that provides so-called resource methods that are able to handle HTTP requests for URI paths that the resource is bound to."

Page 9: RESTful Web Services with Jersey

@Path("/simple")public class SimpleResource {!

@GET @Produces("text/plain") public String get() { return "it's quite simple, you see?"; }}

resource class

Page 10: RESTful Web Services with Jersey

Root Resources

POJO (plain-old Java object)

Annotated with @Path and/or method designator (e.g. @GET)

Page 11: RESTful Web Services with Jersey

@Path

Specifies the URI at which a resource is located

URI template capability(via @PathParam)

Page 12: RESTful Web Services with Jersey

URI path template

@Path("/users/{userid}")@GET@Produces("application/json")public User user(@PathParam("userid") String id) { return _userRepository.getUser(id);}

Page 13: RESTful Web Services with Jersey

Method designators

Represent the HTTP method that resource methods respond to

Page 14: RESTful Web Services with Jersey

@GET@Produces("text/plain")public String get() { return "this is it!";}

HTTP method designator

Page 15: RESTful Web Services with Jersey

@Produces

Specifies the MIME type of representations that a resource

produces

Page 16: RESTful Web Services with Jersey

Media Types

MediaType class contains constants for common MIME types...

Page 17: RESTful Web Services with Jersey

Media Types

MediaType.TEXT_PLAIN!

MediaType.APPLICATION_JSON!

MediaType.APPLICATION_XML!

MediaType.MULTIPART_FORM_DATA!

// and more...

Page 18: RESTful Web Services with Jersey

@Consumes

Specifies the MIME type of representations that a resource

can consume

Page 19: RESTful Web Services with Jersey

@Consumes

@Path("/users")@POST@Consumes(MediaType.APPLICATION_JSON)public Response create(User user) { Long id = _userRepository.create(user); URI uri = URIBuilder.fromURI("/users") .path(id).build(); return Response.created(uri).build();}

Page 20: RESTful Web Services with Jersey

Sub-Resources & Paths

methods annotated with @Path in root resource classes, or...

methods returning an (annotated) resource class

Page 21: RESTful Web Services with Jersey

@Path("/myapp")public class UserResource { // root resource @Path("users") @GET @Produces(MediaType.TEXT_HTML) public String getUsersAsHtml() { ... } ! @Path("users.xml") @GET @Produces(MediaType.APPLICATION_XML) public String getUsersAsXml() { ... }! @Path("users.json") @GET @Produces(MediaType.APPLICATION_JSON) public String getUsersAsXml() { ... }}

Sub-resource methods

Page 22: RESTful Web Services with Jersey

Sub-resource URIs

/myapp/users

/myapp/users.xml

/myapp/users.json

Page 23: RESTful Web Services with Jersey

Injection

Use annotations to specify data to be injected...

Query & form parameters

Headers, cookies, etc.

Security context

...and more

Page 24: RESTful Web Services with Jersey

@*Param

QueryParam

HeaderParam

MatrixParam

FormParam

CookieParam

BeanParam

Page 25: RESTful Web Services with Jersey

@QueryParam

@Path("query-params")@GETpublic String colors (@QueryParam("red") int red, @QueryParam("green") int green, @QueryParam("blue") int blue) { return String.format("RGB(%d,%d,%d)", red, green, blue);}

Page 26: RESTful Web Services with Jersey

@HeaderParam

@Path("header-params")@GETpublic String headers(@HeaderParam("Accept") String accept, @HeaderParam("X-Foo") String foo) { return String.format("Accept: %s, X-Foo: %s", accept, foo);}

Page 27: RESTful Web Services with Jersey

@MatrixParam

@Path("matrix-params")@GETpublic String matrixParams(@MatrixParam("red") int red, @MatrixParam("green") int green, @MatrixParam("blue") int blue) { return String.format("RGB(%d,%d,%d)", red, green, blue);}

Page 28: RESTful Web Services with Jersey

What's a "matrix param"?

http://www.w3.org/DesignIssues/MatrixURIs.html

Also, see Tim-Berners Lee on matrix param design issues circa 1996...

acme.com/rest/samples/color ;red=25;green=78;blue=192

Parameters separate by semi-colons, e.g.

Not widely used, supported (or known)

Page 29: RESTful Web Services with Jersey

What if a parameter isn't supplied???

Page 30: RESTful Web Services with Jersey

@DefaultValue

@Path("defaults")@GETpublic String defaults( @DefaultValue("Orange") @QueryParam("color") String color, @DefaultValue(MediaType.APPLICATION_JSON) @HeaderParam("Accept") String accept) {! return String.format("color: %s, Accept: %s", color, accept);}

Page 31: RESTful Web Services with Jersey

@FormParam

@Path("form-params")@POST@Consumes(MediaType.APPLICATION_FORM_URLENCODED)public Response formParams(@FormParam("first") String firstName, @FormParam("last") String lastName) {! String entity = String.format("%s %s", firstName, lastName); return Response.ok(entity).build();}

Page 32: RESTful Web Services with Jersey

@BeanParam

@Path("bean-params")@POSTpublic Response beanParams(@BeanParam User user) {! String entity = String.format("User: %s %s", user.getFirstName(), user.getLastName()); return Response.ok(entity).build();}

Page 33: RESTful Web Services with Jersey

@BeanParam class

public class User {! @QueryParam("first") @DefaultValue("John") private String _firstName;! @QueryParam("last") @DefaultValue("Doe") private String _lastName;! public String getFirstName() { return _firstName; }! public String getLastName() { return _lastName; }}

Page 34: RESTful Web Services with Jersey

@Context

Use to obtain information related to request/response

Page 35: RESTful Web Services with Jersey

UriInfo

@Path("context-uri-info/{thing}")@GETpublic String uriInfo(@Context UriInfo info) { URI baseUri = info.getBaseUri(); MultivaluedMap<String, String> queryParams = info.getQueryParameters(); MultivaluedMap<String, String> pathParams = info.getPathParameters();! return String.format("base URI: %s, query params: %s, path params: %s", baseUri, queryParams.entrySet(), pathParams.entrySet());}

Page 36: RESTful Web Services with Jersey

HttpHeaders

@Path("http-headers")@GETpublic String httpHeaders(@Context HttpHeaders headers) { List<MediaType> acceptableMediaTypes = headers.getAcceptableMediaTypes(); String xFoo = headers.getHeaderString("X-Foo");! return String.format("acceptableMediaTypes: %s, X-Foo: %s", acceptableMediaTypes, xFoo);}

Page 37: RESTful Web Services with Jersey

Raw form parameters

@Path("raw-form")@POST@Consumes(MediaType.APPLICATION_FORM_URLENCODED)public Response rawForm(MultivaluedMap<String, String> formParams) {! String entity = formParams.entrySet().toString(); return Response.ok(entity).build();}

(Note: don't actually need @Context in above)

Page 38: RESTful Web Services with Jersey

Resource Life Cycle

Page 39: RESTful Web Services with Jersey

Scopes

Per-Request (default)new instance created on each request

Per-lookupnew instance created on each lookup (perhaps within same request)

Singletononly one instance for entire app

Page 40: RESTful Web Services with Jersey

JAX-RS Application Model

Page 41: RESTful Web Services with Jersey

Defines components of a JAX-RS application, i.e. resources

Application class

Independent of deployment environment

JAX-RS apps provide concrete implementation class

Page 42: RESTful Web Services with Jersey

Simple Application

public class SampleApplication extends Application {! @Override public Set<Class<?>> getClasses() { Set<Class<?>> classes = new HashSet<>();! classes.add(SampleResource.class); classes.add(SimpleResource.class); classes.add(UserResource.class);! return classes; }}

Page 43: RESTful Web Services with Jersey

Jersey's implementation of Application

Jersey ResourceConfig

Extend or create programmatically

Provides additional features like resource classpath scanning

Page 44: RESTful Web Services with Jersey

Jersey ResourceConfig

public class SampleJerseyApp extends ResourceConfig {! public SampleJerseyApp() { // scan classpath for resources packages("com.acme.rest", "com.foo.services");! // register filters register(CsrfProtectionFilter.class); register(UriConnegFilter.class); register(HttpMethodOverrideFilter.class);! // other configuration, etc. }}

Page 45: RESTful Web Services with Jersey

Deployment Options

Page 46: RESTful Web Services with Jersey

JavaSE (e.g. Grizzly, Jetty, Simple, etc.)

Servlet container (e.g. Tomcat, Jetty)

JavaEE (e.g. JBoss, etc.)

OSGi

Page 47: RESTful Web Services with Jersey

Using Grizzly HTTP Server

(JavaSE deployment)

Page 48: RESTful Web Services with Jersey

public class Server { public static final String BASE_URI = "http://localhost:8080/rest/";! public static HttpServer startServer() { ResourceConfig config = new ResourceConfig() .packages("com.acme.rest") .register(CsrfProtectionFilter.class) .register(UriConnegFilter.class) .register(HttpMethodOverrideFilter.class);! // create a new Grizzly HTTP server rooted at BASE_URI return GrizzlyHttpServerFactory .createHttpServer(URI.create(BASE_URI), config); }! public static void main(String[] args) throws Exception { final HttpServer server = startServer(); System.out.printf("Jersey app started with WADL available at " + "%sapplication.wadl\nHit enter to stop it...\n", BASE_URI); System.in.read(); server.shutdownNow(); }}

Grizzly Server

Page 49: RESTful Web Services with Jersey

Client API

Page 50: RESTful Web Services with Jersey

Jersey provides a client API to consume RESTful services

Written in fluent-style (method chaining)

Supports URI templates, forms, etc.

Page 51: RESTful Web Services with Jersey

Client client = ClientBuilder.newClient();WebTarget target = client.target("http://localhost:8080/rest") .path("sample/query-params");String response = target.queryParam("red", 0) .queryParam("green", 113)

.queryParam("blue", 195) .request() .get(String.class);

Client API example

Page 52: RESTful Web Services with Jersey

Representations

Page 53: RESTful Web Services with Jersey

...supports common media types like JSON, XML, etc.

...implementations provide ways to convert to/from various media

representations

JAX-RS...

Page 54: RESTful Web Services with Jersey

...supplies support out-of-box for XML, JSON, etc.

...uses MOXy as the default provider for JSON and XML conversion

Jersey...

Page 55: RESTful Web Services with Jersey

@Path("/")public class UserResource {! @Path("/users.json") @GET @Produces(MediaType.APPLICATION_JSON) public Collection<User> users() { return _userRepository.getAllUsers(); }! @Path("/users/{userid}.json") @GET @Produces(MediaType.APPLICATION_JSON) public User user(@PathParam("userid") Integer id) { return _userRepository.getUser(id);

}! @Path("/users.json") @POST @Consumes(MediaType.APPLICATION_JSON) public Response create(User user) throws Exception { Long id = _userRepository.save(user); URI uri = UriBuilder.fromUri("users").path(id).build(); return Response.created(uri).build(); }! // more resource methods...}

Automatic JSON support

Page 56: RESTful Web Services with Jersey

Building Responses

@POST@Consumes("application/xml")public Response post(String content) {  URI createdUri = buildUriFor(content);  String createdContent = create(content);   return Response.created(createdUri) .entity(Entity.text(createdContent)).build();}

Page 57: RESTful Web Services with Jersey

& more to explore...

Page 58: RESTful Web Services with Jersey

Security

JerseyTest

Asynchronous API

Filters & Interceptors

Bean Validation

MVC templates

...and more (see Jersey user guide)

Page 59: RESTful Web Services with Jersey

References

https://jersey.java.netJersey web site

https://jersey.java.net/documentation/latest/index.htmlJersey user guide (latest)

https://grizzly.java.net/Project Grizzly web site

https://jersey.java.net/apidocs/latest/jersey/index.htmlJersey API docs

https://jax-rs-spec.java.netJAX-RS web site

Page 60: RESTful Web Services with Jersey

My Info

twitter: sleberknight

www.sleberknight.com/blog

scott dot leberknight at gmail dot com