大象传媒

芦 Previous Main Next 禄

Extending OpenSocial and Shindig: a crash course

Profile picture for Ben Smith Ben Smith

Post categories: ,

11:20 UK time, Friday, 6 November 2009

Hi, I'm , and I鈥檓 developing a new set of web services that add social features to 大象传媒 Online. Starting this project was clearly an exciting prospect, but without a handy crash course on how to get going, we ran into our fair share of problems. Now that we鈥檝e solved a few of them, I thought I鈥檇 better start writing about it.

Forging ahead

The 大象传媒鈥檚 overall web architecture has been rebuilt over the last couple of years, and a new breed of websites is now starting to appear (the platform's called 'The Forge', and you'll hear more about it soon). In a nutshell, these new sites are delivered through an application layer that relies on making HTTP calls to ish web services to get the data they need.

If we want to develop something social, we need some social web-services, and you don鈥檛 have to look too far into this before the jumps out and does a little dance in front of you. (Well, that鈥檚 what it did for me, but I may have been .)

It鈥檚 Open and it鈥檚 Social

OpenSocial defines a common set of APIs that applications can be developed against. The REST API allows applications to make HTTP requests, and get back things like a list of a user鈥檚 friends

/people/<userId>/@friends

or their recent activity

/activities/<userId>/@friends

Lovely stuff. Not only do we have a specification to work to, we have a popular one that many applications have already been developed against.

Additionally, to aid in the development of OpenSocial-compliant sites, the project provides OpenSocial implementations in both and . As the 大象传媒鈥檚 new platform is particularly fond of developing web services in Java, it鈥檚 all looking pretty good.

Is that it?

Unfortunately, life is never that easy. OpenSocial is designed to be a generic API to present your data through, whether you鈥檙e a , a or a jonnynewsite.com. But different websites have different needs: different relationship models, and various data and business logic around the creation of things like new users or relationships between them. It would be presumptuous of OpenSocial to define how a website should approach them, so it doesn鈥檛.

For example, while OpenSocial allows clients to get a user鈥檚 information:

/people/<userId>/@self

it doesn鈥檛 define a way to create a new user. So we have to do these things ourselves.

A bit of a Shindig

Shindig, the OpenSocial container implementation, quite rightly implements the OpenSocial specification and no more. As everyone will have their own infrastructure, with different databases, key-value stores and identity systems, Shindig defines software-level for you to implement. So, for Shindig to be able to respond to:

/people/<userId>/@self

you need to implement:

Future<Person> getPerson(
    UserId id, Set<String> fields, SecurityToken token)
    throws ProtocolException;

which is defined in the interface.

Extending OpenSocial

The 大象传媒 website has no social graph or any real social features to speak of. This meant that when we started, we were presented with an interesting opportunity: with no existing system to integrate with, could we extend the OpenSocial spec, and Shindig itself, to provide the features we were missing?

As I mentioned before, OpenSocial allows clients to retrieve a user鈥檚 friends:

/people/<userId>/@friends

So, to create a friendship between two users that鈥檚 consistent with the existing API calls, it seemed reasonable to POST a document (JSON in this case) that contains the new friend鈥檚 userId to the same URL:

