cdi, seam & resteasy: you haven't seen rest yet!

51
CDI, Seam & RESTEasy You haven’t seen REST yet! Dan Allen Senior Software Engineer JBoss, by Red Hat

Upload: dan-allen

Post on 10-May-2015

9.375 views

Category:

Technology


0 download

DESCRIPTION

JSR-311 (JAX-RS) is one of the simplest, most elegant of all the Java EE specifications. It enables you to create RESTful web services from POJOs by sprinkling a handful of annotations on them. As of Java EE 6, JAX-RS resources can now tie into the rest of the Java EE platform through the use of the standard contexts and dependency injection. facility (JSR-299: CDI). Seam's RESTEasy module takes this a step further by allowing you to use JAX-RS annotations on your existing Seam components, giving your REST resources access to the Seam container, infusing them with enhanced security, persistence management and other Seam portable extensions. You'll also discover that Seam eliminates the configuration required to add JAX-RS to your application and you'll be enthralled by the module's innovative approach to doing CRUD over REST. Using Seam, CDI and JAX-RS together let's you REST like never before.

TRANSCRIPT

Page 1: CDI, Seam & RESTEasy: You haven't seen REST yet!

CDI, Seam & RESTEasy

You haven’t seen REST yet!

Dan AllenSenior Software EngineerJBoss, by Red Hat

Page 2: CDI, Seam & RESTEasy: You haven't seen REST yet!

Agenda

REST principles

JAX-RS

Seam RESTEasy integration

JAX-RS enhanced with CDI

Demo

Page 3: CDI, Seam & RESTEasy: You haven't seen REST yet!

Abusing HTTP with SOAP

Page 4: CDI, Seam & RESTEasy: You haven't seen REST yet!

REST to the rescue

Web ServiceWeb

Page 5: CDI, Seam & RESTEasy: You haven't seen REST yet!

Staying grounded with REST

Simple

Lightweight

High performance

Page 6: CDI, Seam & RESTEasy: You haven't seen REST yet!

Simple ingredients of the Web

HTTP application protocol

URI naming standard

XML markup language (and alternatives)

Page 7: CDI, Seam & RESTEasy: You haven't seen REST yet!

A tale of two webs

Browsable web

Programmable web

HTML +images +CSS, etc

XML(or JSON)

Document

Page 8: CDI, Seam & RESTEasy: You haven't seen REST yet!

Every web site is a service

Page 9: CDI, Seam & RESTEasy: You haven't seen REST yet!

Enabling automation

Page 10: CDI, Seam & RESTEasy: You haven't seen REST yet!

REST, spelled out

REpresentational State Transfer

Page 11: CDI, Seam & RESTEasy: You haven't seen REST yet!

RESTful architectural principles

Addressable resources

Uniformed, constrained interface

Representation-oriented

Stateless communication

Page 12: CDI, Seam & RESTEasy: You haven't seen REST yet!

Addressable resources

URI for every resource in system

Resource reachable by unique ID

Provides scoping information

– Query string used to narrow result set

Stepping stones

– Makes it possible to link (linkability)– Allows disparate applications to interact

http://socialize.com/rest/updates/311http://socialize.com/rest/updates/311

Page 13: CDI, Seam & RESTEasy: You haven't seen REST yet!

Uniformed, constrained interface

Protocol method == operation

– 4 HTTP methods: GET, PUT, DELETE, POST

An architecture based on 4 methods?

– SQL (SELECT, INSERT, UPDATE, DELETE)– JMS (send, receive)

Page 14: CDI, Seam & RESTEasy: You haven't seen REST yet!

HTTP methods

GET - read only, idempotent and safe

PUT - insert or update, idempotent

DELETE - remove services, idempotent

POST - NOT idempotent NOR unsafe

– constraints are relaxed for flexibility

Page 15: CDI, Seam & RESTEasy: You haven't seen REST yet!

Representation-oriented

Data has a representation

– Negotiated between client and server

HTTP was designed for this purpose

Client – “I would prefer...”

– Accept (MIME type)– Accept-Language– Accept-Encoding

Server – “Here's what I'll give you...”

– Content-type header (MIME type)

Page 16: CDI, Seam & RESTEasy: You haven't seen REST yet!

Stateless communication

More scalable

– GET lends itself well to caching

Client maintains state

Takes burden off server

Page 17: CDI, Seam & RESTEasy: You haven't seen REST yet!

Respect the medium

Request

– HTTP method– URI– Request headers– Entity body

Response

– HTTP response code– Response headers– Entity body

Page 18: CDI, Seam & RESTEasy: You haven't seen REST yet!

What do you need to REST?

HTTP client (browser, bot, smart phone)

HTTP server that speaks REST

