Overview of REST Concepts and Developing your First Web Script using Alfresco

Exclusive offer: get 50% off this eBook here
Alfresco 3 Web Services

Alfresco 3 Web Services — Save 50%

Build Alfresco applications using Web Services, WebScripts and CMIS

$35.99    $18.00
by Piergiorgio Lucidi Ugo Cei | August 2010 | Content Management Open Source Web Development

Alfresco 3 is one of the most versatile open source Enterprise Content Management (ECM) platforms. This is a real open source alternative to commercial product such as Microsoft SharePoint and EMC Documentum. It is also very well designed and suitable to be customized and extended. The open source adoption allows developers to contribute on the project and that's why you can find more than 240 extensions in the Alfresco Forge.

This article by Ugo Cei and Piergiorgio Lucidi, authors of the book Alfresco 3 Web Services, takes you through an overview of REST concepts and also provides you a step-by-step example to start developing your first Web Script.

(For more resources on Alfresco, see here.)

Web Scripts allow you to develop entire web applications on Alfresco by using just a scripting language—JavaScript and a templating language—FreeMarker. They offer a lightweight framework for quickly developing even complex interfaces such as Alfresco Share and Web Studio.

Besides this, Web Scripts can be used to develop Web Services for giving external applications access to the features of the Alfresco repository. Your Web Services, implemented according to the principles of the REST architectural style, can be easily reused by disparate, heterogeneous systems.

Specifically, in this article, you will learn:

  • What REST means and how it compares to SOAP
  • What elements are needed to implement a Web Script

A lightweight alternative to SOAP Web Services

The term Web Services is generally intended to denote a large family of specifications and protocols, of which SOAP is only a small part, which are often employed to let applications provide and consume services over the World Wide Web (WWW). This basically means exchanging XML messages over HTTP.

The main problem with the traditional approach to Web Services is that any implementation has to be compliant with a huge, and complicated set of specifications. This makes the application itself complex and typically hard to understand, debug, and maintain. A whole cottage industry has grown with the purpose of providing the tools necessary for letting developers abstract away this complexity. It is virtually impossible to develop any non-trivial application without these tools based on SOAP. In addition, one or more of the other Web Services standards such as WS-Security, WS-Transaction, or WS-Coordination are required. It is also impossible for any one person to have a reasonably in-depth knowledge of a meaningful portion of the whole Web Services stack (sometimes colloquially referred to as WS-*).

Recently, a backlash against this heavyweight approach in providing services over the Web has begun and some people have started pushing for a different paradigm, one that did not completely ignore and disrupt the architecture of the World Wide Web. The main objection that the proponents of the REST architectural style, as this paradigm is called, raise with respect to WS-* is that the use of the term Web in Web Services is fraudulent and misleading. The World Wide Web, they claim, was designed in accordance with REST principles and this is precisely why it was able to become the largest, most scalable information architecture ever realized. WS-*, on the other hand, is nothing more than a revamped, RPC-style message exchange paradigm. It's just CORBA once again, only this time over HTTP and using XML, to put it bluntly. As it has purportedly been demonstrated, this approach will never scale to the size of the World Wide Web, as it gets in the way of important web concerns such as cacheability, the proper usage of the HTTP protocol methods, and of well-known MIME types to decouple clients from servers.

Of course, you don't have to buy totally into the REST philosophy—which will be described in the next section—in order to appreciate the elegance, simplicity, and usefulness of Alfresco Web Scripts. After all, Alfresco gives you the choice to use either Web Scripts or the traditional, SOAP-based, Web Services. But you have to keep in mind that the newer and cooler pieces of Alfresco, such as Surf, Share, Web Studio, and the CMIS service, are being developed using Web Scripts. It is, therefore, mandatory that you know how the Web Scripts work, how to develop them, and how to interact with them, if you want to be part of this brave new world of RESTful services.

REST concepts

