JAX-RS.Next(): JAX-RS 2 and Beyond

44
JAX-RS.Next(): JAX-RS 2 and Beyond Reza Rahman Java EE/GlassFish Evangelist [email protected] @reza_rahman

description

JAX-RS 2.0 is a new standard Java API for RESTful Web services and a major leap forward in the features and use cases covered by the API. The purpose of this technical session is to elaborate on all the new features being introduced as part of this new major API revision. This session explores the new client API, concepts behind filters and interceptors API, and asynchronous processing support. Other new features it covers include data validation support and improved support for hypermedia and server-side content negotiation. The last part of the session also briefly outlines future plans and focus areas.

Transcript of JAX-RS.Next(): JAX-RS 2 and Beyond

Page 1: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public1

JAX-RS.Next(): JAX-RS 2 and BeyondReza RahmanJava EE/GlassFish [email protected]@reza_rahman

Page 2: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public2

JAX-RS Example

@Path("/atm/{cardId}")public class AtmService {

@GET @Path("/balance") @Produces("text/plain") public String balance( @PathParam("cardId") String card, @QueryParam("pin") String pin) { return Double.toString(getBalance(card, pin)); }

...

Page 3: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public3

JAX-RS Example

...

@POST @Path("/withdrawal") @Consumes("text/plain") @Produces("application/json") public Money withdraw( @PathParam("card") String card, @QueryParam("pin") String pin, String amount) { return getMoney(card, pin, amount); }}

Page 4: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public4

JAX-RS Annotations

Page 5: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public5

JAX-RS Annotations (Continued)

Page 6: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public6Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public

JAX-RS 2

Client API

Modularized Configuration

Asynchronous Processing

Filters/Interceptors

Hypermedia Support

Server-side Content Negotiation

Page 7: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public7

Client API

Page 8: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public8

Client API

// Get instance of ClientClient client = ClientBuilder.newClient();

// Get account balanceString bal = client.target("http://.../atm/{cardId}/balance") .resolveTemplate("cardId", "111122223333") .queryParam("pin", "9876") .request("text/plain").get(String.class);

Page 9: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public9

Client API

// Withdraw some moneyMoney money = client.target("http://.../atm/{cardId}/withdrawal") .resolveTemplate("cardId", "111122223333") .queryParam("pin", "9876") .request("application/json") .post(text("50.0"), Money.class);

Page 10: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public10

Modularized Configuration

Page 11: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public11

Modularized Configuration - Motivation

client .register(JsonMessageBodyReader.class) .register(JsonMessageBodyWriter.class) .register(JsonpInterceptor.class) .property(“jsonp.callback.name”, “callback”) .property(“jsonp.callback.queryParam”, “true”) ...

Client-side

Page 12: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public12

Modularized Configuration - Motivation

public class MyApp extends javax.ws.rs.core.Application { public Set<Class<?>> getClasses() { Set<Class<?>> classes = new HashSet<…>(); ... classes.add(JsonMessageBodyReader.class); classes.add(JsonMessageBodyWriter.class); classes.add(JsonpInterceptor.class); ... return classes; }}

Server-side

Page 13: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public13

Modularized Configuration - Solution

client .register(JsonMessageBodyReader.class) .register(JsonMessageBodyWriter.class) .register(JsonpInterceptor.class) .property(“jsonp.callback.name”, “callback”) .property(“jsonp.callback.queryParam”, “true”) ...

JsonFeature jf = new JsonFeature().enableCallbackQueryParam();client.register(jf);

Client-side

Page 14: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public14

Common Configuration - Solution

public Set<Class<?>> getClasses() { ... classes.add(JsonMessageBodyReader.class); classes.add(JsonMessageBodyWriter.class); classes.add(JsonpInterceptor.class); ...}

public Set<Class<?>> getClasses() { ... classes.add(JsonFeature.class); ...}

Server-side

Page 15: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public15

A Feature Example

public void JsonFeature implements Feature {

public boolean configure(FeatureContext context) { context.register(JsonMessageBodyReader.class) .register(JsonMessageBodyWriter.class) .register(JsonpInterceptor.class) .property(CALLBACK_NAME, calbackName) .property(USE_QUERY_PARAM, useQueryParam);

return true; }}