JAX-RS

Page 19: CDI, Seam & RESTEasy: You haven't seen REST yet!

JSR-311: JAX-RS

Java APIs for developing Web Services following the REST architectural style

Served via an HTTP servlet

Goals:

– POJO-based (annotations)– HTTP-centric– Format independent (MIME type)– Container independent– Inclusion in Java EE 5+

Page 20: CDI, Seam & RESTEasy: You haven't seen REST yet!

http://socialize.com/rest/timelinehttp://socialize.com/rest/timeline

Our first REST resource

Page 21: CDI, Seam & RESTEasy: You haven't seen REST yet!

@Path("/timeline")public class TimelineService {

@GET public String getUpdates() { return "<updates><update>...</update></updates>"; }

}

@Path("/timeline")public class TimelineService {

@GET public String getUpdates() { return "<updates><update>...</update></updates>"; }

}

Our first JAX-RS resource

Page 22: CDI, Seam & RESTEasy: You haven't seen REST yet!

How it works

REST Servlet handles GET request

Instance of TimelineService is created

@GET method called

Return value sent as response

Resource instance thrown away

JAX-RS component model is intentionally simple!

Page 23: CDI, Seam & RESTEasy: You haven't seen REST yet!

http://socialize.com/rest/timeline?count=25http://socialize.com/rest/timeline?count=25

Throttling the response

Page 24: CDI, Seam & RESTEasy: You haven't seen REST yet!

@Path("/timeline")public class TimelineService {

@GET public String getUpdates(@QueryParam("count") @DefaultValue("50") int count) { ... }

}

@Path("/timeline")public class TimelineService {

@GET public String getUpdates(@QueryParam("count") @DefaultValue("50") int count) { ... }

}

Accepting a query parameter

http://socialize.com/rest/timeline http://socialize.com/rest/timeline

http://socialize.com/rest/timeline?count=50http://socialize.com/rest/timeline?count=50

Page 25: CDI, Seam & RESTEasy: You haven't seen REST yet!

Parameter types

@QueryParam – Query string

@HeaderParam – HTTP header

@CookieParam – HTTP cookie

@FormParam – Form input

@PathParam – URI path

@MatrixParam – Matrix URI segment

Page 26: CDI, Seam & RESTEasy: You haven't seen REST yet!

Stepping into a sub-resource

http://socialize.com/rest/timeline/mojavelinuxhttp://socialize.com/rest/timeline/mojavelinux

Page 27: CDI, Seam & RESTEasy: You haven't seen REST yet!

@Path("/timeline")public class TimelineService {

@GET @Path("/{username}") public String getUpdates(@PathParam("username") String u) { ... }

}

@Path("/timeline")public class TimelineService {

@GET @Path("/{username}") public String getUpdates(@PathParam("username") String u) { ... }

}

Mapping a path parameter

Name defined in path expression;segment injected into method

Page 28: CDI, Seam & RESTEasy: You haven't seen REST yet!

@Path("/timeline")public class TimelineService {

@GET @Path("/{id:[0-9]+}") public String getUpdatesById(@PathParam("id") long id) { ... }

@GET @Path("/{username}") public String getUpdatesByUsername( @PathParam("username") String u) { ... }}

@Path("/timeline")public class TimelineService {

@GET @Path("/{id:[0-9]+}") public String getUpdatesById(@PathParam("id") long id) { ... }

@GET @Path("/{username}") public String getUpdatesByUsername( @PathParam("username") String u) { ... }}

Mapping different patterns

Fallback if patterns don't match

Page 29: CDI, Seam & RESTEasy: You haven't seen REST yet!

Negotiating a response

Which representation?

– Plain text?– HTML?– XML?– JSON?

The client needs to tell us

– Accept formats, weighted by preference

We have to decide what we support

– Respond with best match

Page 30: CDI, Seam & RESTEasy: You haven't seen REST yet!

@Path("/timeline")public class TimelineService {

@GET @Path("/{u}") @Produces("application/xml") public String getUpdatesAsXml(@PathParam("u") String u) { ... }

...}

@Path("/timeline")public class TimelineService {

@GET @Path("/{u}") @Produces("application/xml") public String getUpdatesAsXml(@PathParam("u") String u) { ... }

...}

Producing explicitly

Specify which formats aresupported using @Produces

Page 31: CDI, Seam & RESTEasy: You haven't seen REST yet!

@Path("/timeline")public class TimelineService {

@GET @Path("/{u}") @Produces("application/json") public String getUpdatesAsJson(@PathParam("u") String u) { ... }

...}

@Path("/timeline")public class TimelineService {

@GET @Path("/{u}") @Produces("application/json") public String getUpdatesAsJson(@PathParam("u") String u) { ... }

...}