POST {id: 鈥<friendId>鈥檥
/people/<userId>/@friends

Some may argue that a PUT to:

/people/<userId>/@friends/<friendId>

would smell more RESTful, but it鈥檚 not really any better and, considering the of OpenSocial鈥檚 RESTful-ness, keeping the API consistent was most important. However, if we were, say, keeping a description of the type of friendship (colleague, family, etc.) then we would need to be able to update that metadata, and would have PUT to the specific friendship resource:

PUT {type: 鈥榗olleague鈥檥
/people/<userId>/@friends/<friendId>

Extending Shindig

To add this function to Shindig, it鈥檚 a matter of extending the right bits. I鈥檝e created a on that shows how you can do this, but it鈥檚 worth saying that this isn鈥檛 production code, especially as it is backed by a non-persistent JSON store (and probably has more bugs in it than a ). As I mentioned earlier, Shindig specifies a service layer for you to implement. Conveniently, they also provide a that persists to an in-memory JSON store which is populated with dummy data.

Shindig is sensibly split into layers: the , the , and the (there鈥檚 actually a lot more to it than that, but you can read about that here). To extend the RESTful API you have to define the new endpoint in the appropriate handler, and a service that will administer the appropriate model objects.

So, to allow clients to POST new friendships to /people/<userId>/@friends, you must firstly extend the :

@Service(name = 鈥減eople鈥, path = 鈥/{userId}+/{groupId}/{personId}+鈥) 
public class PersonHandlerImpl extends PersonHandler {

Now you can implement a createFriends() method that will respond to POSTs to /people/<userId>/@friends:

@Operation(httpMethods = 鈥淧OST鈥, path = 鈥/{userId}+/@friends鈥)
public Future<?> createFriends(SocialRequestItem request) 
    throws ProtocolException {

You can see exactly how this is done in . The annotations are Shindig鈥檚 own home-brewed routing mechanism, but they鈥檙e pretty standard MVC controller fare. The handler itself shouldn鈥檛 do the work of creating a friendship, but should leave this to a service :

public interface RelationshipService {
  public void createRelationship(String personId, String friendId);

Now you have to implement the RelationshipService, in much the same way as you need to implement Shindig鈥檚 own standard services. As this is an example I simply to include a fleshed out createRelationship() method:

public class JsonDbServiceExample extends JsonDbOpensocialService
    implements RelationshipService {
  public void createRelationship(String personId, String friendId) {

Dependency issues

This is all fine and dandy, but how do any of these pieces actually know to use each other?

Shindig uses , a lightweight dependancy injection framework, which you use to tell the system that you actually want to use your handler and service implementations over theirs. To do this, you simply reference your own in your or .

It鈥檚 also worth mentioning that you can integrate Shindig and Guice with , which also provides dependancy injection and is very popular, as on the Shindig .

Anyway, if you fancy trying it out, the and, assuming the code still works, tinker to your heart鈥檚 content.

Bookmark this page:

What are these?

Comments

  • Comment number 1.

    You need to be cautious when stating a service is REST(ful|like). Fielding has criticised a few services for making such claims including SocialSite (based on OpenSocial)
    see:

  • Comment number 2.

    Absolutely Anthony. Like I said in the post (where I referenced Fielding's criticisms, under that same link) in this case it is more important to provide a consistent API, especially considering the RESTish imperfections.

  • Comment number 3.

    Hi Ben,
    thanks for a great article which explains in detail how to use Shindig in a proper way!:)
    I've also been interested in a way to add social network behavior to my web sites, and Shindig started to dance in front of me too:)
    But, have you heard about Project SocialSite before? It's based on Shindig, but got a JPA backend implemented, together with lot's of other features implemented. The original SocialSite project can be found here , but it's Ant-based, and only supports Shindig 0.7. We're working on a Maven-based SocialSite here which supports the current Shindig version.
    Take a look if you want to:)

  • Comment number 4.

    Hey Viggo, cheers for the comment.

    We did look at SocialSite and found it useful as a comparison. Unfortunately it wasn't mature enough to consider and some of its technology choices (such as using ant) seemed to detract from some of the things we really liked about Shindig. Considering how far we've extended the OpenSocial API, it was a good choice to stick with the core of Shindig.

    Have you spoken to SocialSite about committing back to them?

  • Comment number 5.

    Yes, we will commit it back (if they want the code..) when the Apache SocialSite is up and running :)

大象传媒 iD

大象传媒 navigation

大象传媒 漏 2014 The 大象传媒 is not responsible for the content of external sites. Read more.

This page is best viewed in an up-to-date web browser with style sheets (CSS) enabled. While you will be able to view the content of this page in your current browser, you will not be able to get the full visual experience. Please consider upgrading your browser software or enabling style sheets (CSS) if you are able to do so.