Page 16: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public16

Dynamic Feature

public interface DynamicFeature { void configure(ResourceInfo ri, FeatureContext context);}

public interface ResourceInfo { Method getResourceMethod(); Class<?> getResourceClass();}

Server-side only

Page 17: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public17

Asynchronous Processing

Page 18: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public18

Asynchronous Processing: Server-side

@Stateless@Path("/async/longRunning")public class MyResource {

@GET @Asynchronous public void longRunningOp(@Suspended AsyncResponse ar) {

ar.setTimeoutHandler(new MyTimoutHandler()); ar.setTimeout(15, SECONDS);

final String result = executeLongRunningOperation();

ar.resume(result); }}

Page 19: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public19

Asynchronous Processing: Server-side

public interface AsyncResponse { public void resume(Object/Throwable response);

public void cancel(); public void cancel(int/Date retryAfter);

public boolean isSuspended(); public boolean isCancelled(); public boolean isDone();

public void setTimeout(long time, TimeUnit unit); public void setTimeoutHandler(TimeoutHandler handler);

public Collection<Class<?>> register(Class<?> callback); public Map<Class<?>, Collection<Class<?>>> register( Class<?> callback, Class<?>... callbacks); public Collection<Class<?>> register(Object callback); public Map<Class<?>, Collection<Class<?>>> register( Object callback, Object... callbacks);}

Page 20: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public20

Asynchronous Processing: Client-side

