eXo Social Reference Guide

exo.social.docs.refguide - 1.1.0-CR01

Authors

eXo Platform (eXo Platform)

Acknowledgements
1. Configuration
1.1. Spaces Template Configuration
2. TechnicalFoundations
2.1. Informations
2.1.1. Developing OpenSocial Gadgets
2.1.2. Introduction
2.1.3. Development Parameters
2.1.4. Using Webdav
2.1.4.1. Shindig configuration
2.1.4.2. Adding fields to the Person Object
2.2. Resources
2.3. Space Portlet Preferences
2.3.1. Save and get space context from a portlet
2.3.2. Why save portlet preference
2.3.3. How to save space context
3. Development
3.1. Activity streams
3.2. Opensocial
3.2.1. Gadget
3.2.1.1. Supported APIs
3.2.2. REST/RPC API
3.2.2.1. Configuring the security
3.2.2.2. Publishing an activity into a space
3.2.2.3. Tutorial
3.3. People
3.3.1. Identity
3.3.2. IdentityProvider
3.3.3. IdentityManager
3.3.4. Useful methods
3.3.5. Notifications
3.3.6. = Useful classes =
3.3.7. Invite a user
3.3.8. = Useful methods =
3.3.9. Notifications
3.3.10. = Useful Classes =
3.4. Additional Tutorials
3.4.1. Developing OpenSocial Gadgets
3.4.2. Introduction
3.4.3. Development Parameters
3.4.4. Using Webdav
3.4.5. How to extend the activities rendering
3.4.6. Objective
3.4.7. Requirements
3.4.8. Why would you need to do this ?
3.4.9. Writing an ActivityProcessor
3.4.10. Configuring the processor
4. Support
4.1. eXo Social Frequently Asked Questions
4.2. How to know the version of eXo Social I am using?
4.3. What to do if I'm behind a firewall?

Acknowledgements

This book is produced by the Wikbook tool. Wikbook is an open source project for converting wiki files into a set of docbook files.

Chapter 1. Configuration

[Note]Note

Needs to be updated

1.1. Spaces Template Configuration

