resteasy

37
RESTEasy Dessì Massimiliano Jug Meeting Cagliari 29 maggio 2010

Upload: massimiliano-dessi

Post on 07-Dec-2014

4.075 views

Category:

Technology


1 download

DESCRIPTION

RESTEasy slides may 2010

TRANSCRIPT

Page 1: RESTEasy

RESTEasy

Dessì Massimiliano

Jug Meeting Cagliari 29 maggio 2010

Page 2: RESTEasy

Software Architect and EngineerProNetics / Sourcesense

Presidente JugSardegna Onlus

Fondatore e coordinatoreSpringFramework Italian User Group

Committer - ContributorOpenNMS - MongoDB - MagicBox

AutoreSpring 2.5 Aspect Oriented Programming

Author

Page 3: RESTEasy

* Addressable resources * Each resource must be addressable via a URI

* Uniform, constrained interface * Http methods to manipulate resources

* Representation-oriented * Interact with representations of the service (JSON,XML,HTML)

* Stateless communication *

* Hypermedia As The Engine Of Application State *data formats drive state transitions in the application

REST

Page 4: RESTEasy

http://www.fruits.com/products/134

http://www.fruits.com/customers/146

http://www.fruits.com/orders/135

http://www.fruits.com/shipments/2468

Addressability

Page 5: RESTEasy

Uniform, Constrained Interface

GET read-only idempotent and safe (not change the server state)

PUT insert or update idempotent

DELETE idempotent

POST nonidempotent and unsafe

HEAD like GET but return response code and headers

OPTIONS information about the communication options

Page 6: RESTEasy

JSON XML YAML

...

Content-Type:

text/plain

text/html

application/xml

text/html;

charset=iso-8859-1....

Representation Oriented

Page 7: RESTEasy

no client session data stored on the server

it should be held and maintained

by the client and transferred

to the server with each request as needed

The server only manages the state

of the resources it exposes

Stateless communication

Page 8: RESTEasy

Hypermedia is a document-centric approach

hypermedia and hyperlinks as sets

of information from disparate sources

<order id="576"> <customer>http://www.fruits.com/customers/146</customer> <order-entries> <order-entry>

<quantity>7</quantity> <product>http://www.fruits.com/products/113</product> ...

HATEOAS

Page 9: RESTEasy

http://www.fruits.com/orders

http://www.fruits.com/orders/{id}

http://www.fruits.com/products

http://www.fruits.com/products/{id}

http://www.fruits.com/customers

http://www.fruits.com/customers/{id}

URI != RPC

Page 10: RESTEasy

GET /orders?index=0&size=15 HTTP/1.1

GET /products?index=0&size=15 HTTP/1.1

GET /customers?index=0&size=15 HTTP/1.1

GET /orders/189 HTTP/1.1

HTTP/1.1 200 OK Content-Type: application/xml <order id="189">

... </order>

Read - HTTP GET

Page 11: RESTEasy

