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


Top Related