Overview of REST Implementation in Shindig - Java Version
Author Rajdeep Dua
Aug 2008This article is based on Shindig code available in August ,2008 in svn
Introduction
In the previous articles[1] we have discussed about Shindig architecture on the Java side in detail, focusing on tech class diagrams as well as runtime collaboration diagrams. In this article we focus on the REST implementation which has been added since the last article. REST based implementation has various components, in this article we will be focusing on the Read only operation (GET)within the REST spec as other pieces ( POST, PUT, DELETE ) which modify the state still have to be implemented.
In this article we will be focusing on the key runtime components which serve the REST API calls. Detailed flow discussions will focus on the GET calls as the POST, PUT,DELETE calls have still not been implemented the Java Shindig.
REST Architectural Style
REST as we know stands for Representation State Transfer and was a term coined by Fielding as a part of this PhD thesis as one of the architectural style. Key aspects of this style
- Resources : Application state and features represented as resources with unique globally idenfiable addresses ( URLs )
- Operations : Constrained set of Operations
- Statelessness : System by default does not maintain state between the calls.
- Content - Type : Predefined constrained set of content type.
World wide web is a form of REST Architectural style with the following mapping
- Resources : Web pages
- Operations : GET, POST, PUT, DELETE - as supported by HTTP 1.1
- Content : HTML, XML, JSON,
OpenSocial REST Specification
OpenSocial foundation realized the inherent benefits of REST and have released specification specifying the resources and the unique URLs which will define the address for these resources.
Discovery of the resources
OpenSocial relies on XRDS simple specification for discovery and defining the meta around resources. XRDS Simple is a subset or original XRI 1.0 specification providing simpler means for defining the resources and their metadata at the same time being fully compliant XRI 2.0 specification.
Figure 1 : XRDS Simple document defining the REST Service endpoints in terms of Type and URI:Template
Figure 1 provides the tree representation of the XRDS document and what various nodes mean in relation to the OpenSocial REST endpoints.There are four types of REST services which can be exposed by an OpenSocial containers - People, Activities, Appdata and Group.There are URI Templates defined for each type of service.
Type URI-TemplateExplaination
People1./people/{guid}/@all 2./people/{guid}/@friends 3./people/{guid}/{groupid} 4./people/{guid}/@all/{pid} 5./people/{guid}/@self 6./people/@me/@self1.Collection of all people connected to user {guid} 2.Collection of all friends of user {guid}; subset of @all 3.Collection of all people connected to user {guid} in group {groupid} 4.Individual person record for a specific person known to {guid}; shows {guid}'s view of {pid}. 5.Profile record for user {guid} 6.Profile record for requestor Activities1./activities/{guid}/@self 2./activities/{guid}/@friends 3./activities/{guid}/{groupid} 4./activities/{guid}/@self/{activityid}1.Collection of activities generated by given user 2.Collection of activities for friends of the given user {guid} 3.Collection of activities for people in group {groupid} belonging to given user {uid} 4.Individual activity resource; usually discovered from collection Appdata1./appdata/{guid}/@self/{appid} 2./appdata/{guid}/@friends/{appid} 3./appdata/{guid}/@self/{appid}?fields=count1.All app data for user {guid}, app {appid} 2.All app data for friends of user {guid} and app {appid}; read-only (only GET and HEAD supported) 3.Just the count field for user {guid}, app {appid} Group/groups/{guid}Collection of groups associated with user {guid}
Table 1 : Source - REST API spec
REST Implementation in the client side container
Shindig Client side has a Restful container which extends OpenSocial container and is the component which passes on all the OpenSocial API calls to the REST endpoints. This means that the Endpoints serve both direct HTTP calls as well as calls from the OpenSocial APIs. Restful Container uses gadget.io package which opens an XmlHttpRequest object and then sends the data to the server.
Figure 1.1 : Restful Client container to make Client calls to REST Endpoints for OpenSocial Javascript APIs
REST Implementation in the Server side container
DataServiceServlet is the new Servlet added to support REST Endpoints. It along with the downstream components constitute the basic infrastructure on the which the REST APIs have been built. We had discussed in the earlier articles on various components within Shindig Java implementation, DataServiceServlet is another entry point in addition to the earlier components we had talked about -- GadgetRending and Data
![]()
Figure 2 : DataServiceServlet -- Entry point for REST Endpoints
Next Figure expands the blocks in more detail on how they interact with the handlers and the persistent state.
Figure 3 : Detailed component diagram of Rest implementation in Shindig
Diagram below provides the snapshot of the DataServiceServlet and its relation with other servlets. DataServiceServlet extends InjectedServlet and receives all the requests coming to Rest Endpoints.
Figure 4 : Servlet class diagram representing the class hierarchy of various entry points into Shindig
DataServiceServlet holds the reference of all the Handlers : People, Activity and AppData as well as the Bean and JsonConvertors. Class diagram below describes the relationship in more detail.
Figure 5 : DataServiceServlet's Object composition diagram showing the Handlers and Converters used by it to handle the REST calls
Handlers and Convertors.
All the REST calls are handled by one of the three handlers : PeopleHandler, ActivityHandler and AppDataHandler. All three of them extend DataHandler and hold reference to the JsonDBService which implements all the three interfaces : People, Activity and AppDataService. Convertors on the other hand are responsible for serializing objects into either Atom or Json depending on the format specified in the Url. Both these convertors implement BeanConvertor.
People based Scenarios
Rest Endpoint is identified by /people/ keyword all the sub URLs target Person and People specific scenarios. This endpoint supports getting the information , updating person specific information or deleting the information.
- Get
- Information of all the people belonging to any group
- URL : http://localhost:8080/social/rest/people/john.doe/@all
- Results :
- Information of all the profiles directly linked with the person identified by guid
- URL : http://localhost:8080/social/rest/people/john.doe/@friends
- Information of all the people linked with a Person identfied by guid and belonging to a groupId
- URL : http://localhost:8080/social/rest/people/john.doe/{groupid}
We will explain in a step by step process the GET call to get all the friends of a person using REST. Diagrams below gives a high level flow.All these flows are for http://localhost:8080/social/rest/people/john.doe/@friends?st=a:a:a:a:a:a.
Figure 6 : Describes the overall sequence for the GET Rest call for getting all the friends of john.doe
a:Calls the service method of DataServiceServlet b:Calls the doPost method b.i :Calls the getSecurityToken(..) method, b.ii :Gets the Convertor for the request b.iii :handleSingleRequest(.) method to handle the single request
Figure 7 : Details out step b.ii in Figure 6 in more detail
b.ii.a : Gets the value of the 'param" url parameter from the servletRequest objectb.ii.b : Gets the appropriate Convertor , if param=null get BeanJsonConverter else if the parameter is 'atom' returns BeanXmlConverter.
Figure 8 : Details out step b.iii in more detail
b.iii.a :get the http method from the parameter b.iii.b :Create a RequestItem Object b.iii.c :HandleRequestItem b.iii.c.1 :Gets the route from the parameter b.iii.c.2 :Gets the Handler from the InjectorImpl, PersonHandler in this case b.iii.c.2.1 :returns PersonHandler b.iii.c.3 : finally call the handleItem using this RequestItem
Figure 9 Shows the details of fist step in handleitem(requestItem) method
b.iii.c.3
b.iii.c.3 : handleItem(requestItem) b.iii.c.3.1 :calls the handleGet in PeopleHandler for the following patterns /people/john.doe/@all /people/john.doe/@friends /people/john.dpe/@self b.iii.c.3.1a: parses the Url template to get userId and groupId
Figure 10 : Expands the getPeople(..) request to get the JSON string
to be send back to the client
b.iii.c.3.2 :Call getPeople method in JsonDbOpenSocialService b.iii.c.3.2.a :Get JSONObject which holds the social graph b.iii.c.3.2.b :Get the Ids of friends for the userid b.iii.c.3.2.b.1 :Get the JSONObject from the FRIEND_LINK_TABLE b.iii.c.3.2.c :Create and populate JSONArray ( people ) and populate it based on return object form the previous call. b.iii.c.3.2.d :Convert the JSONArray into string and send it to the print writer.
Activity based Scenarios
Activity based Scenarios supported by REST Endpoints are
- Get
- Get activities for the self
- Get activities for friends
- Get activities for a particular group specified by groupId
- Get details of a particular activity
- Post
- Create a new activity for guid identified by self
- Delete
- Delete an activity identified by guid.
We will call a simple POST end point for creating a new Activity. We will hit the following endpoint and trace the flow of calls in the server side. http://localhost:8080/social/rest/activities/john.doe/@self?st=a:a:a:a:a:a. The content-type for POST request is application/json with character set of UTF-8.
Figure 11 : Describes the overall sequence for the POST Rest call for updating activity stream of john.doe. Almost same as Figure 6 -- Except POST instead of GET
a:Calls the service method of DataServiceServlet b:Calls the doPost method b.i :Calls the getSecurityToken(..) method, b.ii :Gets the Convertor for the request b.iii :handleSingleRequest(.) method to handle the single requestFigure 12 : Details out step b.ii in Figure 11 in more detail Almost same as Figure 7 -- Except POST instead of GET
b.ii.a : Gets the value of the 'param" url parameter from the servletRequest objectb.ii.b : Gets the appropriate Convertor , if param=null get BeanJsonConverter else if the parameter is 'atom' returns BeanXmlConverter.
Figure 13 : Details out step b.iii in more detail
b.iii.a :get the http method from the parameter which is POST in this case b.iii.b :Create a RequestItem Object b.iii.c :HandleRequestItem b.iii.c.1 :Gets the route from the parameter b.iii.c.2 :Gets the Handler from the InjectorImpl, ActivityHandler in this case b.iii.c.2.1 :returns ActivitynHandler b.iii.c.3 : finally call the handleItem using this RequestItem
Figure 14 Shows the details of fist step in handleitem(requestItem) method
b.iii.c.3
b.iii.c.3 : handleItem(requestItem) b.iii.c.3.1 :calls the handlePost in ActivityeHandler for the following patterns /activities/john.doe/@self b.iii.c.3.1a: parses the Url template to get userId and groupId ,userId is John.doe and groupId is @self
Figure 15 : Expands the createActivity(..) request.
to be send back to the client
b.iii.c.3.2 :Call createActivity method in JsonDbOpenSocialService b.iii.c.3.2.1 :Create a JSONObject from the parameters for creating an activity object. b.iii.c.3.2.2 :Get the JSONObject from the ACTIVITIES_TABLE b.iii.c.3.2.3 :Update the ACTIVITIES_TABLE with the new activity object
- Example 1 :
- Request URL : http://localhost:8080/social/rest/appdata/john.doe/@self/@app?count&st=a:a:a:a:a:a
- Response : {"entry":{"john.doe":{"count":"0"}}}
- PUT, POST update AppData for a user identified by a userId with key value pairs
- Key, value pairs specifying the AppData value to be stored
- Delete AppData for a particular person specified by PersonId and keys of the appdata specified.
Figure 17 : Collaboration diagram showing the server side object interaction to get app data for a particular user and app data key, describes the key components of AppData and how they interact with each other to serve the REST requests coming through DataServiceServlet.
a:Calls the service method of DataServiceServlet b:Calls the doPost method b.i :Calls the getSecurityToken(..) method, b.ii :Gets the Convertor for the request b.iii :handleSingleRequest(.) method to handle the single request b.iii.c.1 :Gets the route from the parameter b.iii.c.2 :Gets the Handler from the InjectorImpl, AppDataHandler in this case b.iii.c.3 : finally call the handleItem using this RequestItem b.iii.c.3.2.a : Get the Data_table for the userId b.iii.c.3.2.b : Create a PersonData JSONObject from the data extracted in step (a) b.iii.c.3.2.c : Create person to app data map b.iii.c.3.2.d : Create ResponseItem and send it to the browser
Summary
In this paper we covered where the REST implementation fits in Shindig - OpenSocial's reference implementation. REST has both client and server implementation as normal OpenSocial API calls also go through REST endpoints. We covered REST calls for Person/People , Activities and AppData related Scenarios. We also covered the discovery aspect of REST endpoints which uses XRDS Simple specification.
About the Author
Rajdeep is with Google Developer API Evangelism team working on OpenSocial Advocacy. He has around 10 years of experience in middleware, webservices and Integration space. Before joining Google he was leading development effort for CSF: Connected Services Framework Initiative in Microsoft India. He has also contributed to JBoss Open source development in the past. Rajdeep holds an MBA from IIM Lucknow, India.
References
- http://www.opensocial.org
- http://code.google.com/apis/opensocial/
- http://incubator.apache.org/shindig/
- http://chrisschalk.com/shindig_docs/rajdeep/shindig-overview/onjava-shindig-overview-tidy.html
- http://rajdeep.dua.googlepages.com/shindigPHP-overview-tidy_img.html