JAX-RS 2.0: RESTful Java on Steroids
Arun Gupta, Java EE & GlassFish Guy
http://blogs.oracle.com/arungupta, @arungupta
1
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
The following is intended to outline our general product direction. It is
intended for information purposes only, and may not be incorporated into
any contract. It is not a commitment to deliver any material, code, or
functionality, and should not be relied upon in making purchasing
decisions. The development, release, and timing of any features or
functionality described for Oracle’s products remains at the sole
discretion of Oracle.
2
Copyright © 2011,
2012, Oracle and/or its affiliates. All rights
reserved.
Part I: How we got here ?
3
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
How We Got Here?
• Shortest intro to JAX-RS 1.0
• Requested features for JAX-RS 2.0
• JSR 339: JAX-RS 2.0
4
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
JAX-RS Origins
• JAX-RS 1.0 is Java API for RESTful WS
• RESTFul Principles:
– Assign everything an ID
– Link things together
– Use common set of methods
– Allow multiple representations
– Stateless communications
5
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
JAX-RS 1.0 Goals
• POJO-Based API
• HTTP Centric
• Format Independence
• Container Independence
• Inclusion in Java EE
6
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Example: JAX-RS API
Resources
@Path("/atm/{cardId}")
public class AtmService {
URI Parameter
Injection
@GET @Path("/balance")
@Produces("text/plain")
public String balance(@PathParam("cardId") String card,
@QueryParam("pin") String pin) {
return Double.toString(getBalance(card, pin));
}
…
HTTP Method
Binding
7
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Built-in
Serialization
Example: JAX-RS API (contd.)
…
Custom Serialization
@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);
}
}
8
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Example: JAX-RS API (contd.)
9
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Example: JAX-RS API (contd.)
10
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Requested Features
• Client API
• Client-side and Server-side Asynchronous
• Filters and Interceptors
• Improved Connection Negotiation
• Validation
• Hypermedia
• Alignment with JSR 330
• Model-View-Controller
11
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
JSR 339 Expert Group
• EG Formed in March 2011
• Oracle Leads: Marek Potociar / Santiago Pericas-G.
• Expert Group:
– Jan Algermissen, Florent Benoit, Sergey Beryozkin (Talend),
Adam Bien, Bill Burke (RedHat), Clinton Combs, Bill De Hora,
Markus Karg, Sastry Malladi (Ebay), Julian Reschke, Guilherme
Silveira, Dionysios Synodinos
• Early Draft 3 published on Jun 7, 2012!
12
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Part II: Where We Are Going
13
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
In-Scope Features
• Client API
• Filters and Interceptors
• Client-side and Server-side Asynchronous
• Improved Connection Negotiation
• Validation
• Hypermedia
• Alignment with JSR 330
• Model-View-Controller
14
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
New in JAX-RS 2.0
• Client API
• Filters and Interceptors
• Client-side and Server-side Asynchronous
• Improved Connection Negotiation
• Validation
• Hypermedia
• Alignment with JSR 330
15
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Client API - Motivation
• HTTP client libraries too low level
• Sharing features with JAX-RS server API
• E.g., MBRs and MBWs
• Supported by some JAX-RS 1.0 implementations
• Need for a standard
16
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Client API – Old and New
• Client-side API
URL url = new URL("http://.../atm/balance");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.setDoOutput(false);
Old
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
out.println(line);
}
Client client = ClientFactory.newClient();
String balance = client.target("http://.../atm/balance")
.request()
.get(String.class);
17
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
New
Example: Client API
// Get instance of Client
Client client = ClientFactory.newClient();
Can also inject @URI for the target
// Get account balance
String bal = client.target("http://.../atm/balance")
.pathParam("card", "111122223333")
.queryParam("pin", "9876")
.request().get(String.class);
18
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Example: Client API (contd.)
// Withdraw some money
Money mon = client.target("http://.../atm/withdraw")
.pathParam("card", "111122223333")
.queryParam("pin", "9876")
.request("application/json")
.post(text("50.0"), Money.class);
19
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Example: Generic Interface (Command pattern,
Batch processing)
Invocation inv1 =
client.target("http://.../atm/balance")…
.request().buildGet();
Invocation inv2 =
client.target("http://.../atm/withdraw")…
.request()
.buildPost(text("50.0"));
20
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Example: Generic Interface (contd.)
Collection<Invocation> invs =
Arrays.asList(inv1, inv2);
Collection<Response> ress =
Collections.transform(invs,
new F<Invocation, Response>() {
public Response apply(Invocation inv) {
return inv.invoke();
}
});
21
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
New in JAX-RS 2.0
• Client API
• Filters and Interceptors
• Client-side and Server-side Asynchronous
• Improved Connection Negotiation
• Validation
• Hypermedia
• Alignment with JSR 330
22
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Filters & Interceptors – Motivation
• Customize JAX-RS implementations via well-defined
extension points
• Use Cases: Logging, Compression, Security, Etc.
• Shared by client and server APIs
• Supported by most JAX-RS 1.0 implementations
• All using slightly different types or semantics
23
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Filters
• Non-wrapping extension points
• Pre: Interface RequestFilter
• Post: Interface ResponseFilter
• Part of a filter chain
• Do not call the next filter directly
• Each filter decides to proceed or break chain
• By returning FilterAction.NEXT or FilterAction.STOP
24
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Filter Example: LoggingFilter
@Provider
class LoggingFilter
implements RequestFilter, ResponseFilter {
@Override
public FilterAction preFilter(FilterContext ctx)
throws IOException {
logRequest(ctx.getRequest());
return FilterAction.NEXT;
}
…
25
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Filter Example: LoggingFilter (contd.)
@Override
public FilterAction postFilter(FilterContext ctx)
throws IOException {
logResponse(ctx.getResponse());
return FilterAction.NEXT;
}
}
26
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Interceptors
• Wrapping extension points
• ReadFrom: Interface ReaderInterceptor
• WriteTo: Interface WriterInterceptor
• Part of an interceptor chain
• Call the next handler directly
• Each handler decides to proceed or break chain
• By calling ctx.proceed()
27
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Handler Example: GzipInterceptor
@Provider
class GzipInterceptor implements ReaderInterceptor,
WriterInterceptor {
@Override
public Object aroundReadFrom(ReadInterceptorContext ctx)
throws IOException {
if (gzipEncoded(ctx)) {
InputStream old = ctx.getInputStream();
ctx.setInputStream(new GZIPInputStream(old));
}
return ctx.proceed();
}
… }
28
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Order of Execution
Request
Filter
WriteTo
Handler
Request
Filter
ReadFrom
Handler
ReadFrom
Handler
Response
Filter
WriteTo
Handler
Response
Filter
Client
29
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Server
Binding Example: LoggingFilter
@NameBinding
// or @Qualifier ?
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Logged {
}
@Provider
@Logged
public class LoggingFilter implements RequestFilter,
ResponseFilter
{ … }
30
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Binding Example: LoggingFilter
@Path("/")
public class MyResourceClass {
@Logged
@GET
@Produces("text/plain")
@Path("{name}")
public String hello(@PathParam("name") String name) {
return "Hello " + name;
}
}
31
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
New in JAX-RS 2.0
• Client API
• Filters and Interceptors
• Client-side and Server-side Asynchronous
• Improved Connection Negotiation
• Validation
• Hypermedia
• Alignment with JSR 330
32
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Asynchronous – Motivation
• Let “borrowed” threads run free!
• Container environment
• Suspend and resume connections
• Suspend while waiting for an event
• Resume when event arrives
• Leverage Servlet 3.X async support (if available)
• Client API support
• Future<RESPONSE>, InvocationCallback<RESPONSE>
33
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Example: Suspend and Resume
@Path("/async/longRunning")
public class MyResource {
@Context private ExecutionContext ctx;
@GET @Produces("text/plain")
public void longRunningOp() {
Executors.newSingleThreadExecutor().submit(
new Runnable() {
public void run() {
Thread.sleep(10000);
// Sleep 10 secs
ctx.resume("Hello async world!");
} });
ctx.suspend();
// Suspend connection and return
} … }
34
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Example: @Suspend Annotation
@Path("/async/longRunning")
public class MyResource {
@Context private ExecutionContext ctx;
@GET @Produces("text/plain") @Suspend
public void longRunning() {
Executors.newSingleThreadExecutor().submit(
new Runnable() {
public void run() {
Thread.sleep(10000);
// Sleep 10 secs
ctx.resume("Hello async world!");
} });
// ctx.suspend(); Suspend connection and return
} … }
35
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Example: Client API Async Support
// Build target URI
Target target = client.target("http://.../atm/balance")…
// Start async call and register callback
Future<?> handle = target.request().async().get(
new InvocationCallback<String>() {
public void complete(String balance) { … }
public void failed(InvocationException e) { … }
});
// After waiting for a while …
If (!handle.isDone()) handle.cancel(true);
36
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
New in JAX-RS 2.0
• Client API
• Filters and Interceptors
• Client-side and Server-side Asynchronous
• Improved Connection Negotiation
• Validation
• Hypermedia
• Alignment with JSR 330
37
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Improved Connection Negotiation
GET http://.../widgets2
Accept: text/*; q=1
…
Path("widgets2")
public class WidgetsResource2 {
@GET
@Produces("text/plain",
"text/html")
public Widgets getWidget() {...}
}
38
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Improved Conneg (contd.)
GET http://.../widgets2
Accept: text/*; q=1
…
Path("widgets2")
public class WidgetsResource2 {
@GET
@Produces("text/plain;qs=0.5",
"text/html;qs=0.75")
public Widgets getWidget() {...}
}
39
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
New in JAX-RS 2.0
• Client API
• Filters and Interceptors
• Client-side and Server-side Asynchronous
• Improved Connection Negotiation
• Validation
• Hypermedia
• Alignment with JSR 330
40
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Validation – Motivation
• Services must validate data
• Bean Validation already provides the mechanism
• Integration into JAX-RS
• Support for constraint annotations in:
• Fields and properties
• Parameters (including request entity)
• Methods (response entities)
• Resource classes
41
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Example: Constraint Annotations
@Path("/")
class MyResourceClass {
Built-in
Custom
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void registerUser(
@NotNull @FormParam("firstName") String fn,
@NotNull @FormParam("lastName") String ln,
@Email @FormParam("email") String em) {
... }
}
42
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Example: User defined Constraints
@Target({ METHOD, FIELD, PARAMETER })
@Retention(RUNTIME)
@Constraint(validatedBy = EmailValidator.class)
public @interface Email { ... }
class EmailValidator
implements ConstraintValidator<Email, String> {
public void initialize(Email email) {
… }
public boolean isValid(String value,
ConstraintValidatorContext context) {
// Check 'value' is e-mail address
… } }
43
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Example: Request Entity Validation
@CheckUser1
class User { ... }
@Path("/")
class MyResourceClass {
@POST
@Consumes("application/xml")
public void registerUser1(@Valid User u) { … }
@POST
@Consumes("application/json")
public void registerUser12(@CheckUser2 @Valid User u) {
… }
}
44
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
New in JAX-RS 2.0
• Client API
• Filters and Interceptors
• Client-side and Server-side Asynchronous
• Improved Connection Negotiation
• Validation
• Hypermedia
• Alignment with JSR 330
45
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Motivation
• REST principles
• Identifiers and Links
• HATEOAS (Hypermedia As The Engine Of App State)
• Link types:
• Structural Links
• Transitional Links
46
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Example: Structural vs. Transitional Links
Link: <http://.../orders/1/ship>; rel=ship,
<http://.../orders/1/cancel>; rel=cancel
Transitional
...
<order id="1">
<customer>http://.../customers/11</customer>
<address>http://.../customers/11/address/1</customer>
<items>
Structural
<item>
<product>http://.../products/111</products>
<quantity>2</quantity>
</item>
... </order>
47
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Example: Using Transitional Links
// Server API
Response res = Response.ok(order)
.link("http://.../orders/1/ship", "ship")
.build();
// Client API
Response order = client.target(…)
.request("application/xml").get();
if (order.getLink(“ship”) != null) {
Response shippedOrder = client
.target(order.getLink("ship"))
.request("application/xml").post(null);
… }
48
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Other Topics Under Consideration
• Better integration with JSR 330
• Support @Inject and qualifiers
• High-level client API?
49
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
More Information
• JSR: http://jcp.org/en/jsr/detail?id=339
• Java.net: http://jax-rs-spec.java.net
• User Alias: [email protected]
• All EG discussions forwarded to this list
50
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
Q&A
51
Copyright © 2012, Oracle and/or its affiliates. All rights
reserved.
© Copyright 2026 Paperzz