Latest Posts

Archives [+]

Entries filed under 'social'

    Posted by Lars Trieloff APR 01, 2009

    Posted in cq5, everything is content and social Add comment

    Today, our CQ5 Digital Asset Management and CQ5 Social Collaboration become available with the launch of CQ 5.2. This is a great day for me, because my two products that I have been working on for the last one and a half years are going to market.

    Both with CQ DAM 5.2 and CQ Social Collaboration 5.2 I have been standing on the shoulders of giants, which have enabled me to implement a bold vision of Digital Asset Management and Social Collaboration integrated into Web Content Management in such a short time, following our CQ5.1 release last November. These giants are our developer team and our product marketing team who have a done a marvelous job on getting this product to countless demos, POCs, beta projects, press and analyst briefings and who have implemented one cool feature after the other.

    But standing on the shoulders of giants also means reusing a great platform to build upon. We did not have to think a single second about clustering, backup, scaling, permissions, LDAP integration, workflow, development environment, because all this is at some level provided out of the box by CRX (and its underlying Apache Jackrabbit and Apache Sling foundations) and the CQ5 Platform we share with CQ5 Web Content Management.

    I would like to take the opportunity to shed the light on two smaller features, one in CQ5 DAM and one in Social Collaboration that we typically do not include in demos, but that offer a huge potential for everyone who sees our products as a platform to realize his own ideas.

    Feature number one is the workflow launcher we are using especially for CQ5 DAM. This workflow launcher will listen for repository events at a certain part of your content repository, for example the DAM bulk upload hot zone or a Sharepoint repository we are monitoring through our connectors. Once a new file is being created here, we launch the workflow that will take care of the actual processing. For the end user this means: more flexibility in creating complex workflow-driven processing solutions for digital assets. And it means a reduction of magic, because everything that will happen to your assets is visible (in the Workflow Models tab) and the reason why it happens is visible in the workflow launcher tab. Not attempting to do magic and to appear as magician should be a goal for every software engineer.

    The second feature is even less graphic (guess why we are not demoing it), but it is one of the small pieces that makes Social Collaboration so great. We call it the 'Feed Importer', but it actually does a lot more. The idea of the feed importer is to poll a remote resource at a specified interval, to parse it and to create nodes in the content repository that represent the content of the remote resource. We are using this at two places right now - for subscribing to remote iCalendar files just like you do in Apple's iCal or Google Calendar and in the blog, where you can aggregate existing blogs in one 'planet blog' that for instance contains all bloggers of the JCR community. This auto-blogging-feature has been in the blog since Advanced Collaboration 1.1, but with Social Collaboration 5.2 there is a proper and powerful API that can be used in customer projects as well. Needless to say, in order to implement a new parser & importer all you have to do is implement one OSGi component and I expect it to be not too long till we see Twitter-mashups on CQ5-powered websites that are using the Feed Importer.

     

    So thank you very much for all the help with the 5.2 release and I am looking forward to see many CQ5-powered community websites and public asset repositories soon.

    Posted by Lars Trieloff MAY 30, 2008

    Posted in social Add comment

    In my second presentation I tried to be less controversial, at least in the title. In "Creating Value in Social Networking" I took the product manager's point of view to define social networking by analyzing existing popular social networks feature-by-feature. From this feature-oriented approach we took a look at some ways of monetizing social networks, which is actually much easier if you are not a pure social network, but already have valuable content that you enhance by adding social relevancy. Even better, when you already have a revenue model the social networking features can increase visitor loyalty and boost your revenues.



    Posted by Michael Marth APR 18, 2008

    Posted in crx quickstart, data first, davids model, everything is content, graph, jcr, open, rest, sling, social and tutorial Comments 4

    In case you follow emerging Internet standards you will have come across OpenSocial, the Google-led spec for social network applications. Major supporters are MySpace, LinkedIn, XING, Google's own Orkut, Hi5 and others. The Apache Software Foundation's implementation of this spec is called Apache Shindig. It is a container (runtime) for OpenSocial applications (which are called gadgets).

    In my opinion OpenSocial and Apache Sling are a good technical fit for at least two reasons:

    1. On a raw technology level both use the same technology building blocks, e.g. JavaScript: in Sling JS is used on the server-side for .esp templates and on the client-side in the case of JST templates. OpenSocial gadgets are coded in JS as well. Moreover, associated technologies like JSON, feeds and REST are supported by both.
    2. On a more conceptional level: As a spec that must work across a number of different social networks the majority of information that is accessible through the OpenSocial API is optional, i.e. it is up to the container if data is returned or not. This situation is a good fit to the unstructured, "Data First" approach that is enabled by Sling (respectively the underlying JCR).

    I would like to show Apache Shindig (Apache's OpenSocial container implementation) and CRX Quickstart (a bundle of Apache Sling and Day's JCR-compliant repository) working together in this blog post.

    Installation

    In this screencast I have shown how to install CRX Quickstart: double-click on its icon (CRX Quickstart is not available, yet, but it will be very soon). Strictly speaking, you do not need CRX Quickstart for the examples below. It all works with "plain" Sling as well.

    Installing Shindig is a tad more complicated and described on Shindig's web site. You need to check out, do a Maven build (I used revision 648157 for this example) and start Shindig's Jetty server on port 8080 with:

    mvn jetty:run-war

    Once you started Shindig hit /gadgets/files/samplecontainer/samplecontainer.html on http://localhost:8080. You should get a kind of gadget console that looks like this (click to enlarge):

     

    Shindig comes with an example implementation of a social network. By default it runs the "Hello World" example gadget located at:/gadgets/files/samplecontainer/examples/SocialHelloWorld.xml on http://localhost:8080.(btw Shindig comes with some example data so don't worry, if you have no friends - Shindig has some imaginary ones for you).

    Friends are Content

    What I would like do is: grab the gadget's viewer's friends and all the available data about them and store this data in the repository. For this purpose I have written a little gadget (see below) and saved it in my JCR repository at /apps/friends/friendsaver.html. By default the repository is running on port 7402, so when I point the gadget console to http://localhost:7402/apps/friends/friendsaver.html I get (click to enlarge):

     

    The gadget retrieves the viewer's friends and displays them in HTML. Moreover, in the background the viewer's data and the available friend data is posted to my repository. In the Content Explorer this looks like (click to enlarge):

     

    Hey, remember the "Everything is Content" mantra? Well, your imaginary friends are content, too.

    Please note that this works without setting up any schema or any other configuration of the repository. I ran it on an out-of-the-box CRX Quickstart (see also this screencast and this post about Data First). Only for the fields that are actually sent node properties are created.

    The Gadget Code

    The gadget is completely standard OpenSocial code, no surprises here. In onLoadFriends() the viewer's friends (variable viewerFriends) are iterated and displayed in HTML. For each opensocial.Person object the function createFriendNode() is called. In this function an HTTP POST request is sent to the repository that persists the person. Available opensocial.Person.Field data is sent as POST parameters (in the code only gender and first phone number are implemented) and thus persisted as node properties. I want to leverage the repository's hierarchy and store the friends as child nodes below the viewer (see David's model, rule 2). Here's the relevant snippet:

     /**  * Request for friend information.  */function getData() {      var req = opensocial.newDataRequest();  req.add(req.newFetchPersonRequest(opensocial.    DataRequest.PersonId.VIEWER), 'viewer');  req.add(req.newFetchPeopleRequest(opensocial.    DataRequest.Group.VIEWER_FRIENDS),    'viewerFriends');  req.send(onLoadFriends);}; /**  * Parses the response to the friend request  * @param {Object} dataResponse Friend      information that was requested.  */function onLoadFriends(dataResponse) {  var viewer = dataResponse.get('viewer').    getData();  var html = 'Friends of ' + viewer.    getDisplayName();   html += ':<br><ul>';  createFriendNode(viewer);  var viewerFriends = dataResponse.    get('viewerFriends').getData();  viewerFriends.each(function(person) {    html += '<li>'      + person.getDisplayName()      + '</li>';    createFriendNode(person, viewer);  });  html += '</ul>';  document.getElementById('message').    innerHTML = html;};  function createFriendNode(person, parent) {     var url = "http://localhost:7402/content/friends/";  if(parent) {    url += sanitizeId(parent.getId())+"/*";     } else {     url += "*";    }        var params = {};    params[gadgets.io.    RequestParameters.CONTENT_TYPE] =    gadgets.io.ContentType.TEXT;    params[gadgets.io.    RequestParameters.METHOD] =    gadgets.io.MethodType.POST;    var postParams = "";  postParams += 'name=' +    sanitizeId(person.getId()) + '&fullname=' +    person.getDisplayName();  if(person.getField(opensocial.Person.Field.    PHONE_NUMBERS)) postParams +=    ('&phone=' +    person.getField(opensocial.Person.Field.    PHONE_NUMBERS)[0].    getField(opensocial.Phone.Field.NUMBER))  if(person.getField(opensocial.Person.Field.    GENDER)) postParams += ('&gender=' +    person.getField(opensocial.Person.Field.    GENDER).getKey())  // I could add more fields here...        params[gadgets.io.RequestParameters.    POST_DATA] = postParams  gadgets.io.makeRequest(url, null, params);};    function sanitizeId(id) {  return id.replace(".", "_");   }gadgets.util.registerOnLoadHandler(getData);  

    Round-Tripping

    Now that the friends are stored in the repository each one has a URL. Displaying a friend in a simple HTML page can be done with e.g. server-side Javascript. Storing this file in the repository in /apps/friends/html.esp

    <html>  <body>    <h1><%= currentNode["fullname"] %></h1><ul><li>gender: <%= currentNode["gender"] %></li><li>phone: <%= currentNode["phone"] %></li></ul>  </body></html>

    will yield for the URL http://localhost:7402/content/friends/john_doe/jane_doe.html

    But this is only half the fun. It is much more interesting to retrieve the friends data in another OpenSocial gadget. This can easily be done without any repository-side code as Sling natively supports the json format. For example the URL http://localhost:7402/content/friends/john_doe/jane_doe.json will return this node in json format. Like that, we can easily access the friends nodes through a gadget containing this snippet:

    function makeCRXRequest() {    var params = {};    params[gadgets.io.RequestParameters.    CONTENT_TYPE] =    gadgets.io.ContentType.JSON;    var url =    "http://localhost:7402/content/friends/john_doe/"+    document.getElementById("person_name").value+    ".json";    gadgets.io.makeRequest(url, response, params);};function response(person) {    var html = "";  html += "name: " + person.data.fullname +    "<br/>";  html += "phone: " + person.data.phone +     "<br/>";  html += "gender: " + person.data.gender +    "<br/>";    document.getElementById('content_div').     innerHTML = html;};

    The gadget in action looks like this (click to enlarge)

     

    This little hack could be the starting point for a cross-social network phone book application.

    Final remarks

    I hope I could show that Sling and Shindig go really well together. Especially, being able to utilize the JCR repository as a backend without any coding on the repository side looks tempting to me. Maybe at one point Sling will even be able to run OpenSocial gadgets natively.

    In this post I concentrated on frontend intergration technologies. But OpenSocial will soon add a REST API next to its JS API. For Shindig the implementation of this REST API is likely to be Apache Abdera which uses JCR as an optional persistence storage. So there will be additional points of contact.

    Posted by Lars Trieloff JAN 09, 2008

    Posted in graph, news, open and social Comment 1

    The in the last two days we have seen two exciting news: Google and Facebook joining Dataportability.org and Google, IBM and Verisign agree to support OpenID. Together with Apache's Shindig, an open source implementation of Google's OpenSocial engine (see this Youtube Video for an interview with Brian McCallister who explains what Shindig and OpenSocial are) we are witnessing what will evolve to true social network portability.

    • With OpenID you are able to transfer your identity from one network to another. No need to enter the same information about yourself over and over again. You are even free to create multiple identities if you would like to separate some aspects of your digital life.
    • With DataPortability.org you are able to transfer the social graph from one network to another. This means you do not have to find your friends on each new network again and again.
    • And with OpenSocial have application portability. If there is a nice widget in one network that you would like to embed into another network - no problem with OpenSocial.

    As a consequence, the costs of joining yet another social network will shrink dramatically. As you have portability of identity, social graph and applications, you can start cherry-picking by joining many specialized networks, selecting the parts of the application that are most useful and aggregate them in your main OpenSocial container. But this also changes the rules of the game for social network vendors. You do not have to build up your user community from scratch, you do not have to convince your users to jump the high sign-up-and give-away-your-private-information barrier anymore, no you can create a highly specialized niche social network that serves only a small fraction of the population or that has only few, highly specific use-cases. This will lead to the generation of thousands of nice social networks, some standalone, some embedded into larger websites, but all will be able to interchange users, social graph and widgets with each other.

    As for the big players Google and Facebook: They will have to compete for the best platform for running these widgets. Facebook can benefit from the large number of existing Facebook applications and the really neat integration into the site from a usability point of view, but Google's hold on the desktop with Google Toolbar and the ability to display desktop widgets in the web and vice versa could lead to a completely new way to see the web.