(Quick Reference)

Facebook SDK Plugin - Reference Documentation

Authors: Benoit Hediard

Version: 2.3.0

1 Introduction

The Facebook Platform is a set of APIs that make your application more social. Read more about integrating Facebook with your web site on the Facebook developer site.

This project contains the open source Grails Facebook SDK Plugin that allows you to integrate the Facebook Platform on a website/app powered by Grails .

This plugin is a port of the official Facebook PHP SDK to Grails 2.0 .

It supports the latest OAuth2.0 authentication (required since October 1st 2011).

Grails Facebook SDK Plugin provides the following Grails artefacts:

Latest releases

WARNING: Since V2.3.0, Facebook Graph API v2.3 will be used. Make sure that your app is compatible with v2.3 upgrade .

Use grails.plugin.facebooksdk.apiVersion = 'v2.2' to override default behaviour.

Please check FacebookGraphClient doc for more info.

  • 2015-05-04 V2.3.0 : v2.3 Facebook Graph API support (from now on, used by default) + RestFB dependency updated to 1.10.1
  • 2015-01-08 V2.2.1 : minor bug fix for token for business parsing
  • 2014-11-16 V2.2.0 : v2.2 Facebook Graph API support (from now on, used by default) + RestFB dependency updated to 1.7.0
  • 2014-10-08 V2.1.0 : v2.1 Facebook Graph API support + RestFB dependency updated to 1.6.16
  • 2014-07-28 V2.0.0 : v2.0 Facebook Graph API support
  • 2014-05-23 V0.6.4 : version attribute added to initJS tag to choose API version for Facebook JS SDK (v1.0 or v2.0)
  • 2014-05-19 V0.6.3 : customSelector attribute and config param added to tag lib
  • 2014-04-28 V0.6.2 : bug fix in FacebookContext (use @PostConstruct instead of InitializingBean) to solve reloading issue since Grails 2.3.7 (GRAILS-7799)
  • 2014-04-04 V0.6.1 : TagLib update (scripts are only included once in a page even if tags are used more than once)
  • 2014-04-02 V0.6.0 : Resources Grails Plugin dependencies removed (to be compatible with Asset Pipeline Grails Plugin)
  • 2014-02-12 V0.5.0 : RestFB dependency updated to 1.6.14
  • 2013-12-06 V0.4.13 : bug fix in picture tag (secure mode)
  • 2013-06-05 V0.4.12 : bug fix in sendLink tag (callback attribute)
  • 2013-05-28 V0.4.11 : tokenRetrievalRetryCount config parameter added + doc update
  • 2013-04-03 V0.4.10 : RestFB dependency updated to 1.6.12 + bug fix token exchange
  • 2013-03-19 V0.4.9 : bug fix token exchange from code with concurrent requests (thanks to elegorod )
  • 2013-01-03 V0.4.8 : bug fix token expiration time handling (in Facebook Page tabs)
  • 2012-12-20 V0.4.7 : bug fix resources definition
  • 2012-12-07 V0.4.6 : bug fix in invite/publish/send tags (encode text as HTML in attributes)
  • 2012-12-05 V0.4.5 : bug fix in FacebookSignedRequest appData property
  • 2012-11-15 V0.4.4 : for photo/video publishing, FacebookGraphClient publish method accepts now InputStream argument type (instead of FileInputStream only)
  • 2012-10-29 V0.4.3 : tag lib improvements: channel integration (initJS tag and FacebookSdkController created), resources plugin integration (FacebookSdkResources created)
  • 2012-10-10 V0.4.2 : bug fix in batch responses error handling
  • 2012-09-25 V0.4.1 : bug fix in server side OAuth redirect
  • 2012-10-25 V0.4.0 : complete refactoring to improve SDK architecture (FacebookContext implemented) and multiple Facebook apps support added
  • 2012-09-03 V0.3.6 : RestFB dependency updated to 1.6.10, proxyHost and proxyPort added to config and signedRequest added to filter facebook map
  • 2012-08-24 V0.3.5 : proxyHost and proxyPort parameters added to Graph/Rest client (thanks to Eduard Martini)
  • 2012-07-23 V0.3.4 : bug fix in facebookAppService
  • 2012-07-17 V0.3.3 : readTimeout parameter added to Graph/Rest client + upgrade to Grails 2.1 with wrapper
  • 2012-06-12 V0.3.2 : bug fix in filter and plugin config
  • 2012-06-12 V0.3.1 : package grails.plugins.facebooksdk renamed to grails.plugin.facebooksdk
  • 2012-06-08 V0.3.0 : new documentation based on GDoc, FacebookRestClient added + bug fixes