The term REST had been introduced by Roy T. Fielding, one of the architects of the HTTP protocol, in his Ph.D dissertation titled Architectural Styles and the Design of Network-based Software Architectures (available online at http://www.ics.uci.edu/ ~fielding/pubs/dissertation/top.htm).

Constraints

In his work, Dr. Fielding introduces an "architectural style for distributed hypermedia systems" called Representational State Transfer (REST). It does so by starting from an architectural style that does not impose any constraints on implementations (called the Null Style) and progressively adds new constraints that together define what REST is. Those constraints are:

  1. Client-Server interaction
  2. Statelessness
  3. Cacheability
  4. Uniform Interface
  5. Layered System
  6. Code-On-Demand (optional)

Fielding then goes on to define the main elements of the REST architectural style. Foremost among those are resources and representations. In contrast with distributed object systems, where data is always hidden behind an interface that only exposes operations that clients may perform on said data, "REST components communicate by transferring a representation of a resource in a format matching one of an evolving set of standard data types, selected dynamically based on the capabilities or desires of the recipient and the nature of the resource."

Resources

It is important to understand what a resource is and what it isn't. A resource is some information that can be named. It can correspond to a specific entity on a data management system such as a record in a database or a document in a DMS such as Alfresco. However, it can also map to a set of entities, such as a list of search results, or a non-virtual object like a person in the physical world. In any case, a resource is not the underlying entity.

Resources need to be named, and in a globally distributed system such as the World Wide Web, they must be identified in a way that guarantees the universality and possibly the univocity of identifiers. On the Web, resources are identified using Uniform Resource Identifiers (URI). A specific category of URIs are Uniform Resource Locators (URL) , which provide a way for clients to locate, that is to find, a resource anywhere on the Web, in addition to identifying it.

It is also assumed that URIs never change over the lifetime of a resource, no matter how much the internal state of the underlying entities changes over time. This allows the architecture of the Web to scale immensely, as the system does not need to rely on centralized link servers that maintain references separated from the content.

Representations

Representations are sequences of bytes intended to capture the current or intended state of a resource, as well as metadata (in the form of name / value pairs) about the resource or the representation itself.

The format of a representation is called its media type. Examples of media types are plain text, HTML , XML, JPEG, PDF, and so on. When servers and clients use a set of well-known, standardized media types, interoperability between systems is greatly simplified. Sometimes, it is possible for clients and servers to negotiate a specific format from a set that is supported by both.

Control data, which is exchanged between systems together with the representation, is used to determine the purpose of a message or the behavior of any intermediaries. Control data can be used by the client, for instance, to inform the server that the representation being transferred is meant to be the intended new state of the resource, or it can be used by the server to control how proxies, or the client itself, may cache representations.

The most obvious example of control data on the Web is HTTP methods and result codes. By using the PUT method, for example, a client usually signals to a server that it is sending an updated representation of the resource.

REST in practice

As we mentioned, REST is really just an abstract architectural style, not a specific architecture, network protocol, or software system. While no existing system exactly adheres to the full set of REST principles, the World Wide Web is probably the most well-known and successful implementation of them.

Developing Web Services that follow the REST paradigm boils down to following a handful of rules and using HTTP the way it was meant to be used. The following sections detail some of those rules.

Use URLs to identify resources

It is important that you design the URLs for your Web Service in such a way that they identify resources and do not describe the operations performed on said resources. It is a common mistake to use URLs such as:

/widgetService/createNewWidget

/widgetService/readWidget?id=1

/widgetService/updateWidget?id=1

/widgetService/deleteWidget?id=1

whenever, for instance, you want to design a web service for doing CRUD operations on widgets.

A proper, RESTful URL space for this kind of usage scenario could instead be something like the following:

/widgets/

To identify a collection of widgets

/widgets/id

To identify a single widget.

Then again, a RESTful interaction with a server that implements the previous service would be along the lines of the following (where we have indicated the HTTP verb together with the URL):

POST /widgets/

To create a new widget, whose representation is contained in the body of the request

GET /widgets/

To obtain a representation (listing) of all widgets of the

collection

GET /widgets/1

To obtain a representation of the widget having id=1

POST /widgets/1

To update a widget by sending a new representation (the PUT verb could be used here as well)

DELETE /widgets/1

To delete a widget

You can see here how URLs representing resources and the appropriate usage of HTTP methods can be used to implement a correctly designed RESTful Web Service for CRUD operations on server-side objects.

Use HTTP methods properly

There are four main methods that a client can use to tell a server which kind of operation to perform. You can call them commands, if you like. These are GET, POST, PUT, and DELETE. The HTTP 1.1 specification lists some other methods, such as HEAD, TRACE, and OPTIONS, but we can ignore them as they are not frequently used.

GET

GET is meant to be used for requests that are not intended to modify the state of a resource. This does not mean that the processing by the server of a GET request must be free of side effects—it is perfectly legal, for instance, to increment a counter of page views.

GET requests, however, should be idempotent. The property of idempotency means that a sequence of N identical requests should have the same side effects as a single request. The methods GET, HEAD, PUT, and DELETE share this property.

Basically, by using GET, a client signals that it intends to retrieve the representation of a resource. The server can perform any operation that causes side effects as part of the execution of the method, but the client cannot be held accountable for them.

PUT

PUT is generally used to send the modified representation of a resource. It is idempotent as well—multiple, identical PUT requests have the same effect as a single request.

DELETE

DELETE can be used to request the removal of a resource. This is another idempotent method.

POST

The POST method is used to request that the server accepts the entity enclosed in the request as a new subordinate of the resource identified by the URI named in the request.

POST is a bit like the Swiss army knife of HTTP and can be used for a number of purposes, including:

  • Annotation of existing resources
  • Posting a message to a bulletin board, newsgroup, or mailing list
  • Providing a block of data, such as the result of submitting a form, to a data-handling process
  • Extending a database through an append operation

POST is not an idempotent method.

One of the main objections proponents of REST raise with respect to traditional Web Service architectures is that, with the latter, POST is used for everything. While you shouldn't feel compelled to use every possible HTTP method in your Web Service (it is perfectly RESTful to use only GET and POST), you should at least know the expectations behind them and use them accordingly.

Alfresco 3 Web Services Build Alfresco applications using Web Services, WebScripts and CMIS
Published: August 2010
eBook Price: $35.99
Book Price: $59.99
See more
Select your format and quantity:

(For more resources on Alfresco, see here.)

Avoiding tight coupling

Ideally, any Web Services client should be able to talk to any server without many assumptions or the transmission of data outside the boundaries of the HTTP protocol. In general, you should eschew any practice, which tends to create unnecessary tight coupling between the client and the server.

One way to achieve this is to use standardized formats whenever possible. For instance, using Atom or RSS to represent a list of entities is generally preferable to inventing yet another markup language. Almost any client should be able to at least do something when served a response with a MIME type of application/atom+xml, for instance, a completely generic aggregator could act as an intermediary for clients by aggregating and caching Atom or RSS feeds, even without knowing anything about how application-specific data is encoded, for example, using foreign namespaces.

Use hyperlinks to drive the application state

One of the fundamental and mostly ignored principles of REST is that of Hypermedia as the Engine of Application State. This principle underlines the importance of hyperlinks as the preferred mechanism whereby clients know how to modify the state of an application hidden behind a Web Service.

In simple terms, this means that embedding links lets the clients know that, by following those links, they are acting on the server in a predetermined way.

The most egregious example of this is HTML forms. The action attribute of a form HTML element is exactly that: a link that the browser (the client) can follow by sending to its URL, using the method specified in the method attribute, a set of form data encoded using the format specified in the enctype attribute. There is no prior knowledge shared by the client and the server except what is known about the HTTP protocol itself and about the representation of form data using either the application/x-www-form-urlencoded or the multipart/form-data encodings.

By following this principle, you avoid, once again, unnecessary coupling between clients and servers—all of the information required to drive the application state is contained in the representations transmitted between them. A sure sign that you are not following REST principles is that you start writing documents about how clients should construct URLs and expect client implementers to read them. This is out-of-band transmission of information, and it should be avoided whenever possible.

Your first Web Script

That's enough with theory; in this section, we are going to show how to implement a very simple Web Script. You will see that, in order to do this, you don't have to launch your IDE, build, package, and deploy code. It is all very quick and can be done using just your browser.

You will probably have to do the write-build-package-deploy-test routine eventually, if you want to follow a repeatable, automatable development process, but not now. For now, we are going to keep things as simple as possible.

Components of a Web Script

At the very minimum, a Web Script is made up of two files:

  • A descriptor
  • A template

Somewhat ironically, a Web Script doesn't always need to have a script.

Creating your first Web Script

First, you are going to create the descriptor. This is an XML file, which you need to create in the Company Home | Data Dictionary | Web Scripts Extensions space. You can either create the descriptor locally on your computer, using your favorite programmer's editor (or even Notepad, if you like), or directly using the in-line editor of the Alfresco Explorer. Name the file first.get.desc.xml and type in its content as follows:

<webscript>
<shortname>First</shortname>
<description>My first Web Script</description>
<url>/first</url>
</webscript>

Next, you will write the template. Create or upload a file named first.get.html.ftl with the following content:

<html>
<body>
<p>This is your first Web Script. Congratulations!</p>
</body>
</html>

Finally, you need to register your new Web Script. It would be nice if Alfresco were able to register new Web Scripts automatically without the user's intervention. This is not the case at the moment, but luckily you only have to do this once for every new Web Script, not every time you modify it.

In order to register your new Web Script, navigate to http://localhost:8080/ alfresco/service/index and press the Refresh Web Scripts button. Please note that the previous URL ends with a slash, which you must include. If you now click on the List Web Scripts link, you should be able to see your newly created Web Script, listed with its URL, short name, and description, exactly as you have specified them in the descriptor file.

Invoking your first Web Script

In order to execute the Web Script you just created and see its output, simply point your browser to http://localhost:8080/alfresco/service/first and this is what you should see:

This is your first Web Script. Congratulations!

As you can probably imagine, the URL you used to obtain this output matches what was specified in the url tag inside the descriptor. This underscores the fact that Web Scripts are URL-addressable, it means that you can design and implement your own URL space, according to whatever rules and principles you want to follow. Just remember to always add http://localhost:8080/alfresco/service in front of the URLs found inside the descriptor.

What happens here is that Alfresco maps all request URLs starting with /service/ to the Web Script request dispatcher servlet. This, in turn, scans the URLs contained in all the Web Scripts' descriptors to find the one that matches most closely, and it then invokes the corresponding Web Script.

If a match is found and, as in our case, there is no controller script, the corresponding template is immediately rendered. The base logic for selecting a template is to search for a FreeMarker document having the same base name as the descriptor (first in this example), followed by the HTTP method used (which is always GET when you navigate using a browser, but is spelled in lowercase in the filename), followed by a format specification (html in this case, which wasn't actually specified anywhere, but is the default choice). Finally, the template must have the .ftl extension that indicates a FreeMarker template. The final result is exactly first.get.html.ftl.

The actual logic covers more complex situations, but what we outlined here is what happens in this simple case.

Adding a controller

More often than not, a Web Script will have a controller of some sort. While it is possible to have Web Scripts that are entirely backed by Java beans, the most often used option is to implement the controller in JavaScript, so this is what we will concentrate on.

In order to have a controller, all you need to do is create a text document called <basename>.<method>.js in the same folder as the descriptor and the templates. In the previous example, this would be first.get.js.

Let's then create a new text document called first.get.js in Company Home | Data Dictionary | Web Scripts Extensions, with the following content:

model.fullname = person.properties.firstName;
if (person.properties.lastName != "")
{
model.fullname += ' ' + person.properties.lastName;
}

You also need to modify the template first.get.html.ftl to make use of the fullname variable that we have just added to the model:

<html>
<body>
<p>Hello ${fullname}, this is your first Web Script.</p>
</body>
</html>

As we are now accessing the repository through the person object, we need to indicate that our Web Script must require authentication and execute it in a transaction. We do this by modifying the descriptor first.get.desc.xml to read:

<webscript>
<shortname>First</shortname>
<description>My first Web Script</description>
<url>/first</url>
<authentication>user</authentication>
<transaction>required</transaction>
</webscript>

After having added a controller and modified the descriptor, you must refresh the list of Web Scripts, as explained previously. This is necessary not only when you create a new Web Script, but also every time you alter the descriptor of an existing Web Script.

Do this now and, assuming that you have logged on to Alfresco as a user named, say, Jane Doe, this is what you should see:

Hello Jane Doe, this is your first Web Script.

If you haven't logged in yet, or if you are using a different browser to test your Web Script from the one you are using to edit it, the browser will pop up a login box before it lets you run it.

What we have just shown is how it is possible for the controller to pass values to the template by means of the model object. Just by naming a property x of the model object and assigning it a value, the controller makes that value available to the template as the value of the x variable. In FreeMarker templates , you use the ${x} syntax to evaluate the value of a variable or of an expression and output it at the position in the template that the expression occupies.

The set of objects which are available to the template includes everything that the controller adds to the model, also a number of so-called root-scoped objects, which are always available.

Some of these pre-defined objects, such as args, headers, and url, provide information about the current request.

Others, such as status, cache, and format, allow the script developer to manipulate the response that is being sent back to the client.

Another set of objects is only available when the user invoking the script has been authenticated. This includes roothome, companyhome, userhome, people, and person. These provide direct access to repository objects: folders, documents, and users.

Other objects, finally, are used to invoke repository services, such as search, classification, workflows, and actions.

The full list of root-scoped objects is documented at the following Wiki page: http://wiki.alfresco.com/wiki/Web_Scripts.

Summary

This article introduced the Web Scripts framework that has been an important part of Alfresco since version 2.1 and whose relevance is continually growing.

In this article, you learned:

  • The basic principles of the REST architectural style and how it compares to the traditional Web Services stack of specifications based on SOAP.
  • How the adoption of these principles impacts aspects like URL design and the choice of representation formats.
  • How to build and deploy a very simple Web Script and saw how this can be done very quickly and with very simple tools.

Further resources on this subject:


Alfresco 3 Web Services Build Alfresco applications using Web Services, WebScripts and CMIS
Published: August 2010
eBook Price: $35.99
Book Price: $59.99
See more
Select your format and quantity:

About the Author :


Piergiorgio Lucidi

Piergiorgio Lucidi is an open source ECM Specialist at Sourcesense. Sourcesense is a European open source systems integrator providing consultancy, support, and services around key open source technologies.

He works as Software Engineer, and he has 8 years of experience in the areas of Enterprise Content Management (ECM), system integrations, web, and mobile applications. He is an expert in integrating ECM solutions in web and portal applications.

He contributes as PMC member, Project Leader, and Committer at the Apache Software Foundation for the project Apache ManifoldCF; he also contributes on ECM connectors such as CMIS, Alfresco, and ElasticSearch. He is a Project Leader and Committer of the JBoss Community, and he contributes to some of the projects of the JBoss Portal platform.

He is a Speaker at conferences dedicated to ECM, Java, Spring Framework, and open source products and technologies.

He is an Author, Technical Reviewer, and Affiliate Partner at Packt Publishing, for whom he wrote the technical book Alfresco 3 Web Services. As Technical Reviewer, he contributed to both Alfresco 3 Cookbook and Alfresco Share. As Affiliate Partner, he writes and publishes book reviews on his website Open4Dev (http://www.open4dev.com/).

Ugo Cei

Ugo Cei is Solutions Delivery Manager at Sourcesense Italy. He has over 20 years of experience in the IT sector. His areas of expertise include Web application development, content management systems, database, and search technologies. He has a Ph.D. in Engineering from the University of Pavia, Italy.Ugo is a long-time active contributor to numerous Open Source project and a member of the Apache Software Foundation.Besides his interests in computer-related matters, Ugo is a passionate photographer. He sometimes dreams of leaving the IT field to pursue his passion full-time, and travel the world with a camera.

Books From Packt


jQuery 1.4 Reference Guide
jQuery 1.4 Reference Guide

WordPress 3 Site Blueprints
WordPress 3 Site Blueprints

The Oracle Universal Content Management Handbook
The Oracle Universal Content Management Handbook

Plone 3 Intranets
Plone 3 Intranets

Joomla! 1.5 Site Blueprints
Joomla! 1.5 Site Blueprints

Joomla! Social Networking with JomSocial
Joomla! Social Networking with JomSocial

Agile Web Application Development with Yii1.1 and   PHP5
Agile Web Application Development with Yii1.1 and PHP5

Nginx HTTP Server
Nginx HTTP Server


Your rating: None Average: 5 (2 votes)
good by
good
yes by
yes!

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
r
9
j
3
u
V
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software