@Path("/orders") public class OrderController {

@GET @Path("/{id}") @Produces("application/xml") public StreamingOutput getCustomer(@PathParam("id") int id) { final Order order = DBOrders.get(id); if (order == null) { throw new WebApplicationException(Response.Status.NOT_FOUND); } return new StreamingOutput() { public void write(OutputStream outputStream) throws IOException, WebApplicationException { outputOrder(outputStream, order); } };

}

Read - HTTP GET - RESTEasy way

Page 12: RESTEasy

POST /orders HTTP/1.1

Content-Type: application/xml <order> <total>€150.20</total>

<date>June 22, 2010 10:30</date> ... </order>

Create - HTTP POST

Page 13: RESTEasy

@Path("/customers") public class CustomerController {

@POST @Consumes("application/xml") public Response createCustomer(InputStream is) { Customer customer = readCustomerFromStream(is); customer.setId(idCounter.getNext()); DB.put(customer); StringBuilder sb = new StringBuilder("/customers/"). append(customer.getId()); return Response.created(URI.create(sb.toString()).build(); }

Create - HTTP POST – RESTEasy Way

Page 14: RESTEasy

PUT /orders/232 HTTP/1.1

Content-Type: application/xml <product id="444"> <name>HTC Desire</name> <cost>€450.00</cost> </product>

Update - HTTP PUT

Page 15: RESTEasy

@Path("/customers") public class CustomerController {

@PUT @Path("{id}") @Consumes("application/xml") public void updateCustomer(@PathParam("id") int id,InputStream is){ Customer update = readCustomerFromStream(is); Customer current = DB.get(id); if (current == null) throw new WebApplicationException(Response.Status.NOT_FOUND); current.setFirstName(update.getFirstName()); … DB.update(current);

}

Update - HTTP PUT - RESTEasy Way

Page 16: RESTEasy

DELETE /orders/232 HTTP/1.1

Delete - HTTP DELETE

Page 17: RESTEasy

@Path("/customers") public class CustomerController { @Path("{id}")

@DELETE public void delete(@PathParam("id") int id) {

db.delete(id); }

Delete - HTTP DELETE -RESTEasy way

Page 18: RESTEasy

@Consumes("text/xml")

@Produces("application/json")

@Produces("text/*")

...

Content Negotiation

Page 19: RESTEasy

@PathParam

@QueryParam

@HeaderParam

@MatrixParam

@CookieParam

@FormParam

@Form

@Encoded

@Context

Annotations available

Page 20: RESTEasy

The best is yet to come :)

Interceptors like Servlet Filter and AOP

Asynchronous calls

Asynchronous Job

GZIP compression

Page 21: RESTEasy

Interceptors

public interface MessageBodyReaderInterceptor { Object read(MessageBodyReaderContext context) throws IOException, WebApplicationException; }

public interface MessageBodyWriterInterceptor { void write(MessageBodyWriterContext context) throws IOException, WebApplicationException; }

Page 22: RESTEasy

Interceptors

public interface PreProcessInterceptor {ServerResponse preProcess(HttpRequest req, ResourceMethod method)

throws Failure, WebApplicationException; }

public interface PostProcessInterceptor { void postProcess(ServerResponse response); }

Page 23: RESTEasy

Interceptors

public interface ClientExecutionInterceptor {ClientResponse execute(ClientExecutionContext ctx)

throws Exception; }

public interface ClientExecutionContext { ClientRequest getRequest(); ClientResponse proceed() throws Exception; }

Page 24: RESTEasy

Interceptors

public interface MessageBodyReaderInterceptor { Object read(MessageBodyReaderContext context) throws IOException, WebApplicationException; }

public interface MessageBodyWriterInterceptor { void write(MessageBodyWriterContext context) throws IOException, WebApplicationException; }

public interface PreProcessInterceptor {ServerResponse preProcess(HttpRequest req, ResourceMethod method)

throws Failure, WebApplicationException; }

Page 25: RESTEasy

Interceptors

@Provider @ServerInterceptor public class MyHeaderDecorator implements

MessageBodyWriterInterceptor { public void write(MessageBodyWriterContext context)

throws IOException, WebApplicationException{context.getHeaders().add("My-Header", "custom"); context.proceed();

}

}

Page 26: RESTEasy

Interceptors

@Provider @ServerInterceptor @ClientInterceptor @Precedence("ENCODER") public class MyCompressionInterceptor

implements MessageBodyWriterInterceptor { … }

Page 27: RESTEasy

Asynchronous Job

RESTEasy Asynchronous Job Service is an implementation of

the Asynchronous Job pattern defined in

O'Reilly's "Restful Web Services"

Use:

/asynch/jobs/{job-id}?wait={millisconds}|nowait=true

Fire and forget http://example.com/myservice?oneway=true

Page 28: RESTEasy

@Consumes("application/xml") @PUT public void put(@GZIP Customer customer){ … }

@GET @Produces("application/xml") @GZIP public String getFooData() {

.. }

@GZIP

Page 29: RESTEasy

@Cache maxAge sMaxAge noStore noTransform mustRevalidate proxyRevalidate isPrivate

@NoCache

@CACHE

Page 30: RESTEasy

Asyncronous

@GET @Path("basic") @Produces("text/plain")public void getBasic(final @Suspend(10000) AsynchronousResponse res) throws Exception{

Thread t = new Thread() {

@Override public void run(){

try{ Response jaxrs = Response.ok("basic").type(MediaType.TEXT_PLAIN).build(); res.setResponse(jaxrs); }catch (Exception e) { e.printStackTrace(); } } }; t.start();}

Page 31: RESTEasy

WEB.XML

<servlet> <servlet-name>

Resteasy </servlet-name>

<servlet-class> org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher

</servlet-class> </servlet><servlet-mapping>

<servlet-name>Resteasy</servlet-name> <url-pattern>/*</url-pattern></servlet-mapping>

Page 32: RESTEasy

RESTEasy With Spring Without SpringDispatcherServlet/SpringMVC

<listener> <listener-class> org.resteasy.plugins.server.servlet.ResteasyBootstrap </listener-class></listener><listener> <listener-class> org.resteasy.plugins.spring.SpringContextLoaderListener </listener-class></listener><servlet-mapping>

<servlet-name>Resteasy</servlet-name> <url-pattern>/*</url-pattern></servlet-mapping><servlet-mapping>

<servlet-name>Resteasy</servlet-name> <url-pattern>/*</url-pattern>

</servlet-mapping>

Page 33: RESTEasy

RESTEasy With Spring With SpringDispatcherServlet/SpringMVC <servlet> <servlet-name>Resteasy</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> </servlet> <servlet-mapping>

<servlet-name>Spring</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>

Import in your bean's definition

<beans xmlns="http://www.springframework.org/schema/beans" ... <import resource="classpath:springmvc-resteasy.xml"/>

Page 34: RESTEasy

RESTEasy With Springimport javax.ws.rs.GET;import javax.ws.rs.Path;import javax.ws.rs.PathParam;import javax.ws.rs.Produces;...import org.springframework.stereotype.Controller;

@Path("rest/services")@Controllerpublic class FrontController {

@GET @Path("/{id}") @Produces(MediaType.TEXT_HTML) public ModelAndView getData(@PathParam("id") String collectionId) {

.... }

Page 35: RESTEasy

Other Features

ATOM supportJSON support

Client FrameworkMultipart Providers

YAML ProviderJAXB providersAuthenticationEJB IntegrationSeam Integration

Guice 2.0 IntegrationJBoss 5.x Integration

Page 36: RESTEasy

Q & A

Page 37: RESTEasy

Massimiliano Dessì desmax74 at yahoo.it

massimiliano.dessi at pronetics.it

http://twitter.com/desmax74

http://jroller.com/desmax

http://www.linkedin.com/in/desmax74

http://www.slideshare.net/desmax74

http://wiki.java.net/bin/view/People/MassimilianoDessi

http://www.jugsardegna.org/vqwiki/jsp/Wiki?MassimilianoDessi

Thanks for your attention!