Bugs

To report any bug, please use the project Issues section on GitHub.

Demo app

If you want to quickly run the SDK on a demo app, you can download Facebook SDK Grails - Demo .

About

The Grails Facebook SDK Plugin is not an official Facebook SDK such as Javascript , PHP , iOS and Android SDKs .

It is developed by AgoraPulse and licensed under the Apache Licence, Version 2.0 .

2 Configuration

Installation

Declare the plugin dependency in BuildConfig.groovy file, as shown here:

grails.project.dependency.resolution = {
		inherits("global") { }
		log "info"
		repositories {
				//your repositories
		}
		dependencies {
				//your regular dependencies
		}
		plugins {
				//here go your plugin dependencies
				runtime ':facebook-sdk:2.3.0'
		}
}

Single Facebook app

Create a Facebook app on Facebook Developers , in order to get your own app ID and app secret.

Add your app settings in Config.groovy:

// Required
grails.plugin.facebooksdk.app.id = {APP_ID}
grails.plugin.facebooksdk.app.permissions = {APP_PERMISSIONS} // Ex. ['email','user_photos']
grails.plugin.facebooksdk.app.secret = {APP_SECRET}
// Optional, default proxy config for Facebook Graph Client API calls
// grails.plugin.facebooksdk.proxyHost = {PROXY_HOST}
// grails.plugin.facebooksdk.proxyPort = {PROXY_PORT}

Or

grails {
    plugin {
        facebooksdk {
            app = [
                id: APP_ID,
                permissions: APP_PERMISSIONS,
                secret: APP_SECRET
            ]
        }
    }
}

Multiple Facebook apps

Since V0.4, it is possible do define multiple apps in Config.groovy:

grails {
    plugin {
        facebooksdk {
            appIdParamName = 'app_id' // Default app selection param name
            apps = [
                [
                    id: {APP_ID1},
                    permissions: {APP_PERMISSIONS1}, // Ex. ['email','user_photos']
                    secret: {APP_SECRET1}
                ],
                [
                    id: {APP_ID2},
                    permissions: {APP_PERMISSIONS2}, // Ex. ['email','user_photos']
                    secret: {APP_SECRET2}
                ],
                …
            ]
        }
    }
}

For each request, you must define app_id in params (by appending ?app_id={APP_ID} to query string) in order to specify which Facebook app setting to use.

Note: to define another parameter name, set config param grails.plugin.facebooksdk.appIdParamName.

You can also associate a Facebook app to a default controller by adding controller name in each app settings :

grails {
    plugin {
        facebooksdk {
            apps = [
                [
                    controller: {CONTROLLER_NAME1},
                    id: {APP_ID1},
                    permissions: {APP_PERMISSIONS1},
                    secret: {APP_SECRET1}
                ],
                [
                    controller: {CONTROLLER_NAME2},
                    id: {APP_ID2},
                    permissions: {APP_PERMISSIONS2},
                    secret: {APP_SECRET2}
                ],
                …
            ]
        }
    }
}

For example, let's say you have two apps with two controllers: QuizController and SweepstakesController.

Add controller: 'quiz' in quiz app settings and controller: 'sweepstakes' in sweepstakes app settings.

To access your quiz app, use http://localhost:8080/my-app/quiz .

To access your sweepstakes app, use http://localhost:8080/my-app/sweepstakes .

If no app is found based on app_id params and controller name, default single app grails.plugin.facebooksdk.app settings will be used (if defined).

Graph API Version

By default, latest Graph API v2.3 will be used. You can override default settings with apiVersion config parameter :

