Shindig : An Architectural Overview ( PHP Version)
Author : Rajdeep Dua
This article is based on Shindig PHP code available in svn in May 2008
Social Networking has taken the internet from read only mode to a real collaborative mode intertwined with human networks. This has opened up unlimited ways in which the information can be stored, retrieved and used. OpenSocial attempts to reduce the pain for application developers to write applications from scratch for various Social networking sites.
OpenSocial is a specification which envisions a write once, run anywhere mantra in the Social Networking space. Shindig is a reference implementation of OpenSocial specifications for developers to develop against container providers. The Shindig code base can be used as a starting point and modified for Social networking sites which want to join the OpenSocial revolution.
The goal of this open source project is to be language neutral and provide implementation in multiple languages. Currently Java and PHP implementations are available. In the previous article I had outlined the Architectural Components of the Java Version. Since a lot of Social Networking sites are based on PHP, Shindig's PHP version can be an option for them if they want their site to be a pure play PHP based site.
Since the PHP version of Shindig has been ported from the Java Version, concepts like HTTP Servlet have been ported to a light weight HTTPServlet Implementation. The PHP version has a single entry point and all the calls are routed through index.php using Apache's mod_rewrite module.
Similar to the java version the PHP version also has 3 major server side components.
- Persistent Data Loading Mechanism
- Gadget Rendering Infrastructure
- OpenSocial server side implementation
Figure 1 describes these components in more detail. All the three components are accessed using HTTP / HTTPs through a Web Server. OpenSocial Server side components and Persistent Data Access Layer share a common Servlet Class ( GadgetDataServlet ), while Gadget Rendering components have a separate Servlet class as their entry point ( GadgetRenderingServlet).
Figure 1 : Components of Shindig Server Side container
The container consists of 6 different servlet classes. We describe how each of these map to server side components listed above
Figure 2 : Class diagram of various servlets within the Shindig container
All the servlets are subclasses of HttpServlet and serve as independent entry points at runtime. This architecture adoption has to do with the way in which Shindig has evolved.
- GadgetDataServlet -
- Takes requests for loading social data from file into DataObjects
- Takes requests for OpenSocial APIs
- Converts Gadget Xml into HTML
- Proxy Servlet
- Takes requests for URL Gadgets connects to the remote URL, fetches the content converts it into JSON and sends it back.
- Used for Loading JS libraries from external sources in URL gadgets
- Used to handle RPC metadata requests
Home page of the SampleContainer
Figure 3 : Sequence diagram explaining how the SampleContainer.html is loaded by the FilesServlet.php
Persistent Data Loading Mechanism
This layer is responsible for loading the persistent social data which includes- Person details, friends list, activities associated with a Person. In the default implementation this is stored in an XML file.
The GadgetDataServlet provides the entry point for the Persistent loading mechanism. This layer is pretty much pluggable and can be easily replaced with a more robust persistence mechanism. OpenSocialData Handler is used to populate the OpenSocial objects and query them. OpensocialDataHandler knows which handlers to invoke for loading the data from the XML file. The type of handler invoked depends on the kind of request.
Gadget Rendering Infrastructure
Gadget Rendering infrastructure has client side and server side components. It is responsible for generation of Gadget HTML from the Gadget Xml.
Client Side Components
Server Side Components :
Diagram below explains the sequence in more detail on how HTML is generated from the Gadget Xml and sent back to the browser.
Figure 4 : Collaboration flow on how the Gadget XML gets converted into HTML by the GadgetRenderingServlet and its downstream components
OpenSocial Server Side Implementation
We will be covering this scenario in more detail using the collaboration diagram. This diagram will show the call flow from the client side to the server side.
Client Side Components:
Figure 5 : Client Side Java Script Objects and their interaction.
All the Java script files within these are added to the generated HTML.
Figure 6 provides the details of various classes which represent and store the social graph on the client side for OpenSocial APIs.
Figure 6 : OpenSocial Model Class diagram
Server Side Components
All the OpenSocial calls are received by GadgetDataServlet and passed on to an instance of OpenSocialDataHandler. The actual type of data handler called depends on the type of request. List below is representative of the types for OpenSocial APIs.
- FETCH_PEOPLE : Get Person data
- FETCH_PERSON_APP_DATA : Get the data attributes for a person
- UPDATE_PERSON_APP_DATA : update attributes of a person
- FETCH_ACTIVITIES : Get List of activities for a Particular Person
- CREATE_ACTIVITY : create Activity associated with a Person
In the PHP implementation, OpenSocialDataHandler is responsible for handling all the requests. Figure 6a shows the Class diagram and Object composition which is involved in loading data for Person, Activities and Persistence from the Xml file
Figure 6a : Class and Object composition diagram for handlers responsible for loading and persisting social graph and related data in the Xml file.
GadgetDataServlet holds an array of handlers and has the mapping for which handler to call based on the nature of the call. In PHP implementation OpenSocialDataHandler is the only handler through which the flow goes. It extends the GadgetDataHandler and holds object instances of BasicPeopleService, BasicActivitiesService and BasicDataService.All the three services extend the corresponding abstract classes and are part of the SampleContainer. BasicPeopleService, BasicActivitiesService and BasicDataService eachof these classes use a single instance of XmlStateFileFetcher to parse and load data from the xml state file.
We will take FETCH_PEOPLE as an example and go through the flow in the figure below. BasicPeopleService is a wrapper on XML file based Persistent store which is used in Shindig .( XML file based implementation is just for demonstration, needs to be replaced by a more robust persistent mechanism)
This service loads, parses and stores the data of Person, Friends, Activities in memory in arrays in PHP (it was Maps in the Java version). Depending on the nature of call data is retrieved in memory, converted into JSON object(18) and sent back (19,20,21 ) to the client side for presentation.
Replacing the default Sample Container persistent store with a Custom Store
The diagram below expands the discussion so far into one figure. The OpenSocial Sample Container piece is the actual runtime by default. It consists of 3 services, BasicPeopleService, BasicActivitiesService and BasicDataService.
Figure 8 : Shindig architecture components and Sample Container Implementation
For Custom Persistent implementation the following classes in Figure 10 need to be replaced and implemented according to the storage mechanism being put in place. The handler class name also needs to be configured in config.php. For example, if we have a customer handler with a name 'MyHandler', the configuration will be 'handlers' => 'MyHandler'. There are other classes which can be easily replaced like Gadget blacklist , remote content fetcher and caching mechanism. Containers might want to modify or have their own custom implementation.
Shindig's basic implementation is a good starting point for somebody interested in getting started quickly on OpenSocial in their networking web sites. We explained how the container has a single entry point implemented using index.php and mod_rewrite module in Apache. The actual implementation is a straight port of servlet concept from the Java world with a basic Http servlet as a starting point. The rendering and social data access are independent components and can be replaced depending on the needs for it has to be used. Towards end of the article we talk about the pluggable nature of the data persistent layer. The pluggability in the architecture is a big help in adapting it quickly to the exact storage model required to be plugged in.
Shindig itself is a moving target with an active community and OpenSocial's evolving spec,but is a very good starting point for container providers looking for a head start.
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.