Producing explicitly

Specify which formats aresupported using @Produces

Page 32: CDI, Seam & RESTEasy: You haven't seen REST yet!

Simplifying response production

Creating XML and JSON is laborious :(

JAX-RS supports converters

– HTTP entity body readers/writers

Provides built-in JAXB provider!

– Object ⇔ XML– Object ⇔ JSON

Page 33: CDI, Seam & RESTEasy: You haven't seen REST yet!

@XmlRootElement(name = "updates")public class Timeline implements Serializable {

private List<Update> updates = new ArrayList<Update>();

// constructors

@XmlElement(name = "update") public List<Update> getUpdates() { return updates; }

public void setUpdates(List<Update> updates) { this.updates = updates; }

}

@XmlRootElement(name = "updates")public class Timeline implements Serializable {

private List<Update> updates = new ArrayList<Update>();

// constructors

@XmlElement(name = "update") public List<Update> getUpdates() { return updates; }

public void setUpdates(List<Update> updates) { this.updates = updates; }

}

A model with XML hints

Page 34: CDI, Seam & RESTEasy: You haven't seen REST yet!

@Entity@XmlRootElementpublic class Update implements Serializable {

private Long id; private User user; private Date created; private String text;

// getters and setters

}

@Entity@XmlRootElementpublic class Update implements Serializable {

private Long id; private User user; private Date created; private String text;

// getters and setters

}

A related model with XML hints

Page 35: CDI, Seam & RESTEasy: You haven't seen REST yet!

@Path("/timeline")public class TimelineService {

@GET @Path("/{u}") @Produces("application/xml") public Timeline getUpdates(@PathParam("u") String u) { List<Update> updates = ...; return new Timeline(updates); }

}

@Path("/timeline")public class TimelineService {

@GET @Path("/{u}") @Produces("application/xml") public Timeline getUpdates(@PathParam("u") String u) { List<Update> updates = ...; return new Timeline(updates); }

}

Turning production over to JAXB

Page 36: CDI, Seam & RESTEasy: You haven't seen REST yet!

RESTEasy

Fully certified JAX-RS implementation

Portable to any container

Embedded server for testing

Client-side framework for JAX-RS

Response caching and compression

Rich set of providers

– XML, JSON, RSS, Atom, YAML, etc.

Asynchronous support

Page 37: CDI, Seam & RESTEasy: You haven't seen REST yet!

public interface TimelineClient {

@GET @Path("/timeline") @Produces("application/xml") Timeline getUpdates(@QueryParam("count") int count);

}

public interface TimelineClient {

@GET @Path("/timeline") @Produces("application/xml") Timeline getUpdates(@QueryParam("count") int count);

}

Invoking a service with RESTEasy

TimelineClient client = ProxyFactory.create(TimelineClient.class, ROOT_URI);String response = client.getUpdates(25);

TimelineClient client = ProxyFactory.create(TimelineClient.class, ROOT_URI);String response = client.getUpdates(25);

Page 38: CDI, Seam & RESTEasy: You haven't seen REST yet!

What does Seam 2 provide?

RESTEasy bootstrap and configuration

– Automatic resource/provider discovery– Resources/providers are Seam components

Seam security– HTTP authentication

– Authorization: @Restrict, @PermissionCheck

Exception to HTTP response mapping

Media type extension mapping

REST CRUD framework

SeamTest support

Page 39: CDI, Seam & RESTEasy: You haven't seen REST yet!

public abstract class Application { public abstract Set<Class<?>> getClasses(); public abstract Set<Object>getSingletons();}

public SocializeConfig extends Application { ...}

<context-param> <param-name>javax.ws.rs.core.Application</param-name> <param-value>com.socialize.SocializeConfig</param-value></context-param>

public abstract class Application { public abstract Set<Class<?>> getClasses(); public abstract Set<Object>getSingletons();}

public SocializeConfig extends Application { ...}

<context-param> <param-name>javax.ws.rs.core.Application</param-name> <param-value>com.socialize.SocializeConfig</param-value></context-param>

Typical JAX-RS setup (Java EE 5)

Page 40: CDI, Seam & RESTEasy: You haven't seen REST yet!

REST as a Seam resource

http://socialize.com/seam/resources/rest/timeline/mojavelinuxhttp://socialize.com/seam/resources/rest/timeline/mojavelinux

Page 41: CDI, Seam & RESTEasy: You haven't seen REST yet!

@Name("timelineService")@Path("/timeline")public class TimelineService { @In TimelineDao timelineDao;

@GET @Path("/{u}") @Produces("application/xml") public Timeline getUpdates(@PathParam("u") String u) { return timelineDao.fetchTimelineForUsername(u); }

}

@Name("timelineService")@Path("/timeline")public class TimelineService { @In TimelineDao timelineDao;

@GET @Path("/{u}") @Produces("application/xml") public Timeline getUpdates(@PathParam("u") String u) { return timelineDao.fetchTimelineForUsername(u); }

}

Seam-infused REST

Page 42: CDI, Seam & RESTEasy: You haven't seen REST yet!

<exception class="com.socialize.NoSuchUserException"> <http-error error-code="404"> <message>No such user</message> </http-error></exception>

<exception class="com.socialize.NoSuchUserException"> <http-error error-code="404"> <message>No such user</message> </http-error></exception>

Trapping exceptions

Page 43: CDI, Seam & RESTEasy: You haven't seen REST yet!

REST in a few fragments

<components> <framework:entity-home name="userHome" entity-class="com.socialize.model.User"/>

<resteasy:resource-home name="userResourceHome" path="/users" entity-home="#{userHome}" entity-id-class="java.lang.Long" media-types="application/xml application/json" readonly="false"/>

<resteasy:resource-query name="userResourceQuery" path="/users" entity-class="com.socialize.model.User" media-types="application/xml application/json"/></components>

<components> <framework:entity-home name="userHome" entity-class="com.socialize.model.User"/>

<resteasy:resource-home name="userResourceHome" path="/users" entity-home="#{userHome}" entity-id-class="java.lang.Long" media-types="application/xml application/json" readonly="false"/>

<resteasy:resource-query name="userResourceQuery" path="/users" entity-class="com.socialize.model.User" media-types="application/xml application/json"/></components>

Page 44: CDI, Seam & RESTEasy: You haven't seen REST yet!

Java EE 6, keeping it simple

@ApplicationPath("rest")public class JaxRsConfig extends Application {}@ApplicationPath("rest")public class JaxRsConfig extends Application {}

@Stateless@Path("/timeline")public class TimelineService { @PersistenceContext EntityManager em;

@GET @Path("/{u}") @Produces("application/xml") public Timeline getUpdates(@PathParam("u") String u) { return new Timeline(em.createQuery( "select u from Update u where u.user.username = :u") .setParameter("u", u).getResultList()); }}

@Stateless@Path("/timeline")public class TimelineService { @PersistenceContext EntityManager em;

@GET @Path("/{u}") @Produces("application/xml") public Timeline getUpdates(@PathParam("u") String u) { return new Timeline(em.createQuery( "select u from Update u where u.user.username = :u") .setParameter("u", u).getResultList()); }}

Must be a managedbean to enable CDI

Page 45: CDI, Seam & RESTEasy: You haven't seen REST yet!

Java EE 6, keeping it clean

@ApplicationPath("rest")public class JaxRsConfig extends Application {}@ApplicationPath("rest")public class JaxRsConfig extends Application {}

@Stateless@Path("/timeline")public class TimelineService { @Inject TimelineDao timelineDao;

@GET @Path("/{u}") @Produces("application/xml") public Timeline getUpdates(@PathParam("u") String u) { return timelineDao.fetchTimelineForUsername(u); }

}

@Stateless@Path("/timeline")public class TimelineService { @Inject TimelineDao timelineDao;

@GET @Path("/{u}") @Produces("application/xml") public Timeline getUpdates(@PathParam("u") String u) { return timelineDao.fetchTimelineForUsername(u); }

}

Page 46: CDI, Seam & RESTEasy: You haven't seen REST yet!

Socialize demo

Page 47: CDI, Seam & RESTEasy: You haven't seen REST yet!

Summary and call to action

Respect HTTP

– Resources are the foundation of the web

Expose your data in a standard way

– Don’t ball it up inside web pages!

Embrace simplicity

– Seam 2 + RESTEasy– Java EE 6 (JAX-RS + CDI)– Seam 3 integration coming soon...

Page 48: CDI, Seam & RESTEasy: You haven't seen REST yet!

Must reads

RESTful Web ServicesRichardson & RubyO’Reilly

RESTful Java with JAX-RSBill BurkeO’Reilly

Page 49: CDI, Seam & RESTEasy: You haven't seen REST yet!

To follow me

mojavelinux

Page 50: CDI, Seam & RESTEasy: You haven't seen REST yet!

GET /questions? HTTP/1.1

Page 51: CDI, Seam & RESTEasy: You haven't seen REST yet!

Presentation resources

JSR-311– http://jcp.org/en/jsr/detail?id=311

RESTEasy– http://jboss.org/resteasy

Seam RESTEasy integration– Web Services chapter of Seam reference guide

Bill Burke’s REST series on DZone– http://java.dzone.com/articles/putting-java-rest

Code samples– http://seaminaction.googlecode.com/svn/demos