C DI, S eam & R E S TE as y You havent seen RES T yet! Dan - - PowerPoint PPT Presentation
C DI, S eam & R E S TE as y You havent seen RES T yet! Dan - - PowerPoint PPT Presentation
C DI, S eam & R E S TE as y You havent seen RES T yet! Dan Allen S enior S oftware Engineer JBoss, by Red Hat Ag enda R E S T princ iples JAX -R S S eam R E S TE as y integ ration JAX -R S enhanc ed w ith C DI Demo Abus ing H TTP
Ag enda
R E S T princ iples JAX -R S S eam R E S TE as y integ ration JAX -R S enhanc ed w ith C DI Demo
Abus ing H TTP w ith S OAP
R E S T to the res c ue
Web S ervic e Web
S taying g rounded w ith R E S T
S imple Lig htw eig ht Hig h performanc e
S imple ing redients of the Web
HTTP applic ation protoc ol U R I naming s tandard X M L markup lang uag e
(and alternatives)
A tale of tw o w ebs
B row s able w eb Prog rammable w eb
HTML + images + CSS, etc XML (or JSON)
Document
E very w eb s ite is a s ervic e
E nabling automation
R E S T, s pelled out
R E pres entational S tate Trans fer
R E S Tful arc hitec tural princ iples
Addres s able res ourc es U niformed, c ons trained interfac e R epres entation-oriented S tateles s c ommunic ation
Addres s able res ourc es
U R I for every res ourc e in s ys tem R es ourc e reac hable by unique ID Provides s c oping information
– Query string used to narrow result set
S tepping s tones
– Makes it possible to link (linkability) – Allows disparate applications to interact
http://socialize.com/rest/updates/311 http://socialize.com/rest/updates/311
U niformed, c ons trained interfac e
Protoc ol method == operation
– 4 HTTP methods: GET, PUT, DELETE, POS T
An arc hitec ture bas ed on 4 methods ?
– SQL (SELECT, INSERT, UPDATE, DELETE) – JMS (send, receive)
HTTP methods
G E T - read only, idempotent and s afe PU T - ins ert or update, idempotent DE LE TE - remove s ervic es , idempotent POS T - NOT idempotent NOR uns afe
– constraints are relaxed for flexibility
R epres entation-oriented
Data has a repres entation
– Negotiated between client and server
HTTP w as des ig ned for this purpos e C lient – “I would prefer...”
– Accept (MIME type) – Accept-Language – Accept-Encoding
S erver – “Here's what I'll give you...”
– Content-type header (MIME type)
S tateles s c ommunic ation
M ore s c alable
– GET lends itself well to caching
C lient maintains s tate Takes burden off s erver
R es pec t the medium
R eques t
– HTTP method – URI – Request headers – Entity body
R es pons e
– HTTP response code – Response headers – Entity body
What do you need to R E S T?
HTTP c lient (browser, bot, smart phone) HTTP s erver that s peaks R E S T
JAX -R S
JS R -311: JAX -R S
Java APIs for developing Web S ervic es follow ing the R E S T arc hitec tural s tyle S erved via an HTTP s ervlet G oals :
– POJO-based (annotations) – HTTP-centric – Format independent (MIME type) – Container independent – Inclusion in Java EE 5+
http://socialize.com/rest/timeline http://socialize.com/rest/timeline
Our firs t R E S T res ourc e
@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 firs t JAX -R S res ourc e
How it w orks
R E S T S ervlet handles G E T reques t Ins tanc e of TimelineS ervic e is c reated @G E T method c alled R eturn value s ent as res pons e R es ourc e ins tanc e throw n aw ay
JAX-RS component model is intentionally simple!
http://socialize.com/rest/timeline?count=25 http://socialize.com/rest/timeline?count=25
Throttling the res pons e
@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) { ... } }
Ac c epting a query parameter
http://socialize.com/rest/timeline http://socialize.com/rest/timeline http://socialize.com/rest/timeline?count=50 http://socialize.com/rest/timeline?count=50
↴
Parameter types
@QueryParam – Query s tring @HeaderParam – HTTP header @C ookieParam – HTTP c ookie @FormParam – Form input @PathParam – U R I path @M atrixParam – M atrix U R I s eg ment
S tepping into a s ub-res ourc e
http://socialize.com/rest/timeline/mojavelinux http://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) { ... } }
M apping 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) { ... } }
M apping different patterns
Fallback if patterns don't match
N eg otiating a res pons e
Whic h repres entation?
– Plain text? – HTML? – XML? – JSON?
The c lient needs to tell us
– Accept formats, weighted by preference
We have to dec ide w hat w e s upport
– Respond with best match
@Path("/timeline") public class TimelineService { @GET @Path("/{u}") @Produces("applic ation/xml") public String getUpdatesAs X ml(@PathParam("u") String u) { ... } ... } @Path("/timeline") public class TimelineService { @GET @Path("/{u}") @Produces("applic ation/xml") public String getUpdatesAs X ml(@PathParam("u") String u) { ... } ... }
Produc ing explic itly
Specify which formats are supported using @Produces
@Path("/timeline") public class TimelineService { @GET @Path("/{u}") @Produces("applic ation/js on") public String getUpdatesAs Js on(@PathParam("u") String u) { ... } ... } @Path("/timeline") public class TimelineService { @GET @Path("/{u}") @Produces("applic ation/js on") public String getUpdatesAs Js on(@PathParam("u") String u) { ... } ... }
Produc ing explic itly
Specify which formats are supported using @Produces
S implifying res pons e produc tion
C reating X M L and JS ON is laborious :( JAX -R S s upports c onverters
– HTTP entity body readers/writers
Provides built-in JAX B 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 w ith X M L hints
@Entity @XmlRootElement public class Update implements Serializable { private Long id; private User user; private Date created; private String text; // getters and setters } @Entity @XmlRootElement public class Update implements Serializable { private Long id; private User user; private Date created; private String text; // getters and setters }
A related model w ith X M L 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 produc tion over to JAX B
R E S TE as y
Fully c ertified JAX -R S implementation Portable to any c ontainer E mbedded s erver for tes ting C lient-s ide framew ork for JAX -R S R es pons e c ac hing and c ompres s ion R ic h s et of providers
– XML, JSON, RSS, Atom, YAML, etc.
As ync hronous s upport
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 s ervic e w ith R E S TE as y
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 S eam 2 provide?
R E S TE as y boots trap and c onfig uration
– Automatic resource/provider discovery – Resources/providers are Seam components
S eam s ec urity
– HTTP authentication – Authorization: @Restrict, @PermissionCheck
E xc eption to HTTP res pons e mapping M edia type extens ion mapping R E S T C R U D framew ork
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>
Typic al JAX -R S s etup (Java E E 5)
R E S T as a S eam res ourc e
http://socialize.com/seam/resources/rest/timeline/mojavelinux http://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); } }
S eam-infus ed R E S T
<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 exc eptions
R E S T in a few frag ments
<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 E E 6, keeping it s imple
@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 managed bean to enable CDI
Java E E 6, keeping it c lean
@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); } }
S oc ialize demo
S ummary and c all to ac tion
R es pec t HTTP
– Resources are the foundation of the web
E xpos e your data in a s tandard w ay
– Don’t ball it up inside web pages!
E mbrac e s implic ity
– Seam 2 + RESTEasy – Java EE 6 (JAX-RS + CDI) – Seam 3 integration coming soon...
M us t reads
R E S Tful Web S ervic es Richardson & Ruby O’ Reilly R E S Tful Java w ith JAX - R S Bill Burke O’ Reilly
To follow me
mojavelinux
G E T /ques tions ? HTTP/1.1
Pres entation res ourc es
JS R -311
– http://jcp.org/en/jsr/detail?id=311
R E S TE as y
– http://jboss.org/resteasy
S eam R E S TE as y integ ration
– Web Services chapter of Seam reference guide
B ill B urke’s R E S T s eries on DZ one
– http://java.dzone.com/articles/putting-java-rest
C ode s amples
– http://seaminaction.googlecode.com/svn/demos