WebTarget target = client.target("http://.../balance”)… // Start async call and register callbackFuture<?> handle = target.request().async().get( new InvocationCallback<String>() { void complete(String balance) { … } void failed(InvocationException e) { … } }); // After waiting for too long…if (!handle.isDone()) handle.cancel(true);

Page 21: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public21

Filters/Interceptors

Page 22: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public22

Filters & Interceptors

Non-wrapping filter chain – Filters do not invoke next filter in

the chain directly

– managed by the JAX-RS runtime

Each filter decides to proceed or break the chain

Filter each incoming/outgoing message

Request Request– ContainerRequestFilter, ClientRequestFilter

Response Response– ContainerResponseFilter, ClientResponseFilter

Server-side specialties– @PreMatching, DynamicFeature

Page 23: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public23

Filters & Interceptors

public class RequestLoggingFilter implements ContainerRequestFilter {

@Override public void filter(ContainerRequestContext requestContext) { log(requestContext); // non-wrapping => returns without invoking the next filter }

...}

A Logging Filter Example

Page 24: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public24

Filters & Interceptors

Invoked ONLY when/if entity processing occurs

– Performance boost

Wrapping interceptor chain– Each interceptor invokes the next

one in the chain via context.proceed()

Intercept entity providers

MessageBodyReader interceptor

– ReaderInterceptor interface

MessageBodyWriter interceptor

– WriterInterceptor interface

Page 25: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public25

Filters & Interceptors

public class GzipInterceptor implements ReaderInterceptor { @Override Object aroundReadFrom(ReaderInterceptorContext ctx) { InputStream old = ctx.getInputStream(); ctx.setInputStream(new GZIPInputStream(old)); // wrapping => invokes the next interceptor Object entity = ctx.proceed();

ctx.setInputStream(old); return entity; }}

A GZip Reader Interceptor Example

Page 26: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public26

Application

Filters & Interceptors

Request Filter Filter

NetworkTransport

…Response FilterFilter

write(…)

WriterInterceptor

…MBW

read(…) - optional

…MBR

WriterInterceptor

ReaderInterceptor

ReaderInterceptor

Page 27: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public27

Response

Application

Filters & Interceptors

Filter Filter

Network

…ResponseFilterFilter

write(…)

…MBW Writer

InterceptorWriter

Interceptor

Filter Filter…

RequestRequest

read(…) - optional

ReaderInterceptor

…MBR

ReaderInterceptor

Filter Filter

Resource Matching

@PreMatching

Page 28: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public28

Bindings & Priorities Binding

– Associating filters and interceptors with resource methods– Server-side concept

Priority– Declaring relative position in the execution chain– @Priority(int priority)

Shared concept by filters and interceptors

Scoped Binding Global Binding

Static @NameBindingDefault

@PreMatching

Dynamic DynamicFeature N/A

Page 29: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public29

Bindings

@NameBinding@Target({ElementType.TYPE, ElementType.METHOD})@Retention(value = RetentionPolicy.RUNTIME)public @interface Logged {}

@Provider@Logged@Priority(USER)public class LoggingFilter implements ContainerRequestFilter, ContainerResponseFilter

{ … }

Page 30: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public30

Bindings

@Path("/greet/{name}")@Produces("text/plain")public class MyResourceClass {

@Logged @GET public String hello(@PathParam("name") String name) { return "Hello " + name; }}

Page 31: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public31

A DynamicFeature Example

public void SecurityFeature implements DynamicFeature {

public boolean configure(ResourceInfo ri, FeatureContext context) { String[] roles = getRolesAllowed(ri);

if (roles != null) { context.register(new RolesAllowedFilter(roles)); } } ...}

Server-side only

Page 32: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public32

Hypermedia Support

Page 33: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public33

Hypermedia

Link: <http://.../orders/1/ship>; rel=ship, <http://.../orders/1/cancel>; rel=cancel ...<order id="1"> <customer>http://.../customers/11</customer> <address>http://.../customers/11/address/1</address> <items> <item> <product>http://.../products/111</product> <quantity>2</quantity> </item> <items> ... </order>

Page 34: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public34

Hypermedia

// Producer API (server-side)Link self = Link.fromMethod(MyResource.class, ”handleGet”) .build();

Link update = Link.fromMethod(MyResource.class, “handlePost”) .rel(”update”) .build();

...

Response res = Response.ok(order) .link("http://.../orders/1/ship", "ship") .links(self, update) .build();

Page 35: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public35

Hypermedia

Response order = client.target(…).request("application/xml").get();

// Consumer API (client-side)Link shipmentLink = order.getLink(“ship”);if (shipmentLink != null) { Response shipment = client.target(shipmentLink).post(null); … }

Page 36: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public36

Content Negotiation

Page 37: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public37

Server Side Content Negotiation

GET http://.../widgets2Accept: text/*; q=1...

Path("widgets2")public class WidgetsResource2 { @GET @Produces("text/plain", "text/html") public Widgets getWidget() {...}}

Page 38: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public38

Server Side Content Negotiation

GET http://.../widgets2Accept: text/*; q=1...

Path("widgets2")public class WidgetsResource2 { @GET @Produces("text/plain; qs=0.5", "text/html; qs=0.75") public Widgets getWidget() {...}}

Page 39: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public39

Try it Out!

http://dlc.sun.com.edgesuite.net/glassfish/4.0.1/promoted/

Page 40: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public40

JAX-RS 2 Implementations

TomEE

GlassFish

Page 41: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public41

JAX-RS.next

CDI alignment Server-Sent Events (SSE) More Hypermedia (Structural Links) Action-Oriented Web Framework? Higher level client API? Fixes and clarifications

Page 42: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public42

Summary

Major improvements– Client API– Modularized Configuration– Asynchronous Processing– Filters/Interceptors– Hypermedia Support– Server-side Content Negotiation

Many minor API improvements– Bean Validation, Request / Response, URI builder, String Converters, @BeanParam, MultivaluedHashMap, GenericType, etc

JAX-RS.next spinning up now!

Page 43: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public43

Learning More

Jersey User Guide– https://jersey.java.net/documentation/latest/user-guide.html

JAX-RS Transparent Expert Group– http://jax-rs-spec.java.net

Java EE 7 Reference Implementation– http://glassfish.org

JAX-RS Reference Implementation– https://jersey.java.net

The Aquarium– http://blogs.oracle.com/theaquarium

Page 44: JAX-RS.Next(): JAX-RS 2 and Beyond

Copyright © 2012, Oracle and/or its affiliates. All rights reserved. Public44