Author: dkatayev
Date: 2010-08-05 11:08:10 -0400 (Thu, 05 Aug 2010)
New Revision: 2890
Added:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/introduction-to-rest.xml
Removed:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-framework.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-service-tutorial.xml
Modified:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws.xml
Log:
EXOJCR-870 WS documentation cleaned up
Added:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/introduction-to-rest.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/introduction-to-rest.xml
(rev 0)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/introduction-to-rest.xml 2010-08-05
15:08:10 UTC (rev 2890)
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id = "WS.Introduction">
+ <?dbhtml filename="ch-introduction-to-rest.html"?>
+
+ <title>Introduction to the Representational State Transfer (REST)</title>
+
+ <section>
+ <title>Introduction</title>
+
+ <para><command>Representational State Transfer (REST)</command> is
a style
+ of software architecture for distributed hypermedia systems such as the
+ World Wide Web. The term was introduced in the doctoral dissertation in
+ 2000 by Roy Fielding, one of the principal authors of the Hypertext
+ Transfer Protocol (HTTP) specification, and has come into widespread use
+ in the networking community.</para>
+
+ <para>REST strictly refers to a collection of network architecture
+ principles that outline how resources are defined and addressed. The term
+ is often used in a looser sense to describe any simple interface that
+ transmits domain-specific data over HTTP without an additional messaging
+ layer such as SOAP or session tracking via HTTP cookies.</para>
+
+ <para>The key abstraction of information in REST is a
+ <command>resource</command>. Any information that can be named can be a
+ resource: a document or image, a temporal service (e.g. "today's weather
+ in Los Angeles"), a collection of other resources, a non-virtual object
+ (e.g. a person), and so on. In other words, any concept that might be the
+ target of an author's hypertext reference must fit within the definition
+ of a resource. A resource is a conceptual mapping to a set of entities,
+ not the entity that corresponds to the mapping at any particular point in
+ time.</para>
+
+ <para>REST uses a <command>resource identifier </command>to
identify the
+ particular resource involved in an interaction between components. REST
+ connectors provide a generic interface for accessing and manipulating the
+ value set of a resource, regardless of how the membership function is
+ defined or the type of software that is handling the request. URL or URN
+ are the examples of a resource identifier.</para>
+
+ <para>REST components perform actions with a resource by using a
+ <command>representation</command> to capture the current or intended
state
+ of that resource and transferring that representation between components.
+ A representation is a sequence of bytes, plus <command>representation
+ metadata </command>to describe those bytes. Other commonly used but less
+ precise names for a representation include: <command>document, file, and
+ HTTP message entity, instance, or variant</command>. A representation
+ consists of data, metadata describing the data, and, on occasion, metadata
+ to describe the metadata (usually for the purpose of verifying message
+ integrity). Metadata are in the form of name-value pairs, where the name
+ corresponds to a standard that defines the value's structure and
+ semantics. The data format of a representation is known as a media
+ type.</para>
+
+ <table>
+ <title>REST Data Elements</title>
+
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry align="center">Data Element</entry>
+
+ <entry align="center">Modern Web Examples</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>resource</entry>
+
+ <entry>the intended conceptual target of a hypertext
+ reference</entry>
+ </row>
+
+ <row>
+ <entry>resource identifier</entry>
+
+ <entry>URL, URN</entry>
+ </row>
+
+ <row>
+ <entry>representation</entry>
+
+ <entry>HTML document, JPEG image</entry>
+ </row>
+
+ <row>
+ <entry>representation metadata</entry>
+
+ <entry>media type, last-modified time</entry>
+ </row>
+
+ <row>
+ <entry>resource metadata</entry>
+
+ <entry>source link, alternates, vary</entry>
+ </row>
+
+ <row>
+ <entry>control data</entry>
+
+ <entry>if-modified-since, cache-control</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>REST uses various <command>connector</command> types to
encapsulate
+ the activities of accessing resources and transferring resource
+ representations. The connectors present an abstract interface for
+ component communication, enhancing simplicity by providing a complete
+ separation of concepts and hiding the underlying implementation of
+ resources and communication mechanisms.</para>
+
+ <table>
+ <title>REST Connectors</title>
+
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry align="center">Connector</entry>
+
+ <entry align="center">Modern Web Examples</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>client</entry>
+
+ <entry>libwww, libwww-perl</entry>
+ </row>
+
+ <row>
+ <entry>server</entry>
+
+ <entry>libwww, Apache API, NSAPI</entry>
+ </row>
+
+ <row>
+ <entry>cache</entry>
+
+ <entry>browser cache, Akamai cache network</entry>
+ </row>
+
+ <row>
+ <entry>resolver</entry>
+
+ <entry>bind (DNS lookup library)</entry>
+ </row>
+
+ <row>
+ <entry>tunnel</entry>
+
+ <entry><para></para>SOCKS, SSL after HTTP
CONNECT</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>The primary connector types are client and server. The essential
+ difference between the two is that a client initiates communication by
+ making a request, whereas a server listens for connections and responds to
+ requests in order to supply access to its services. A component may
+ include both client and server connectors.</para>
+
+ <para>An important part of RESTful architecture is a well-defined
+ interface to communicate, in particular it is a set of HTTP methods such
+ as POST, GET, PUT and DELETE. These methods are often compared with the
+ CREATE, READ, UPDATE, DELETE (CRUD) operations associated with database
+ technologies. An analogy can also be made:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>PUT is analogous to CREATE or PASTE OVER,</para>
+ </listitem>
+
+ <listitem>
+ <para>GET to READ or COPY,</para>
+ </listitem>
+
+ <listitem>
+ <para>POST to UPDATE or PASTE AFTER, and</para>
+ </listitem>
+
+ <listitem>
+ <para>DELETE to DELETE or CUT.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><command>Note</command>: RESTful architecture is not limited
to
+ those methods, one of good examples of extension is the WebDAV
+ protocol.</para>
+
+ <para>The <command>CRUD</command> (Create, Read, Update and Delete)
verbs
+ are designed to operate with atomic data within the context of a database
+ transaction. REST is designed around the atomic transfer of a more complex
+ state and can be viewed as a mechanism for transferring structured
+ information from one application to another.</para>
+
+ <para>HTTP separates the notions of a web server and a web browser. This
+ allows the implementation of each to vary from the other based on the
+ client/server principle. When used RESTfully, HTTP is
+ <command>stateless</command>. Each message contains all the information
+ necessary to understand the request.</para>
+
+ <para>As a result, neither the client nor the server needs to remember any
+ communication-state between messages. Any state retained by the server
+ must be modeled as a resource..</para>
+ </section>
+</chapter>
Deleted:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-framework.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-framework.xml 2010-08-05
14:54:33 UTC (rev 2889)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-framework.xml 2010-08-05
15:08:10 UTC (rev 2890)
@@ -1,472 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="WS.RestFramework">
- <?dbhtml filename="ch-rest-framework.html"?>
-
- <title>REST Framework</title>
-
- <important>
- <para>This describes REST framework before version exo-ws-2.0</para>
- </important>
-
- <section>
- <title>Requirements</title>
-
- <para>The purpose of eXo REST framework is to make eXo services (i.e. the
- components deployed inside eXo Container) simple and transparently
- accessible via HTTP in RESTful manner. In other words those services
- should be viewed as a set of REST Resources - endpoints of the HTTP
- request-response chain, we call those services ResourceContainers.</para>
-
- <para>image: Simplified working model</para>
-
- <para>Taking into account HTTP/REST constraints, it is considered that
- Resources (naturally mapped as Java methods) contained in
- ResourceContainer conform with the following conditions:</para>
-
- <itemizedlist>
- <listitem>
- <para>they are uniquely identifiable in the same way as it is
- specified for HTTP i.e. using URI</para>
- </listitem>
-
- <listitem>
- <para>they can accept data from an HTTP request using all possible
- mechanisms, i.e. as a part of an URL, as URI parameters, as HTTP
- headers and body</para>
- </listitem>
-
- <listitem>
- <para>they can return data to an HTTP response using all possible
- mechanisms, i.e. as HTTP status, headers and body</para>
- </listitem>
- </itemizedlist>
-
- <para>From the implementation point of view:</para>
-
- <itemizedlist>
- <listitem>
- <para>the framework should be as much JSR-311 compatible as possible
- for the time the Specification is in draft and fully compatible after
- the standard's release</para>
- </listitem>
-
- <listitem>
- <para>the ResourceContainer components should be deployable and
- accessible in the same way as an ordinary service</para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>Implementation</title>
-
- <para>In our REST architecture implementation, an HTTPServlet is the
- front-end for the REST engine. In this RESTful framework, endpoints for
- HTTP request are represented by java classes (ResourceContainers). All
- ResourceContainers are run as components of an ExoContainer, so they are
- configured within the same configuration file.</para>
-
- <para>ResourceBinder and ResourceDispatcher are two other important
- components of the REST engine. ResourceBinder deals with binding and
- unbinding ResourceContainer. ResourceDispatcher dispatches REST requests
- to ResourceContainer. ResourceBinder and ResourceDispatcher are also
- components of the ExoContainer</para>
-
- <section>
- <title>ResourceContainer</title>
-
- <para>A ResourceContainer is an annotated java class. Annotations must
- at least describe URLs and HTTP methods to be served by this container.
- But they may also describe other parameters, like produced content type
- or transformers. Transformers are special Java classes, used to
- serialize and deserialize Java objects.</para>
-
- <para>A very simple ResourceContainer may look like this:</para>
-
- <programlisting>@HTTPMethod("GET")
-@URITemplate("/test1/{param}/test2/")
-public Response method1(@URIParam("param") String param) {
-//...
-//...
- Response resp = Response.Builder.ok().build();
- return resp;
-}</programlisting>
-
- <para>The ResourceContainer described above is very simple, it can serve
- the GET HTTP method for the relative URL /test1/{param}/test2/ where
- {param} can be any string value. Additionally, {param} can be used as a
- method parameter of the container by annotating it as :
- @URIParam("param") String param. For example, in URL /test1/myID/test2
- the method parameter "param" has the value
"myID".</para>
-
- <para>@URITemplate may be used for annotating classes or methods. If the
- TYPE scope annotation is for example @URITemplate("/testservices/") and
- a METHOD scope annotation is @URITemplate("/service1/") then that method
- can be called with the path /testservices/service1/. All
- ResourceContainer methods return Response objects. A Response includes
- HTTP status, an entity (the requested resource), HTTP headers and
- OutputEntityTransformer.</para>
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/rest-scheme.png" />
- </imageobject>
- </mediaobject>
-
- <para>A client sends a request, after some operations, the HTTP request
- is parsed into three parts: the HTTP request stream, which consists of
- the body of the request, HTTP headers and query parameters. Then
- ResourceDispatcher gets this request. During the start of ExoContainers
- ResourceBinder collects all available ResourceContainers and after the
- start passes the list of ResourceContainers to the ResourceDispatcher.
- When ResourceDispatcher gets the request from a client it tries to
- search for a valid ResourceContainer. For this search ResourceDispatcher
- uses @HTTPMethod, @URITemplate and @ProducedMimeType annotations. The
- last one is not always necessary, if it is not specified this is set in
- / (all mime types). When ResourceDispatcher found the "right"
- ResourceContainer it tries to call a method with some parameters.
- ResourceDispatcher will send only parameters which ResourceContainer
- requests. In the code example above the parameter is a part of the
- requested URL between "/test1/" and "/test2/".
ResourceContainer methods
- can consist only of some well-defined parameters. See the next
- rules:</para>
-
- <itemizedlist>
- <listitem>
- <para>Only one parameter of a method can be not annotated. This
- parameter represents the body of the HTTP request.</para>
- </listitem>
-
- <listitem>
- <para>All other parameters should be of java.lang.String types or
- must have a constructor with the java.lang.String parameter and must
- have annotation.</para>
- </listitem>
-
- <listitem>
- <para>If the parameter which represents the HTTP request body is
- present, then in the annotation @InputTransformer a java class must
- be defined that can build the requested parameter from
- java.io.InputStream. About transformation see below. After request
- processing ResourceContainer creates Request. Request is a special
- Java object which consists of HTTP status, a response header, an
- entity, a transformer. The entity is a representation of the
- requested resource. If Response has an entity it also must have
- OutputEntityTransformer. OutputEntityTransformer can be set in a few
- different ways.</para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>Response</title>
-
- <para>Response is created by Builder. Builder is an inner static Java
- class within Response. Builder has some preset ways to build Response,
- for example (see code example above). The method ok() creates Builder
- with status 200 (OK HTTP status) and ok() returns again a Builder
- object. In this way a developer can again call other Builder methods.
- For example:</para>
-
- <programlisting>//...
-Document doc = ....
-Response response = Response.Builder.ok().entity(doc,
"text/xml").transformer(new
XMLOutputTransformer()).build();</programlisting>
-
- <para>In the code example above Response has HTTP status 200, an XML
- document like entity, a Content-Type header "text/xml" and
- OutputEntityTransformer of type XMLOutputTransformer. The method build()
- should be called at the end of process. In the same way a developer can
- build some other prepared Responses, like CREATED, NO CONTENT,
- FORBIDDEN, INTERNAL ERROR and other. In this example we set
- OutputEntityTransformer directly. Another mechanism to do this is the
- same like in the case with InputEntityTransformer.</para>
-
- <programlisting>//...
-@HTTPMethod("GET")
-@URITemplate("/test/resource1/")
-(a)InputTransformer(XMLInputTransformer.class)
-(a)OutputTransformer(XMLOutputTransformer.class)
-public Response method1(Document inputDoc) {
-//...
- Document doc = ....
- Response response = Response.Builder.ok(doc, "text/xml").build();
- return response;
-}</programlisting>
-
- <para>InputEntityTransformer is described in the annotation to the
- method "method1". OutputEntityTransformer is described in the annotation
- to the method "method1".</para>
- </section>
-
- <section>
- <title>Transformer</title>
-
- <para>All transformers can be created by EntityTransformerFactory.
- Transformers can be divided in two groups. Transformers from the first
- one extend the abstract class InputEntityTransformer.
- InputEntityTransformer implements the interface
- GenericInputEntityTransformer, and GenericInputEntityTransformer extends
- the interface GenericEntityTransformer. This architecture gives the
- possibility to use one class EntityTransformerFactory for creating both
- types of transformers (input and output). At first we will speak about
- InputEntityTransformer.</para>
-
- <para><command>InputEntityTransformer</command></para>
-
- <para>All classes which extend the abstract class InputEntitytransformer
- must override the method ObjectreadFrom(InputStream entityDataStream).
- This method must return an object with the same type as
- ResourceContainer requires in method parameters (one not annotated
- parameter). This mechanism works in the following way. For example, a
- class which extends InputEntityTransformer will be called
- SimpleInputTransformer. So, SimpleInputTransformer must have a simple
- constructor (without any parameters). SimpleInputTransformer also has
- two methods void setType(Class entityType) and Class getType(). Those
- methods are described in InputEntityTransformer. And, as we said above,
- SimpleInputTransformer must override the abstract method Object
- readFrom(InputStream entityDataStream). So, a developer needs to create
- a class which can build a Java Object from InputStream and then create
- annotation to ResourceContainer or some method in ResourceContainer.
- This annotation must define the type of InputEntityTransformer. Here is
- the code of the annotation InputTransformer.</para>
-
- <programlisting>//...
-@Retention(RUNTIME)
-@Target({TYPE, METHOD})
-public @interface InputTransformer {
- Class<? extends InputEntityTransformer> value();
-}</programlisting>
-
- <para>Then ResourceDispatcher gets InputTransformer from the factory
- during runtime then builds an Object from stream and adds it to the
- parameter array. See the code below.</para>
-
- <programlisting>//...
- InputEntityTransformer transformer = (InputEntityTransformer)
factory_.newTransformer(resource.getInputTransformerType());
- transformer.setType(methodParameters[i]);
- params[i] = transformer.readFrom(request.getEntityStream());
-//...
- Response response = (Response)
resource.getServer().invoke(resource.getResourceContainer(),
params);</programlisting>
-
- <para>A developer can find some prepared transformers in the package
- "org.exoplatform.services.rest.transformer".</para>
-
- <para><command>OutputEntityTransformer</command></para>
-
- <para>OutputEntityTransformer can be used to serialize the Object which
- represents the requested resource to OutputStream.
- OutputEntityTransformer, in future we will call it
- SimpleOutputTransformer, can be defined in a few ways.</para>
-
- <para>Now some more words about transformation. The RESTful framework
- has two multi-purpose input/output transformers. One of them is
- JAXB(Input/Output)Transformer, and another one is
- Serializable(Input/Output)Transformer. The first one uses JAXB API for
- serializing and deserializing an object. Serializable
- (Input/Output)Transformer uses the own methods of an entity for
- serialization and deserialization. Here is an example:</para>
-
- <programlisting>/...
-public class SimpleSerializableEntity implements SerializableEntity {
-
- String data;
-
- public SimpleSerializableEntity() {
- }
-
- public void readObject(InputStream in) throws IOException {
- StringBuffer sb = new StringBuffer();
- int rd = -1;
- while((rd = in.read()) != -1)
- sb.append((char)rd);
- data = sb.toString();
- }
-
- public void writeObject(OutputStream out) throws IOException {
- out.write(data.getBytes());
- }
-}</programlisting>
-
- <para>SerializableInputTransformer will try to use the method void
- readObject(InputStream in) and SerializableOutputTransformer will try to
- use the method void writeObject(OutputStream in).</para>
- </section>
-
- <section>
- <title>Binding and unbinding components (ResourceContainers)</title>
-
- <para>ResourceBinder takes care of binding and unbinding components
- which represent ResourceContainer. All ResourceContainers must be
- defined as ExoContainer components in configuration files, for
- example:</para>
-
- <programlisting><component>
-
<type>org.exoplatform.services.rest.samples.RESTSampleService</type>
-</component></programlisting>
-
- <para>ResourceBinder is an ExoContainer component and implements the
- interface org.picocontainer.Startable (see the picocontainer
- documentation). So at the start of ExoContainer ResourceBinder collects
- all available ResourceContainers. ResourceBinder makes validation for
- all ResourceContainers. At least each ResourceContainer must have the
- @HTTPMethod annotation and @URITemplate annotation. Other annotations
- are not obligatory. It's not allowed to have few ResourceContainers or
- methods with the same @HTTPMethod and @URITemplate annotation value. For
- example, if one container/method has the following code:</para>
-
- <programlisting>public class SimpleResourceContainer implements
ResourceContainer {
- @HTTPMethod("GET")
- @URITemplate("/services/{id}/service1/")
- @InputTransformer(StringInputTransformer.class)
- @OutputTransformer(StringOutputTransformer.class)
- public Response method1(String data, @URIParam("id") String param) {
- // ...
- }
-}</programlisting>
-
- <para>than another component with @HTTPMethod("GET") and
- @URITemplate("/services/service1/{id}/") can't be bound. And now
we'll
- try to explain this situation. On the one hand URITemplate is defined by
- value /services/{id}/service1/, instead of {id} there can be any other
- string value, so the combination /services/service1/service1/ is
- possible and valid. On the other hand another URITemplate
- /services/service1/{id}/ can have the string service1 instead of {id},
- so for this resource the combination /services/service1/service1/ is
- possible and valid. And now we have two resources with the same
- URITemplate and the same HTTPMethod. This situation is not obligatory,
- we can't say what method we must call! In this case ResourceBinder
- generates InvalidResourceDescriptorException. Binder also checks the
- method parameters. In parameters only one parameter without annotation
- and of free type is allowed. All other parameters must have String type
- (or have a constructor with String) and be annotated. In other cases
- InvalidResourceDescriptorException* is generated. If all components have
- the "right" @HTTPMethod and @URITemplate annotations they should be
- bound without any problems. ResourceDispather gets a collection of
- ResourceContainers during the start and everything is ready to serve a
- request.</para>
-
- <para>Note: within the scope of one component (one class) validation for
- URI templates is not implemented, so a developer must take care of
- @URITemplate and @HTTPMethod. Both of them must not be the same for
- different methods. Except if @QueryTemplate or/and @ProducedMimeTypes
- annotation is used.</para>
- </section>
-
- <section>
- <title>ResourceDispatcher</title>
-
- <para>Now let's talk about the features of ResourceDispatcher.
- ResourceDispatcher is the main part of the RESTful engine. Above we said
- some words about transformation and the role of ResourceDispatcher in
- this process. Now we are ready to talk about annotated method
- parameters. In one of the code examples above you could see the next
- construction</para>
-
- <programlisting>public Response method1(String data,
@URIParam("id") String param) {</programlisting>
-
- <para>The method method1 is described with two parameters. The first
- parameter String data is built from the entity body (InputStream). The
- second one - String param is annotated by a special type Annotation.
- This Annotation has the following code:</para>
-
- <programlisting>@Target(value={PARAMETER})
-@Retention(RUNTIME)
-public @interface URIParam {
- String value();
-}</programlisting>
-
- <para>How does it work? After having found the right method
- ResourceDispatcher gets the list of method parameters and starts
- handling them. Dispatcher tries to find the not annotated parameter
- (this entity body) and addresses InputEntityTransformer in order to
- build the required Object from InputStream. When dispatcher finds an
- annotated parameter it checks the type of annotation. It is possible to
- have four types of annotation: @URIParam, @HeaderParam, @QueryParam and
- @ContextParameter. If dispatcher has found the annotation
- @URIParam("id") then it takes the parameter with the key "id"
from
- ResourceDescription and adds it into the parameter array. The same
- situation is with header, context and query parameters. So within the
- method a developer gets only the necessary parameters from header, query
- and uri. Some more information about @ContextParameters.
- @ContextParameters can be set in the configuration file of a
- component:</para>
-
- <programlisting><component>
-<type>org.exoplatform.services.rest.ResourceDispatcher</type>
- <init-params>
- <properties-param>
- <name>context-params</name>
- <property name="test" value="test_1"/>
- </properties-param>
- </init-params>
-</component></programlisting>
-
- <para>In this case any service can use this parameter, for
- example:</para>
-
- <programlisting>...method(@ContextParam("test") String p) {
- System.out.println(p);
-}</programlisting>
-
- <para>After its execution you should see "test_1" in
console.</para>
-
- <para>And in each service the next context parameters can be used. The
- name of these parameters are described in ResourceDispatcher:</para>
-
- <programlisting>public static final String CONTEXT_PARAM_HOST =
"host";
-public static final String CONTEXT_PARAM_BASE_URI = "baseURI";
-public static final String CONTEXT_PARAM_REL_URI = "relURI";
-public static final String CONTEXT_PARAM_ABSLOCATION =
"absLocation";</programlisting>
-
- <para>After that dispatcher finishes collecting parameters that the
- method requires, invokes this method and passes the result to the client
- as it is described above.</para>
-
- <para>This part of code can explain how this mechanism works:</para>
-
- <programlisting>//...
- for (int i = 0; i < methodParametersAnnotations.length; i++) {
- if (methodParametersAnnotations[i] == null) {
- InputEntityTransformer transformer = (InputEntityTransformer) factory
- .newTransformer(resource.getInputTransformerType());
- transformer.setType(methodParameters[i]);
- params[i] = transformer.readFrom(request.getEntityStream());
- } else {
- Constructor<?> constructor =
methodParameters[i].getConstructor(String.class);
- String constructorParam = null;
- Annotation a = methodParametersAnnotations[i];
- if (a.annotationType().isAssignableFrom(URIParam.class)) {
- URIParam u = (URIParam) a;
- constructorParam =
request.getResourceIdentifier().getParameters().get(u.value());
- } else if (a.annotationType().isAssignableFrom(HeaderParam.class)) {
- HeaderParam h = (HeaderParam) a;
- constructorParam = request.getHeaderParams().get(h.value());
- } else if (a.annotationType().isAssignableFrom(QueryParam.class)) {
- QueryParam q = (QueryParam) a;
- constructorParam = request.getQueryParams().get(q.value());
- } else if (a.annotationType().isAssignableFrom(ContextParam.class)) {
- ContextParam c = (ContextParam) a;
- constructorParam = contextHolder_.get().get(c.value());
- }
- if (methodParameters[i].isAssignableFrom(String.class)) {
- params[i] = constructorParam;
- } else {
- params[i] = (constructorParam != null) ?
constructor.newInstance(constructorParam) : null;
- }
- }
- }
- Response resp = (Response)
resource.getServer().invoke(resource.getResourceContainer(), params);
-//...</programlisting>
-
- <para>The more detailed schema looks like this:</para>
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/rest-scheme-detailed.png" />
- </imageobject>
- </mediaobject>
- </section>
- </section>
-</chapter>
Deleted:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-service-tutorial.xml
===================================================================
---
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-service-tutorial.xml 2010-08-05
14:54:33 UTC (rev 2889)
+++
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws/rest-service-tutorial.xml 2010-08-05
15:08:10 UTC (rev 2890)
@@ -1,218 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="WS.RestServiceTutorial">
- <?dbhtml filename="ch-rest-service-tutorial.html"?>
-
- <title>REST Service Tutorial</title>
-
- <important>
- <para>This article describes REST framework before version
- exo-ws-2.0.</para>
- </important>
-
- <section>
- <title>Introduction</title>
-
- <para>This HOW-TO explains how to create your own REST based services. In
- this HOW-TO we will create a simple calculator, which can do basic
- operations with integers.</para>
- </section>
-
- <section>
- <title>Source code</title>
-
- <programlisting>// ...
-@URITemplate("/calculator/{item1}/{item2}/")
-public class Calculator implements ResourceContainer {
-}</programlisting>
-
- <para>Writing <command>@URITemplate</command> before the class
definition
- gives you the possibility not to set it for each method. Furthermore the
- class must implement the interface <command>ResourceContainer</command>.
- This interface doesn't have any methods, it is just an indication for the
- <command>ResourceBinder</command>. Add the code for adding two
- integers.</para>
-
- <programlisting>// ...
-@URITemplate("/calculator/{item1}/{item2}/")
-public class Calculator implements ResourceContainer {
- @QueryTemplate("operation=add")
- @OutputTransformer(StringOutputTransformer.class)
- @HTTPMethod("GET")
- public Response add(@URIParam("item1") Integer item1,
- @URIParam("item2") Integer item2) {
- StringBuffer sb = new StringBuffer();
- sb.append(item1).append(" + ").append(item2).append(" =
").append(item1 + item2);
- return Response.Builder.ok(sb.toString(), "text/plain").build();
- }
-}</programlisting>
-
- <para>@QueryTemplate("operation=add") - only requests with query
- parameters "operation=add" can reach this method;
- @OutputTransformer(StringOutputTransformer.class) - the output
- transformer; @HTTPMethod("GET") - the HTTP method
"GET".</para>
-
- <para>Write the code for other operations in the same way. Then the result
- should look like:</para>
-
- <programlisting>package org.exoplatform.services.rest.example;
-
-import org.exoplatform.services.rest.HTTPMethod;
-import org.exoplatform.services.rest.OutputTransformer;
-import org.exoplatform.services.rest.QueryTemplate;
-import org.exoplatform.services.rest.Response;
-import org.exoplatform.services.rest.URIParam;
-import org.exoplatform.services.rest.URITemplate;
-import org.exoplatform.services.rest.container.ResourceContainer;
-import org.exoplatform.services.rest.transformer.StringOutputTransformer;
-
-@URITemplate("/calculator/{item1}/{item2}/")
-(a)OutputTransformer(StringOutputTransformer.class)
-public class Calculator implements ResourceContainer {
-
- @QueryTemplate("operation=add")
- @HTTPMethod("GET")
- public Response add(@URIParam("item1") Integer item1,
@URIParam("item2") Integer item2) {
- StringBuffer sb = new StringBuffer();
- sb.append(item1).append(" + ").append(item2).append(" =
").append(item1 + item2);
- return Response.Builder.ok(sb.toString(), "text/plain").build();
- }
-
- @QueryTemplate("operation=subtract")
- @HTTPMethod("GET")
- public Response subtract(@URIParam("item1") Integer item1,
@URIParam("item2") Integer item2) {
- StringBuffer sb = new StringBuffer();
- sb.append(item1).append(" - ").append(item2).append(" =
").append(item1 - item2);
- return Response.Builder.ok(sb.toString(), "text/plain").build();
- }
-
- @QueryTemplate("operation=multiply")
- @HTTPMethod("GET")
- public Response multiply(@URIParam("item1") Integer item1,
@URIParam("item2") Integer item2) {
- StringBuffer sb = new StringBuffer();
- sb.append(item1).append(" * ").append(item2).append(" =
").append(item1 * item2);
- return Response.Builder.ok(sb.toString(), "text/plain").build();
- }
-
- @QueryTemplate("operation=divide")
- @HTTPMethod("GET")
- public Response divide(@URIParam("item1") Integer item1,
@URIParam("item2") Integer item2) {
- StringBuffer sb = new StringBuffer();
- sb.append(item1).append(" / ").append(item2).append(" =
").append(item1 / item2);
- return Response.Builder.ok(sb.toString(), "text/plain").build();
- }
-}</programlisting>
-
- <para>So we are done with the source code.</para>
- </section>
-
- <section>
- <title>Configuration</title>
-
- <para>Create the directory conf/portal and create the file
- configuration.xml in it. Add the following code to this file:</para>
-
- <programlisting><?xml version="1.0"
encoding="ISO-8859-1"?>
-<configuration>
- <component>
-
<type>org.exoplatform.services.rest.example.Calculator</type>
- </component>
-</configuration></programlisting>
- </section>
-
- <section>
- <title>Build</title>
-
- <para>Now we must create the following directory structure to get the
- possibility to build the source code using maven.</para>
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/rest-build-process.png" />
- </imageobject>
- </mediaobject>
-
- <para>Then create the file pom.xml using the following:</para>
-
- <programlisting><project>
- <parent>
- <groupId>org.exoplatform.ws</groupId>
- <artifactId>config</artifactId>
- <version>trunk</version>
- </parent>
-
- <modelVersion&#624;.0.0</modelVersion>
- <groupId>org.exoplatform.ws.rest</groupId>
- <artifactId>simple.calculator</artifactId>
- <packaging>jar</packaging>
- <version>trunk</version>
- <description>Simple REST service</description>
-
- <dependencies>
- <dependency>
- <groupId>org.exoplatform.ws.rest</groupId>
- <artifactId>exo.rest.core</artifactId>
- <version>trunk</version>
- </dependency>
- </dependencies>
-</project></programlisting>
-
- <para>Build this by executing the command:</para>
-
- <programlisting>andrew@ubu:~/workspace/calculator$ mvn clean
install</programlisting>
- </section>
-
- <section>
- <title>Deploy</title>
-
- <para>We have done all now. Then copy the jar file from the target
- directory of project exo-tomcat into the server with all prepared stuff
- for REST services. (You can download it here: <ulink
-
url="http://forge.ow2.org/project/download.php?group_id=151&...
-
- <para>So just put the jar file into the lib directory of the tomcat and
- restart it. In the console you should see this message:</para>
-
- <programlisting>[INFO] ResourceBinder - Bind new ResourceContainer:
org.exoplatform.services.rest.example.Calculator@19846fd</programlisting>
-
- <para>This message indicates that our service was found, bound and is
- ready to work</para>
- </section>
-
- <section>
- <title>Usage</title>
-
- <para>Open your browser and type the following URL:
- <uri>http://localhost:8080/rest/calculator/12/5/?operation=add</uri> and
- you should see the next page:</para>
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/rest-run-process.png" />
- </imageobject>
- </mediaobject>
-
- <para>The service is working. This is a very simple example, but it should
- help developers use the REST framework.</para>
-
- <para>Try to check other URLs.</para>
-
- <itemizedlist>
- <listitem>
-
<para><uri>http://localhost:8080/rest/calculator/12/5/?operation=subtract</uri>
- - must give "12 - 5 = 7";</para>
- </listitem>
-
- <listitem>
-
<para><uri>http://localhost:8080/rest/calculator/12/5/?operation=multiply</uri>
- - must give "12 * 5 = 60";</para>
- </listitem>
-
- <listitem>
-
<para><uri>http://localhost:8080/rest/calculator/12/5/?operation=divide</uri>-
- must give "12 / 5 = 2" (we are working with integers!);</para>
- </listitem>
- </itemizedlist>
- </section>
-</chapter>
Modified: jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws.xml
===================================================================
--- jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws.xml 2010-08-05
14:54:33 UTC (rev 2889)
+++ jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/ws.xml 2010-08-05
15:08:10 UTC (rev 2890)
@@ -9,8 +9,8 @@
<xi:include href="ws/ws.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="ws/rest-framework.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="ws/introduction-to-rest.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="ws/groovy-scripts-as-rest-services.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />