001package org.nuxeo.ecm.webengine.samples;
002
003import javax.ws.rs.GET;
004import javax.ws.rs.Path;
005import javax.ws.rs.Produces;
006
007import org.nuxeo.ecm.webengine.model.WebObject;
008import org.nuxeo.ecm.webengine.model.impl.DefaultObject;
009
010/**
011 * WebEngine Object Model. This sample explains the basics of Nuxeo WebEngine Object Model.
012 * <p>
013 * <h3>Resource Model</h3> Resources are objects used to serve the request. WebEngine Resources are always stateless (a
014 * new instance is created on each request). There are three types of resources defined by WebEngine:
015 * <ul>
016 * <li>Module Resource - this is the Web Module entry point as we've seen in sample3. This is the root resource. The
017 * other type of resources are JAX-RS sub-resources. A WebModule entry point is a special kind of WebObject having as
018 * type name the module name.
019 * <li>Web Object - this represents an object that can be requested via HTTP methods. This resource is usually wrapping
020 * some internal object to expose it as a JAX-RS resource.
021 * <li>Web Adapter - this is a special kind of resource that can be used to adapt Web Objects to application-specific
022 * needs.
023 * <p>
024 * These adapters are useful to add new functionalities on Web Objects without breaking application modularity or adding
025 * new methods on resources. This is helping in creating extensible applications, in keeping the code cleaner and in
026 * focusing better on the REST approach of the application. For example let say you defined a DocumentObject which will
027 * expose documents as JAX-RS resources. A JAX-RS resources will be able to respond to any HTTP method like GET, POST,
028 * PUT, DELETE. So let say we use:
029 * <ul>
030 * <li> {@code GET} to get a view on the DocumentObject
031 * <li> {@code POST} to create a DocumentObject
032 * <li> {@code PUT} to update a document object
033 * <li> {@code DELETE} to delete a DocumentObject.
034 * </ul>
035 * But what if I want to put a lock on the document? Or to query the lock state? or to remove the lock? Or more, to
036 * create a document version? or to get a document version? A simple way is to add new methods on the DocumentObject
037 * resource that will handle requests top lock, unlock, version etc. Somethig like {@code @GET @Path("lock") getLock()}
038 * or {@code @POST @Path("lock") postLock()}. But this approach is not flexible because you cannot easily add new
039 * functionalities on existing resources in a dynamic way. And also, doing so, you will end up with a cluttered code,
040 * having many methods for each new aspect of the Web Object you need to handle. To solve this problem, WebEngine is
041 * defining Web Adapters, so that they can be used to add new functionality on existing objects. For example, to handle
042 * the lock actions on an Web Object we will define a new class LockAdapter which will implement the {@code GET},
043 * {@code POST}, {@code DELETE} methods to manage the lock functionality on the target Web Object. Adapters are
044 * specified using an '@' prefix on the segment in an HTTP request path. This is needed by WebEngine to differentiate
045 * Web Objects from Web Adapters. Thus in our lock example to request the lock adapter on an object you will use a
046 * request path of like the following: {@code GET /my/document/@lock} or {@code POST /my/document/@lock} etc.
047 * <p>
048 * When defining a Web Adapter you can specify on which type of Web Object it may be used. (this is done using
049 * annotations)
050 * </ul>
051 * All WebEngine resources have a type, a super type, an optional set of facets and an optional guard (these are
052 * declared using annotations) By using types and super types you can create hierarchies or resources, so that derived
053 * resource types will inherit attributes of the super types.
054 * <p>
055 * There is a builtin adapter that is managing Web Objects views. The adapter name is {@code @views}. You will see in
056 * the view model an example on how to use it.
057 * <p>
058 * Thus, request paths will be resolved to a resource chain usually of the form: WebModule -> WebObject -> ... ->
059 * WebObject [ -> WebAdapter ]. <br>
060 * Each of these resource objects will be <i>served</i> using the <i>sub-resource</i> mechanism of JAX-RS until the last
061 * resource is reached. The last resource will usually return a view to be rendered or a redirection response. The
062 * request resource chain is exposed by the WebContext object, so that one can programatically retrieve any resource
063 * from the chain. In a given resource chain there will be always 2 special resources: a <b>root</b> and a <b>target</b>
064 * resource The root resource is exposed in templates as the {@code Root} object and the target one as the contextual
065 * object: {@code This}. <br>
066 * <b>Note</b> that the root resource is not necessarily the first one, and the target resource is not necessarily the
067 * last one! More, the root and the target resources are never WebAdapters. They can be only WebObjects or WebModule
068 * entry points (that are aspecial kind of WebObjects).
069 * <p>
070 * The root resource is by default the module entry point (i.e. the first resource in the chain) but can be
071 * programatically set to point to any other WebObject from the chain.
072 * <p>
073 * The target resource will be always the last WebObject resource from the chain (so any trailing WebAdapters are
074 * excluded). This means in the chain: {@code /my/space/doc/@lock}, the root will be by default {@code my} which is the
075 * module entry point, and the target resource will be {@code doc}. So it means that the {@code $This} object exposed to
076 * templates (and/or views) will never points to the adapter {@code @lock} - but to the last WebObject in the chain. So
077 * when an adapter view is rendered the {@code $This} variable will point to the adapted WebObject and not to the
078 * adapter itself. In that case you can retrieve the adapter using {@code $This.activeAdapter}. This is an important
079 * aspect in order to correctly understand the behavior of the {@code $This} object exposed in templates.
080 * <p>
081 * <h3>View Model</h3> The view model is an extension of the template model we discussed in the previous sample. The
082 * difference between views and templates is that views are always attached to an Web Object. Also, the view file
083 * resolution is a bit different from template files. Templates are all living in {@code skin} directory. Views may live
084 * in two places:}
085 * <ul>
086 * <li>in the skin/views/${type-name} folders where type-name is the resource type name the view is applying on. This
087 * location will be consulted first when a view file is resolved, so it can be used by derived modules to replace views
088 * on already defined objects.
089 * <li>in the same folder (e.g. java package) as the resource class. This location is useful to defining views inside
090 * JARs along with resource classes.
091 * </ul>
092 * Another specific property of views is that they are inherited from resource super types. For example if you have a
093 * resource of type {@code Base} and a resource of type {@code Derived} then all views defined on type {@code Base}
094 * apply on type {@code Derived} too. You may override these views by redefining them on type {@code Derived} <br>
095 * Another difference between templates and views is that views may vary depending on the response media-type. A view is
096 * identified by an ID. The view file name is computed as follow:
097 *
098 * <pre>
099 * view_id + [-media_type_id] + ".ftl"
100 * </pre>
101 *
102 * The {@code media_type_id} is optional and will be empty for media-types not explicitly bound to an ID in modules.xml
103 * configuration file. For example, to dynamically change the view file corresponding to a view having the ID
104 * {@code index} when the response media-type is {@code application/atom+xml} you can define a mapping of this media
105 * type to the media_type_id {@code atom} and then you can use the file name {@code index-atom.ftl} to specify a
106 * specific index view when {@code atom} output is required.
107 *
108 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
109 */
110@WebObject(type = "Basics")
111@Produces("text/html;charset=UTF-8")
112public class BasicsObject extends DefaultObject {
113
114    /**
115     * Get the index view. The view file name is computed as follows: index[-media_type_id].ftl First the
116     * skin/views/Basics is searched for that file then the current directory. (The type of a module is the same as its
117     * name)
118     */
119    @GET
120    public Object doGet() {
121        return getView("index");
122    }
123
124    /**
125     * Get the WebObject (i.e. a JAX-RS sub-resource) bound to "users". Look into "users" directory for the UserManager
126     * WebObject. The location of WebObjects is not explictely specified by the programmer. The module directory will be
127     * automatically scanned for WebObject and WebAdapters.
128     */
129    @Path("users")
130    public Object getUserManager() {
131        // create a new instance of an WebObject which type is "UserManager" and push this object on the request chain
132        return newObject("UserManager");
133    }
134
135}