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

Post on 10-May-2015

9.375 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

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

CDI, Seam & RESTEasy

You haven’t seen REST yet!

Dan AllenSenior Software EngineerJBoss, by Red Hat

Agenda

REST principles

JAX-RS

Seam RESTEasy integration

JAX-RS enhanced with CDI

Demo

Abusing HTTP with SOAP

REST to the rescue

Web ServiceWeb

Staying grounded with REST

Simple

Lightweight

High performance

Simple ingredients of the Web

HTTP application protocol

URI naming standard

XML markup language (and alternatives)

A tale of two webs

Browsable web

Programmable web

HTML +images +CSS, etc

XML(or JSON)

Document

Every web site is a service

Enabling automation

REST, spelled out

REpresentational State Transfer

RESTful architectural principles

Addressable resources

Uniformed, constrained interface

Representation-oriented

Stateless communication

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

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)

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

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)

Stateless communication

More scalable

– GET lends itself well to caching

Client maintains state

Takes burden off server

Respect the medium

Request

– HTTP method– URI– Request headers– Entity body

Response

– HTTP response code– Response headers– Entity body

What do you need to REST?

HTTP client (browser, bot, smart phone)

HTTP server that speaks REST

JAX-RS

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+

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

Our first REST resource

@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

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!

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

Throttling the response

@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

Parameter types

@QueryParam – Query string

@HeaderParam – HTTP header

@CookieParam – HTTP cookie

@FormParam – Form input

@PathParam – URI path

@MatrixParam – Matrix URI segment

Stepping into a sub-resource

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

@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

@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

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

@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

@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

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

@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

@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

@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

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

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);

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

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)

REST as a Seam resource

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

@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

<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

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>

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

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); }

}

Socialize demo

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...

Must reads

RESTful Web ServicesRichardson & RubyO’Reilly

RESTful Java with JAX-RSBill BurkeO’Reilly

To follow me

mojavelinux

GET /questions? HTTP/1.1

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