grails.plugin.facebooksdk.apiVersion = 'v2.2'

Session replication and authorization code

When using distributed session replication, if authorization code is used by two concurrent processes, one of the process will received an error from Facebook and the session will be invalidated. You can add the tokenRetrievalRetryCount config parameter to try to extract token from session several times before invalidating the session (the time for the first process to put the token received by Facebook into session scope).

grails.plugin.facebooksdk.tokenRetrievalRetryCount = 10

By default, this parameter is usually not required and is disabled by default.

Controllers scope

Since FacebookContext should be instantiated at each request, you must use prototype scope for your Controllers (since Grails 2.3, generated Config.groovy defines singleton as default scope).

grails.controllers.defaultScope = 'prototype'

JQuery custom selector

Default jQuery selector is $, if you require another one, you can define it globally in your grails-app/conf/Config.groovy :

grails.plugin.facebooksdk.customSelector = 'jQuery'

3 Facebook Context

The plugin can automatically create a facebookContext Spring bean, with all the required info:
  • current Facebook signed request (if defined).
  • current Facebook app,
  • current Facebook user (if authenticated),
  • current Facebook page (if running in a facebook page tab),

To automatically inject it in your controllers, add the facebookContext property.

MyController {

FacebookContext facebookContext … def index() { long userId = facebookContext.user.id … } }

Note: facebookContext is a request scope bean and should only be used in Grails controllers (or other request scope beans).

If you want to access facebookContext from a non request scope bean (ex.: singleton filters), you should use facebookContextProxy (AOP scoped proxy).

MyFilter {

FacebookContext facebookContextProxy … def index() { long userId = facebookContextProxy.user.id … } }

Signed Request

The context gives you access to the current signed request sent to your app by Facebook :

  • on apps.facebook.com or in a page tab, through signed_request params posted to the app iframe,
  • on external sites (web or mobile) through Facebook JS SDK signed request cookie.

// To get access to signed request data
facebookContext.signedRequest

But the signed request is automatically parsed and all its data are available in FacebookContext, so you should not have to use it.

If you are running your app on apps.facebook.com or in a page tab, signedRequest is only available on initial request (if you navigate inside the iframe, signed request is lost if you do not pass it to your links params).

Facebook App

The context gives you access to current Facebook app info.

// To get Facebook app id (defined in Config.groovy)
facebookContext.app.id
// To get Facebook app permissions (defined in Config.groovy)
facebookContext.app.permissions
 // To get Facebook app secret (defined in Config.groovy)
facebookContext.app.secret
 // To get default app token, concatenation of id and secret
facebookContext.app.token
// To get OAuth app token, required for Graph API calls (it will generate a Graph API call)
facebookContext.app.getToken(true)

If you are running your app in a page tab, you'll get additional info:

// To get app data pass through page tab query string (...&app_data={SOME_STRING}...)
facebookContext.app.data

Facebook User

To check if current user has authorized your app and is authenticated, use facebookContext.authenticated.

if (facebookContext.authenticated) {
    // User is authenticated
}

If authenticated, the context gives you access to current Facebook user info.

// To get facebook user id
facebookContext.user.id
// To get OAuth user token, required for Graph API calls
facebookContext.user.token

If the app is running on an external site (web or mobile), the access token will be automatically fetched in exchange for the authorization code returned by Facebook JS SDK signed request cookie or server-side redirect query string.

If the app is running on apps.facebook.com or in a page tab, the access token will be extracted from the signed request params (passed through the canvas iFrame) and you'll get additional info:

// To get facebook user age restriction (only returned in Canvas apps, it will not be returned for external apps)
facebookContext.user.age
// To get facebook user country
facebookContext.user.country
 // To get facebook user locale
facebookContext.user.locale

In order to optimize performances, user id and token are automatically stored in session scope.

By default token are only valid during 2 hours, if a request is made with an expired token, session will be automatically invalidated. If required, you can exchange the short-term token for a long-lived one (valid during 60 days).