In eXo Spaces we will be able to have two type of space (classic and webos spaces). This is for the classic mode (it's the only one implemented now).

For classic space we can pre-configure template, it mean that you can set up where your menu will be display or where your application will be display.

Here is an example of configuration file that display the menu on the left. The Application will be inserted in the container with the id Application:

<page>
  <owner-type></owner-type>
  <owner-id></owner-id>
  <name></name>
  <container id="SpacePage" template="system:/groovy/portal/webui/container/UITableColumnContainer.gtmpl">
    <container id="Menu" template="system:/groovy/portal/webui/container/UIContainer.gtmpl">
      <portlet-application>
        <portlet>
          <application-ref>space</application-ref>
          <portlet-ref>SpaceMenuPortlet</portlet-ref>
        </portlet>
        <access-permissions>*:/platform/users</access-permissions>
        <show-info-bar>false</show-info-bar>
      </portlet-application>
    </container>
    <container id="Application" template="system:/groovy/portal/webui/container/UIContainer.gtmpl">
    </container>
  </container>
</page>

In this example the outer container contains 2 inner containers: one with id is Menu for your Menu and another with id is Application contains your applications

If you want your menu will be in right and your application in left you can swap two containers declared position:

<page>
  <owner-type></owner-type>
  <owner-id></owner-id>
  <name></name>
  <container id="SpacePage" template="system:/groovy/portal/webui/container/UITableColumnContainer.gtmpl">
    <container id="Application" template="system:/groovy/portal/webui/container/UIContainer.gtmpl">
    <container id="Menu" template="system:/groovy/portal/webui/container/UIContainer.gtmpl">
      <portlet-application>
        <portlet>
          <application-ref>space</application-ref>
          <portlet-ref>SpaceMenuPortlet</portlet-ref>
        </portlet>
        <access-permissions>*:/platform/users</access-permissions>
        <show-info-bar>false</show-info-bar>
      </portlet-application>
    </container>
    </container>
  </container>
</page>

Here is the configure file in FishEye: http://fisheye.exoplatform.org/browse/social/trunk/extension/war/src/main/webapp/WEB-INF/conf/portal/template/pages/space/page.xml

In your tomcat, this configuration file is at $EXOTOMCAT/webapps/social-ext/WEB-INF/conf/portal/template/pages/space/page.xml

  • TODO UserProfileFields

Chapter 2. TechnicalFoundations

2.1. Informations

Table 2.1. 

Extension Name Status comments
analytics De-activated
auth-refresh Not Tested
caja Not Tested
core Not Tested
core.io Not Tested
dynamic-height Tested
echo Not Tested
flash Not Tested
locked-domain Not Tested
minimessage Not Tested
opensocial-0.6 Not Tested
opensocial-0.7 Tested
opensocial-0.8 Tested
opensocial-templates Not Tested
pubsub Not working
rpc Not Tested
setprefs Tested
settitle Tested
skins Not Tested
tabs Tested
target Not Tested
views Not Tested

2.1.1. Developing OpenSocial Gadgets

2.1.2. Introduction

eXo Social with OpenSocial container based on apache shindig supports OpenSocial capability. So we can develop gadgets that use OpenSocial API to request OpenSocial data or deploy opensocial gadget using tool supported by portal.

To develop your gadgets, you can use the tool that supported by portal.

2.1.3. Development Parameters

To be able to set this parameters, you have to be in the group "/platform/administrators". So by default, only the root user has access to this functionality. If you want to change this group, you need to change the configuration of the service GadgetRegistryService.

  • Set debug to true to not compress the javascript inside the gadget.

  • Set nocache to true to not cache the rendering of your gadget.

[Note]Note

The settings are saved *just after clicking* on the checkbox. But you need to *refresh the page* to see the parameters activated.

2.1.4. Using Webdav

[Note]Note

TODO, but you can look at this [demonstration|http://www.vimeo.com/2069512]

[Note]Note

not completed yet

This Howto explain how to configure the oAuth 2 legs scenario in openSocial.

For more information about this, you can have a look at this great article

2.1.4.1. Shindig configuration

2.1.4.1.1. Generating the certificates

To generate the key:

$ openssl req -newkey rsa:1024 -days 365 -nodes -x509 -keyout testkey.pem 
     -out testkey.pem -subj '/CN=mytestkey'
$ openssl pkcs8 -in testkey.pem -out oauthkey.pem -topk8 -nocrypt -outform PEM
2.1.4.1.2. Configuring the property file

Edit container.js and change the following parameter to point to your private key and your key name.

"gadgets.signingKeyFile" : "oauth.pem",
"gadgets.signingKeyName" : "oauthKey",

2.1.4.2. Adding fields to the Person Object

2.1.4.2.1. Modifications in the Java

If you need to add more information to the profile of a Person, you can extend ExoPersonImpl to add your fields. Your new fields will be automatically converted thanks to the POJO -> JSON or XML convertion.

The data of a person is pushed in the class ExoPeopleService. If you want to add some data to the ExoPersonImpl, you need to modify/extend this class.

After doing so, you should specify to eXo to use your implementation by extending SocialApiGuiceModule as it is done in ExoSocialApiGuiceModule to specify what of your class to use.

2.1.4.2.2. Modifications in the Javascript API
[Note]Note

TODO

2.2. Resources

2.3. Space Portlet Preferences

2.3.1. Save and get space context from a portlet

[Note]Note

Since eXo Social 1.0.1

2.3.2. Why save portlet preference

When working with space related portlet, we have make sure which space (space context) that portlet is working with to handle and display space's information. For example, SpaceActivityStreamPortlet has to know space context to display space's activity stream. Before (as of 1.0.0-GA), we rely on actual http address to gets space's url and then gets the current space, and that causes a bug here when edit that page node SOC-715.

2.3.3. How to save space context

If you want to register a portlet to be installed when creating a new space, write a portlet and set configuration in <tt>configuration.xml<tt> file of exo.social.component.space project. Just register your portlet here and it will be dynamically created a page with your portlet.

  <component>
    <key>org.exoplatform.social.space.SpaceService</key>
    <type>org.exoplatform.social.space.impl.SpaceServiceImpl</type>
    <init-params>
      <!-- Configure the applications to install in a space -->
      <values-param>
        <name>space.homeNodeApp</name>
        <value>SpaceActivityStreamPortlet</value>
      </values-param>
      <!-- Configure removable application or not <value>Application:removable</value> -->
      <values-param>
        <name>space.apps</name>
        <value>DashboardPortlet:true</value>
        <value>SpaceSettingPortlet:false</value>
        <value>UserListPortlet:true</value>
        <value>YourPortletName:true</value>
      </values-param>
    </init-params>
  </component>

Notice your portlet line configuration:

<value>YourPortletName:true</value>

true or false means that portlet can be uninstalled or mandatory from application settings for space.

If your portlet wants to save space context, register your portlet name in SpaceUtils (it should be configured via xml soon):


//SpaceUtils
static public String[] PORTLETS_SPACE_URL_PREFERENCE_NEEDED = {"SpaceActivityStreamPortlet", "SpaceSettingPortlet", "UserListPortlet","YourPortletName"};

That's it. Whenever creating a page containing your portlet, spaceUrl will be save as portlet preference.

1 How to get space context via portlet preference

Actually, we save a space's url to a portlet preference and by getting that space's url by using <tt>SpaceUtils</tt>:


  //SpaceUtils
  /**
   * Gets spaceName by portletPreference
   * @return space's url
   */
  static public String getSpaceUrl() {
    PortletRequestContext pcontext = (PortletRequestContext)WebuiRequestContext.getCurrentInstance();
    PortletPreferences pref = pcontext.getRequest().getPreferences();
    return pref.getValue(SPACE_URL, "");
  }

and then gets Space instance by SpaceService.


  //SpaceService
  /**
   * Get a space by its url
   * @param spaceUrl url of space
   * @return Space space with string url specified
   * @throws SpaceException
   */
  Space getSpaceByUrl(String spaceUrl) throws SpaceException;

Your portlet:


  //YourPortletName.java
  /**
   * constructor
   */
  public YourPortletName() throws Exception {
    Space space = getSpaceService().getSpaceByUrl(SpaceUtils.getSpaceUrl());
  }


  public SpaceService getSpaceService() {
    return getApplicationComponent(SpaceService.class);
  }

Chapter 3. Development

3.1. Activity streams

[Note]Note

Some changes for Social 1.0.1{/info}

eXo Social provides a way to share status updates and activity information for users as well as spaces (aka Activity Streams). With the API, you can customize the activities or publish new ones.

To manipulate activities, you will use the [ActivityManager|httprepository:exoplatform.org-service-local-repositories-public-archive-org-exoplatform-social-social-1.0.0-GA-social-1.0.0-GA-javadoc.jar-!-org-exoplatform-social-core-activitystream-ActivityManager.html]. To get an instance of this class, you will need to use the PortalContainer.

h2. Create an activity

There are two types of activities : activities for a user and activities for a space. The following examples will show you how to create an activity for each type.

h2. Publish an activity for a user

{code:java} import org.exoplatform.container.PortalContainer; import org.exoplatform.social.core.activitystream.ActivityManager; import org.exoplatform.social.core.activitystream.model.Activity; import org.exoplatform.social.core.identity.IdentityManager; import org.exoplatform.social.core.identity.impl.organization.OrganizationIdentityProvider; import org.exoplatform.social.core.identity.model.Identity;

/

  • Created by The eXo Platform SAS

  • Author : eXoPlatform

  • exo@exoplatform.com

  • Jun 25, 2010 */ .....

public void createActivityForUser() { String username = "zun"; Get current container PortalContainer container = PortalContainer.getInstance();

Get IdentityManager to handle identity operation IdentityManager identityManager = (IdentityManager) container.getComponentInstance(IdentityManager.class);

Get ActivityManager to handle activity operation ActivityManager activityManager = (ActivityManager) container.getComponentInstanceOfType(ActivityManager.class);

Get existing user or create a new one try { Identity userIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, username);

Create new activity for this user Activity activity = new Activity(); activity.setUserId(userIdentity.getId()); activity.setTitle("Hello World!"); Save activity into JCR using ActivityManager activityManager.saveActivity(activity); } catch (Exception e) { TODO Auto-generated catch block e.printStackTrace(); } } {/code}

h2. Publish an activity for a space

{code:java} import org.exoplatform.container.PortalContainer; import org.exoplatform.social.core.activitystream.ActivityManager; import org.exoplatform.social.core.activitystream.model.Activity; import org.exoplatform.social.core.identity.IdentityManager; import org.exoplatform.social.core.identity.impl.organization.OrganizationIdentityProvider; import org.exoplatform.social.core.identity.model.Identity; import org.exoplatform.social.space.Space; import org.exoplatform.social.space.SpaceException; import org.exoplatform.social.space.SpaceService; import org.exoplatform.social.space.impl.SpaceIdentityProvider;

...

public void createActivityForSpace() { make sure a space with name "mySpace" is created. String spaceName = "mySpace"; String username = "zun"; Get current container PortalContainer container = PortalContainer.getInstance();

Get IdentityManager to handle identity operation IdentityManager identityManager = (IdentityManager) container.getComponentInstance(IdentityManager.class);

Get ActivityManager to handle activity operation ActivityManager activityManager = (ActivityManager) container.getComponentInstanceOfType(ActivityManager.class);

Get SpaceService to handle space operation SpaceService spaceService = (SpaceService) container.getComponentInstanceOfType(SpaceService.class); try { Space space = spaceService.getSpaceByName(spaceName); if (space != null) { Get space identity via SpaceIdentityProvider Identity spaceIdentity = identityManager.getOrCreateIdentity(SpaceIdentityProvider.NAME, spaceName); Get identity instance of the user who wants to create activity Identity userIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, username); Create new activity for this space Activity activity = new Activity(); activity.setUserId(userIdentity.getId()); activity.setTitle("An activity for space"); activityManager.saveActivity(spaceIdentity, activity); } } catch (SpaceException e) { TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { TODO Auto-generated catch block e.printStackTrace(); } } {/code}

h2. Useful functions

  • [ActivityManager#getActivity|httprepository:exoplatform.org-service-local-repositories-public-archive-org-exoplatform-social-social-1.0.0-GA-social-1.0.0-GA-javadoc.jar-!-org-exoplatform-social-core-activitystream-ActivityManager.html]

  • [ActivityManager#getActivities|httprepository:exoplatform.org-service-local-repositories-public-archive-org-exoplatform-social-social-1.0.0-GA-social-1.0.0-GA-javadoc.jar-!-org-exoplatform-social-core-activitystream-ActivityManager.html]

  • [ActivityManager#saveActivity|httprepository:exoplatform.org-service-local-repositories-public-archive-org-exoplatform-social-social-1.0.0-GA-social-1.0.0-GA-javadoc.jar-!-org-exoplatform-social-core-activitystream-ActivityManager.html]

  • [ActivityManager#saveComment|httprepository:exoplatform.org-service-local-repositories-public-archive-org-exoplatform-social-social-1.0.0-GA-social-1.0.0-GA-javadoc.jar-!-org-exoplatform-social-core-activitystream-ActivityManager.html]

  • [ActivityManager#saveLike|httprepository:exoplatform.org-service-local-repositories-public-archive-org-exoplatform-social-social-1.0.0-GA-social-1.0.0-GA-javadoc.jar-!-org-exoplatform-social-core-activitystream-ActivityManager.html]

  • [ActivityManager#removeLike|httprepository:exoplatform.org-service-local-repositories-public-archive-org-exoplatform-social-social-1.0.0-GA-social-1.0.0-GA-javadoc.jar-!-org-exoplatform-social-core-activitystream-ActivityManager.html]

  • [ActivityManager#getComments|httprepository:exoplatform.org-service-local-repositories-public-archive-org-exoplatform-social-social-1.0.0-GA-social-1.0.0-GA-javadoc.jar-!-org-exoplatform-social-core-activitystream-ActivityManager.html]

Creating a custom activity processor =

Activity processor is used for modifying the content of activities before they are responsed and rendered at client's browser. For example, we will create an activity processor for replacing all the texts representing the smile face ":-)" in the activity title by the smiley icons.

Firstly, we will create the SmileyProcessor class by extending the BaseActivityProcessorPlugin

{code language="java"} package org.exoplatform.social.core.activitystream;

public class SmileyProcessor extends BaseActivityProcessorPlugin { public SmileyProcessor(InitParams params) { super(params); }

String smiley = "<img src="http://www.tombraider4u.com/pictures/smiley.gif"/>";

public void processActivity(Activity activity) { String title = activity.getTitle(); activity.setTitle(title.replaceAll(":- )", smiley)); } } {/code}

And then, we have to register this processor by adding some XML configuration into the project configuration file (configuration.xml)

{code:language="xml"} <component> <key>org.exoplatform.social.core.activitystream.ActivityManager</key> <type>org.exoplatform.social.core.activitystream.ActivityManager</type> <component-plugins> <component-plugin> <name>SmileyProcessor</name> <set-method>addProcessorPlugin</set-method> <type>org.exoplatform.social.core.activitystrea.SmileyProcessor</type> <init-params> <values-param> <name>priority</name> <value>1</value> </values-param> </init-params> </component-plugin> </component-plugins> </component> {/code}

"init-params" contains all the key-value data which a processor will use to initialize. At the above config, priority value indicates the order that this processor will be used. So with '1' value, this processor will be used before all remaining processors with lower priority.

h2. Publish an rss feed with feedmash

It's really easy to publish an rss feed to a space's activity stream. eXo Social already provides FeedmashJobPlugin for publishing rss feeds. As you can see in project exo.social.extras.feedmash, there are JiraFeedConsumer and HudsonFeedConsumer samples to post eXo Social project's feeds (jira and hudson) to a pre-defined space: exosocial in a specific portal container: socialdemo as in the configuration file:

{code:language="xml"} <external-component-plugins> <target-component>org.exoplatform.services.scheduler.JobSchedulerService</target-component> <component-plugin> <name>RepubSocialJiraActivityJob</name> <set-method>addPeriodJob</set-method> <type>org.exoplatform.social.feedmash.FeedmashJobPlugin</type> <description></description> <init-params> <properties-param> <name>mash.info</name> <property name="feedURL" value="http://jira.exoplatform.org/plugins/servlet/streams?key=SOC"/> <property name="categoryMatch" value="resolved|created"/> <property name="targetActivityStream" value="space:exosocial"/> <property name="portalContainer" value="socialdemo"/> </properties-param> <properties-param> <name>job.info</name> <description>save the monitor data periodically</description> <property name="jobName" value="JIRAFeedConsumer"/> <property name="groupName" value="Feedmash"/> <property name="job" value="org.exoplatform.social.feedmash.JiraFeedConsumer"/> <property name="repeatCount" value="0"/> <property name="period" value="60000"/> <property name="startTime" value="+45"/> <property name="endTime" value=""/> </properties-param> </init-params> </component-plugin> <component-plugin> <name>WatchSocialBuildStatus</name> <set-method>addPeriodJob</set-method> <type>org.exoplatform.social.feedmash.FeedmashJobPlugin</type> <description></description> <init-params> <properties-param> <name>mash.info</name> <property name="feedURL" value="http://builder.exoplatform.org/hudson/view/social/job/social-trunk-ci/rssAll"/> <property name="targetActivityStream" value="space:exosocial"/> <property name="portalContainer" value="socialdemo"/> </properties-param> <properties-param> <name>job.info</name> <description>save the monitor data periodically</description> <property name="jobName" value="HudsonFeedConsumer"/> <property name="groupName" value="Feedmash"/> <property name="job" value="org.exoplatform.social.feedmash.HudsonFeedConsumer"/> <property name="repeatCount" value="0"/> <property name="period" value="60000"/> <property name="startTime" value="+100"/> <property name="endTime" value=""/> </properties-param> </init-params> </component-plugin> </external-component-plugins> {/code}

When running eXo Social, login with http://localhost:8080/socialdemo and create a space named "exosocial". Done, all the feeds from jira and hudson for Social project will be automatically published to exosocial space.

3.2. Opensocial

eXo Social is implementing the OpenSocial standard. So you can integrate OpenSocial Gadget in your dashboard and use the RPC or REST API to access to the social data.

3.2.1. Gadget

Gadgets are web-based software components based on HTML, CSS, and JavaScript. They allow developers to easily write useful web applications that work anywhere on the web without modification. To know more, we suggest some links for detail information :

Gadgets Specification

OpenSocial Core Gadget Specification 10

After getting acquainted with Gadget concept, we enter into the detail on how to create an opensocial gadget. However, the tutorials are done greatly in Opensocial official site so we refer you to read these tutorials at that website

We only note that in Opensocial gadgets only work in the dashboard in eXo Social.

3.2.1.1. Supported APIs

As we have said above, eXo Social is implementing the OpenSocial standard. So every eXo Social implementations apply the Opensocial Specification generally or Apache Shindig specifically. Therefore, eXo Social uses and extends Apache Shindig APIs to compatible with the common Opensocial APIs which is supported by other big social networks like Ning, Hi5, Orkut ...

To get more detail about Supported APIs, we refer you to read Opensocial Specs

3.2.2. REST/RPC API

If your eXo social server is running on http://localhost:8080/ the address of the API will be:

REST API: http://localhost:8080/social/social/rest

RPC API: http://localhost:8080/social/social/rpc

To learn what you can do with this APIs, have a look at the specification. If you are developing in Java, you can use the opensocial-java-client

3.2.2.1. Configuring the security

If you are using opensocial, there is good chance you are going to need to configure the oAuth authentication. To do this, you need to edit the configuration to add you oAuth key.

Edit the file: gatein/conf/portal/portal/configuration.xml and add this component:

        <component>
                <key>org.exoplatform.social.opensocial.oauth.ServiceProviderStore</key>
                <type>org.exoplatform.social.opensocial.oauth.ServiceProviderStore</type>

                <init-params>
                        <properties-param>
                                <name>grails-book-flow</name>
                                <description>consmer key and secret for sample oauth provider. </description>
                                <property name="consumerKey" value="YOUR_KEY_HERE" />

                                <property name="sharedSecret" value="YOUR_SECRET_KEY_HERE" />
                        </properties-param>

                </init-params>
        </component>

The consumerKey and sharedSecret are the key that need to be shared with the application that is doing the request.

3.2.2.2. Publishing an activity into a space

eXo Social added this functionality that is not available in the standard opensocial API. You can publish activities into a space using the opensocial API.

To do this, instead of publishing your activity to the group @self as usual, publish it to the group "space:spaceID" or "space:spaceName".

Using the opensocial java library and groovy, your code will look like this:

      def client = getOpenSocialClient()

      //we create our new activity
      Activity activity = new Activity()
      activity.title = "BookFlow Purchase"
      activity.body = "xx puchased the book xxx"

      //We prepare the request that will create the activity
      Request request = ActivitiesService.createActivity(activity);
      //We specify that the creation of this new activity is for the space bookflow
      request.groupId = "space:bookflow";

      client.send(request);

As you can see in this example, we set the groupId to "space:bookflow", bookflow being the name of our space.

3.2.2.3. Tutorial

3.3. People

eXo Social provides a way to add profile informations, relationships and connections between users: People. With the eXo People API, profile informations and relationship can be easily managed and customized.

3.3.1. Identity

3.3.2. IdentityProvider

Creating your Identity Provider allows you to integrate people outside of your portal (for exemple customers) into your social network without having to create a portal account. You can also use this to populate the profile with data coming from other systems. Here is an example :

class SampleIdentityProvider extends OrganizationIdentityProvider{
  public SampleIdentityProvider(OrganizationService organizationService) {
    super(organizationService);
  }

  @Override
  public void populateProfile(Profile profile, User user) {
    profile.setProperty(Profile.FIRST_NAME, "this is first name");
    profile.setProperty(Profile.LAST_NAME, "this is last name");
    profile.setProperty(Profile.USERNAME, "this is user name");
    profile.setProperty(Profile.URL, "/path/to/profile/");
  }
}

In this example, we created a SampleIdentityProvider class extending OrganizationIdentityProvider which is the IdentityProvider used to connect to the portal user's base. In this class, we overrided the populateProfile method and added some dummy data in the profile fields.

3.3.3. IdentityManager

The IdentityManager is the service used to manipulate the identity operations like creating, getting, deleting or finding a profile. We can get the IdentityManager via the ExoContainer. The following code will show how to get an IdentityManager instance and create a basic identity instance :

import org.exoplatform.container.ExoContainer;
import org.exoplatform.container.ExoContainerContext;
import org.exoplatform.social.core.identity.IdentityManager;
import org.exoplatform.social.core.identity.impl.organization.OrganizationIdentityProvider;
import org.exoplatform.social.core.identity.model.Identity;

//......

String containerName = "portal";
String username = "zun";

//get container to get other registered components
ExoContainer container = ExoContainerContext.getContainerByName(containerName);

//get IdentityManager to handle identity operation
IdentityManager identityManager = (IdentityManager) container.getComponentInstanceOfType(IdentityManager.class);

//get ActivityManager to handle activity operation
ActivityManager activityManager = (ActivityManager) container.getComponentInstanceOfType(ActivityManager.class);

//create new user with name Zun
Identity userIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, username);

3.3.5. Notifications

The People API provides some notification interfaces which programmers can implement in order to create their own handlers for notifications like notifications() for profile modifications(ProfileListenerPlugin]) or for relationship changes(RelationshipListenerPlugin]). The following example will guide you through implementing one of these interfaces and show you how to configure this plugin.

We will create the class ProfileLoggerListener. Its tasks is to log all profile modifications of the systems. The abstract class ProfileListenerPlugin provides us the interface to implement this method.

import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.social.core.identity.lifecycle.ProfileListenerPlugin;
import org.exoplatform.social.core.identity.spi.ProfileLifeCycleEvent;


public class ProfileLoggerListener extends ProfileListenerPlugin{
  private static final Log logger = ExoLogger.getExoLogger(ProfileLoggerListener.class);
  @Override
  public void avatarUpdated(ProfileLifeCycleEvent event) {
    logger.info("@" + event.getUsername() + " profile has updated his basic profile info.");
  }

  @Override
  public void basicInfoUpdated(ProfileLifeCycleEvent event) {
    logger.info("@" + event.getUsername() + " profile has updated his basic profile info.");
  }

  @Override
  public void contactSectionUpdated(ProfileLifeCycleEvent event) {
    logger.info("@" + event.getUsername() + " profile has updated his contact info.");
  }

  @Override
  public void experienceSectionUpdated(ProfileLifeCycleEvent event) {
    logger.info("@" + event.getUsername() + " profile has an updated experience section.");
  }

  @Override
  public void headerSectionUpdated(ProfileLifeCycleEvent event) {
    logger.info("@" + event.getUsername() + " has updated his header info.");
  }
}

After creating the ProfileLoggerListener class, we have to add some configurations for this class to the configuration.xml :

<external-component-plugins>
  <target-component>org.exoplatform.social.core.identity.IdentityManager</target-component>
  <component-plugin>
    <name>ProfileLoggerListener</name>
    <set-method>addProfileListener</set-method>
    <type>path.to.ProfileLoggerListener</type>
  </component-plugin>
</external-component-plugins>

Similarly, you can apply the above steps to implement the RelationshipListenerPlugin for relationship notifications.

3.3.6. = Useful classes =

= Relationship =

Relationship is the bridge between two identities in eXo Social. There are many types of relationships defined in the Relationship class. With these types, a user can invite another user, confirm invitations or remove relationship.

3.3.7. Invite a user

The following code will show how to invite a user from a user :

import org.exoplatform.container.ExoContainer;
import org.exoplatform.container.ExoContainerContext;
import org.exoplatform.social.core.identity.IdentityManager;
import org.exoplatform.social.core.identity.impl.organization.OrganizationIdentityProvider;
import org.exoplatform.social.core.identity.model.Identity;
import org.exoplatform.social.core.relationship.Relationship;
import org.exoplatform.social.core.relationship.RelationshipManager;

public void inviteUser() throws Exception {
  String containerName = "portal";
  ExoContainer container = ExoContainerContext.getContainerByName(containerName);

  IdentityManager identityManager = (IdentityManager) container.getComponentInstanceOfType(IdentityManager.class);

  Identity invitedIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, "Hoat");
  String invitedUserId = invitedIdentity.getId();

  String currUserId = "Zun";
  Identity currentIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME,  currUserId);

  RelationshipManager relationshipManager = (RelationshipManager) container.getComponentInstanceOfType(RelationshipManager.class);
  Relationship relationship = relationshipManager.invite( currentIdentity, invitedIdentity);
}

3.3.9. Notifications

Let's take a look at relationship notifications(RelationshipListenerPlugin). The following example will show you how to implement one of these interfaces and how to configure this plugin. The following step is similar to the Profile notifications implementation.

import org.exoplatform.social.core.relationship.Relationship;
import org.exoplatform.social.core.relationship.lifecycle.RelationshipListenerPlugin;
import org.exoplatform.social.relationship.spi.RelationshipEvent;

public class RelationshipLoggerListener extends RelationshipListenerPlugin{
  private static final Log logger = ExoLogger.getExoLogger(RelationshipLoggerListener.class);

  @Override
  public void confirmed(RelationshipEvent event) {
    String[] names = getUserNamesFromEvent(event);
    logger.info(names[0] +" confirmed the invitation of "+ names[1]);
  }

  @Override
  public void ignored(RelationshipEvent event) {
    String[] names = getUserNamesFromEvent(event);
    logger.info(names[0] +" ignored the invitation of "+ names[1]);
  }

  @Override
  public void removed(RelationshipEvent event) {
    String[] names = getUserNamesFromEvent(event);
    logger.info(names[0] +" removed the relationship with "+ names[1]);
  }

  private String[] getUserNamesFromEvent(RelationshipEvent event){
    Relationship relationship = event.getPayload();

    Identity id1 = relationship.getIdentity1();
    Identity id2 = relationship.getIdentity2();

    String user1 = "@" + id1.getRemoteId();
    String user2 = "@" + id2.getRemoteId();

    return new String[]{user1, user2 };
  }
}

After creating the RelationshipLoggerListener class, we have to add some configurations for this class to the configuration.xml :

<external-component-plugins>
  <target-component>org.exoplatform.social.core.relationship.RelationshipManager</target-component>
  <component-plugin>
    <name>RelationshipLoggerListener</name>
    <set-method>addListenerPlugin</set-method>
    <type>classpath.of.your.RelationshipLoggerListener</type>
  </component-plugin>
</external-component-plugins>

3.3.10. = Useful Classes =

[Note]Note

The UWC detected velocity templates not surrounded by pre blocks in this page. If you would like it to attempt to convert it, re-run the conversion with the following converter from conf/converter.xwiki.properties commented out: Xwiki.0060.clean-velocity.class=com.atlassian.uwc.converters.xwiki.VelocityCleaner

[Note]Note

Some changes updated for eXo Social 1.0.1

3.4. Additional Tutorials

3.4.1. Developing OpenSocial Gadgets

3.4.2. Introduction

eXo Social with OpenSocial container based on apache shindig supports OpenSocial capability. So we can develop gadgets that use OpenSocial API to request OpenSocial data or deploy opensocial gadget using tool supported by portal.

To develop your gadgets, you can use the tool that supported by portal.

3.4.3. Development Parameters

To be able to set this parameters, you have to be in the group "/platform/administrators". So by default, only the root user has access to this functionality. If you want to change this group, you need to change the configuration of the service GadgetRegistryService.

  • Set debug to true to not compress the javascript inside the gadget.

  • Set nocache to true to not cache the rendering of your gadget.

[Note]Note

The settings are saved *just after clicking* on the checkbox. But you need to *refresh the page* to see the parameters activated.

3.4.4. Using Webdav

[Note]Note

TODO, but you can look at this [demonstration|http://www.vimeo.com/2069512]

3.4.5. How to extend the activities rendering

3.4.6. Objective

In this article you will learn how you can implement a preprocessor for activities rendering.

3.4.7. Requirements

You need to be familiar with the eXo Kernel component model and its xml configuration. You also need be able to program in java.

3.4.8. Why would you need to do this ?

An simplistic activity is made of simple text. We have created an extension point at the level of activities renderting for two cases :

  • support more html tags

  • support @mentions

But you may want to support a special syntax like :

  • #hashtags to feel like twitter

  • smileys to look like skype

  • Markdown to be as cool as Buzz ;-)

You can imagine more sophisticated processing. And not only text-related because a processor actually has full access to the Activity. So you can very well process based on the owner, the app, mediaitem, etc..

3.4.9. Writing an ActivityProcessor

eXo Social let's you pre-process an activity before it is returned by the ActivityManager. To do this you simply need to implement the interface ActivityProcessor :

/**
 * An activity processor is responsible to pre-process an activity before it is returned by the {@link ActivityManager}
 */
public interface ActivityProcessor {

  /**
   * Process an activity
   * @param activity the activity. It can be modified
   */
  void processActivity(Activity activity);

  /**
   * Priority of this processor.
   * All activity processors will be executed in ascending priority order
   * @return
   */
  int getPriority();

}

For example let's implement a SmileyProcessor that will replace text smileys by icons :

public class SmileyProcessor implements ActivityProcessor {

  String smiley =  "<img src='/images/smiley.gif'/>";

  public void processActivity(Activity activity) {
    String title = activity.getTitle();
     activity.setTitle(title.replaceAll(":-\)", smiley));
  }

  public int getPriority() {
    return 100;
  }

}

3.4.10. Configuring the processor

Now that you have a nice procesor you need to hook it to the system. At runtime, processors can be attached to the ActivityManager via the method ActivityManageraddProcessor(ActivityProcessor processor).

But there is also a component plugin hook for it : public void addProcessorPlugin(BaseActivityProcessorPlugin plugin)

So to make your processor easy to hook, you simply need to let him extend the BaseActivityProcessorPlugin.

public class SmileyProcessor extends BaseActivityProcessorPlugin {

  String smiley =  "<img src='/images/smiley.gif'/>";

  public SmileyProcessor(InitParams params) {
    super(params);
  }

  public void processActivity(Activity activity) {
    String title = activity.getTitle();
      activity.setTitle(title.replaceAll(":-\)", smiley));
  }
}

It will have the additional benefit to make the priority field configurable so you don't need to implement getPriorty().

Then your processor can be configured as a component plugi like this :

  <external-component-plugins>
    <target-component>org.exoplatform.social.core.activitystream.ActivityManager</target-component>
    <component-plugin>
      <name>SmileyProcessor</name>
      <set-method>addProcessorPlugin</set-method>
      <type>org.example.SmileyProcessor</type>
      <init-params>
        <value-param>
          <name>priority</name>
          <description>priority of this processor (lower are executed first)</description>
          <value>2</value>
        </value-param>
      </init-params>
    </component-plugin>
  </external-component-plugins>

Restart, place the smiley gif on the server and you should see something like that :

Externalresources OfficialOpenSocialDeveloper'sGuide onGoogleCode HowtodeployaremoteOpenSocialGoogleGadgetmadewithGWTineXo by LaurentBois

  • Also check this list of useful RSS feeds to follow.

[Note]Note

The UWC detected velocity templates not surrounded by pre blocks in this page. If you would like it to attempt to convert it, re-run the conversion with the following converter from conf/converter.xwiki.properties commented out: Xwiki.0060.clean-velocity.class=com.atlassian.uwc.converters.xwiki.VelocityCleaner

Chapter 4. Support

4.1. eXo Social Frequently Asked Questions

4.2. How to know the version of eXo Social I am using?

Go to your $TOMCATHOME/lib and search for the library starting by "exo.social", the version number is at the end of the file name. For example: "exo.social.component.opensocial-1.0-alpha1.jar", the version number is "1.0-alpha1".

If the version number ends by SNAPSHOT, it means that this version has been built against a development version. To know what svn version corresponds to this jar:

  • Unzip the jar

  • Open the file "META-INF/MANIFEST.MF"

  • In this file you will see the svn version, it's the line starting by SCM-Revision (ex: SCM-Revision: 25023)

4.3. What to do if I'm behind a firewall?

Some OpenSocial gadgets needs to have access to internet. You can copy this gadgets to your local repository, setup your proxy or simply not use it. No OpenSocial gadget is required to have eXo Social working. To setup your proxy you should setup the proxy of your appserver :

-Dhttp.proxyHost=yourproxy.your.domain -Dhttp.proxyPort=80