if (facebookContext.authenticated && !facebookContext.user.tokenExpired) {
  // Exchange token to get an extended expiration time (60 days)
  log.info "Current token expiration time: " + new Date(facebookContext.user.tokenExpirationTime)
  facebookContext.user.exchangeToken()
  log.info "Exchanged token expiration time:  " + new Date(facebookContext.user.tokenExpirationTime)
}

Facebook Page

If the app is running in a page tab, the context gives you access to current Facebook page info.

Otherwise, facebookContext.page is null. You must check if it exists before accessing it.

// To get facebook page id (where the app is installed)
facebookContext.page?.id
// To know if current user has liked the current page
facebookContext.page?.liked
 // To know if current user is an admin of the current page
facebookContext.page?.admin

4 Facebook Graph Client

WARNING: Since V2.1.0, FacebookGraphClient constructor has changed with a new apiVersion parameter (default to V2.1).
// From
FacebookGraphClient(String accessToken = '', Integer timeout = DEFAULT_READ_TIMEOUT_IN_MS, String proxyHost = null, Integer proxyPort = null) {
// To
FacebookGraphClient(String accessToken = '', String apiVersion = DEFAULT_API_VERSION, Integer timeout = DEFAULT_READ_TIMEOUT_IN_MS, String proxyHost = null, Integer proxyPort = null) {

To perform Facebook Graph API call, use the FacebookGraphClient without access token for public data or with an access token for private data. FacebookGraphClient is a thin groovy wrapper around the rock solid RestFB java library . It will return JSON-based graph objects.

To play with the API, you might use the grails console from your project root and get user token or app token from Facebook Access Token Tool .

grails console

Initialization

import grails.plugin.facebooksdk.FacebookGraphClient

// For public data def facebookClient = new FacebookGraphClient()

// For private data (access token required) def userAccessToken = facebookAppService.getUserAccessToken() // Or any app/user token def facebookClient = new FacebookGraphClient(userAccessToken)

// With specific api version def facebookClient = new FacebookGraphClient(userAccessToken, 'v1.0')

// With specific timeout (default to 180s) def facebookClient = new FacebookGraphClient(userAccessToken, FacebookGraphClient.DEFAULT_API_VERSION, 90000)

// With proxy support def facebookClient = new FacebookGraphClient(userAccessToken, FacebookGraphClient.DEFAULT_API_VERSION, FacebookGraphClient.DEFAULT_READ_TIMEOUT_IN_MS, '192.168.0.10', 8080)

Fetching Single Objects

def user = facebookClient.fetchObject("me") // Requires a user access token
def page = facebookClient.fetchObject("cocacola")
println "User name: " + user.name
println "Page likes: " + page.likes

Fetching Multiple Objects in One Call

def fetchObjectsResults = facebookClient.fetchObjects(["me", "cocacola"])
println "User name: " + fetchObjectsResults["me"].name
println "Page likes: " + fetchObjectsResults["cocacola"].likes

Fetching Connections

Make sure that you asked for the corresponding user permissions, e.g. user_status for the feed, user_photos for the photos, etc.

def myFriends = facebookClient.fetchConnection("me/friends")
def myFeed = facebookClient.fetchConnection("me/feed")
println "Count of my friends: " + myFriends.size()
println "First item in my feed: " + myFeed[0]

Searching

// Searching is just a special case of fetching Connections -
// all you have to do is pass along a few extra parameters.
def publicSearch = facebookClient.fetchConnection("search", [q:"watermelon", type:"post"])
println "Public search: " + publicSearch[0].message
// Targeted search
def targetedSearch = facebookClient.fetchConnection("me/home", [q:"Mark", type:"user"])
println "Posts on my wall by friends named Mark: " + targetedSearch.size()

Fetching Insights

// Fetching Insights data is as simple as fetching a Connection
def insights = facebookClient.fetchConnection("PAGE_ID/insights")
for (insight in insights) println insight.name

Executing FQL Queries

String query = "SELECT uid, name FROM user WHERE uid=220439 or uid=7901103"
def users = facebookClient.executeQuery(query)
println "Users: " + users

Executing Multiple FQL Queries in One Call

Map queries = [users:"SELECT uid, name FROM user WHERE uid=220439 OR uid=7901103", likers:"SELECT user_id FROM like WHERE object_id=122788341354"]
multiqueryResults = facebookClient.executeMultiquery(queries)
println "Users: " + multiqueryResults.users
println "People who liked: " + multiqueryResults.likers

Metadata/Introspection

// You can specify metadata=1 for many calls, not just this one.
// See the Facebook Graph API documentation for more details.
def userWithMetadata = facebookClient.fetchObject("me", [metadata:1])
println "User connections  " + userWithMetadata.metadata.connections

Passing Parameters

// You can pass along any parameters you'd like to the Facebook endpoint.
Date oneWeekAgo = new Date() - 7
def filteredFeed = facebookClient.fetchConnection("me/feed", [limit:3, until:"yesterday", since:oneWeekAgo])
println "Filtered feed count: " + filteredFeed.size()

Selecting Specific Fields

def user = facebookClient.fetchObject("me", [fields:"id, name"])
println "User name: " + user.name

Publishing a Message and Event

// Publishing a simple message.
def publishMessageResponse = facebookClient.publish("me/feed", [message:"RestFB test"])
println "Published message ID: " + publishMessageResponse.id

// Publishing an event Date tomorrow = new Date() + 1 Date twoDaysFromNow = new Date() + 2 def publishEventResponse = facebookClient.publish("me/events", [name:"Party", start_time:tomorrow, end_time:twoDaysFromNow]) println "Published event ID: " + publishEventResponse.id

Publishing a Photo or a Video

// Publishing an image to a photo album is easy!
// Just specify the image you'd like to upload and RestFB will handle it from there.
def publishPhotoResponse = facebookClient.publish("me/photos", [message, "Test cat"], "/Users/ben/Downloads/cat.png")
println "Published photo ID: " + publishPhotoResponse.id
// Publish a submitted file
def publishPhotoResponse = facebookClient.publish("me/photos", [message, "Test upload"], multipartFile.originalFilename, multipartFile.inputStream)
// Publish an existing remote file by URL
def someUrl = "http://www.google.com/images/logo.gif"
def publishPhotoResponse = facebookClient.publish("me/photos", [message, "Test logo"], "logo.gif", new URL(someUrl).openStream())
println "Published photo ID: " + publishPhotoResponse.id
// Publishing a video works the same way.
facebookClient.publish("me/videos", [message, "Test cat"], "/Users/ben/Downloads/cat.mov")

Deleting

Boolean deleted = facebookClient.deleteObject("some object ID")
out.println("Deleted object? " + deleted)

Using the Batch Request API

List batchResponses = facebookClient.executeBatch(["me", "m83music/feed"]);
// Responses are ordered to match up with their corresponding requests.
println "Me object " + batchResponses[0]
println "M83 feed " + batchResponses[1]

Error Handling

All FacebookClient methods may throw com.restfb.exception.FacebookException, which is an unchecked exception as of RestFB 1.6.

These are the FacebookException subclasses that you may catch:

  • FacebookJsonMappingException
  • FacebookNetworkException
  • FacebookGraphException
  • FacebookOAuthException
  • FacebookQueryParseException
  • FacebookResponseStatusException

For more info, check RestFB java library documentation.

5 Facebook JS Tag Lib

Facebook JS Tag Lib is a set of tags to easily integrate Facebook JS SDK Dialogs in your GSPs.

It provides the following tags:

Dialogs not yet implemented:

Feel free to contribute… ;)

6 Facebook Social Plugins

Facebook Social Plugins

Facebook also provides Facebook Social Plugins .

They are very easy to integrate, you just need to set xfbml to true in facebook:initJS tag.

…
<body>
<facebook:initJS
        appId="${facebookContext.app.id}"
        xfbml="${true}" />
…
<!-- Facebook Like Button -->
<div class="fb-like" data-href="http://example.com" data-send="false" data-show-faces="false" data-width="810"></div>
…
<!-- Facebook Comments -->
<div class="fb-comments" data-href="http://example.com" data-num-posts="5" data-width="810"></div>