Over a million developers have joined DZone.
Platinum Partner

Tapestry Linkedin

· Java Zone

The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.

Continuing from the Tweeting post and Facebook post, lets us extend the OAuth Service to enable us to update status on Linkedin. We start by creating LinkedinService

So here is the Linkedin service

public interface LinkedinService extends BaseOAuthService {


public class LinkedinServiceImpl extends BaseOAuthServiceImpl implements LinkedinService {

    private ApplicationStateManager stateManager;

    public LinkedinServiceImpl(OAuthConfiguration configuration, String apiPrefix,
        ApplicationStateManager stateManager) {
        super(configuration, LinkedInApi.class, apiPrefix);

        this.stateManager = stateManager;

    public String getAuthorizationURL() {
        Token requestToken = newRequestToken();

        stateManager.set(Token.class, requestToken);

        return getOAuthService().getAuthorizationUrl(requestToken);

    public Token requestAccessToken(String oauthToken, String verifier) {
        Token requestToken = stateManager.getIfExists(Token.class);
        return getOAuthService().getAccessToken(requestToken, new Verifier(verifier));

Linkedin uses the request token for getting access token. This requires us to save the request token in the user’s session using ApplicationStateManager. Next is the OAuthResource for Linkedin Status Update.

public class LinkedinStatusUpdate extends AbstractOAuthResource {
    private String text;
    private String title;
    private String link;
    private String imageLink;

    public LinkedinStatusUpdate(Token accessToken,
        String text, String title, String link, String imageLink) {
        super(accessToken, Verb.POST, "people/~/shares");
        this.text = text;
        this.title = title;
        this.link = link;
        this.imageLink = imageLink;

    public void process(Response response) {


    public void initialize(OAuthRequest request) {
        Document doc = new Document();

        Element share = doc.newRootElement("share");

        if(text != null) {
        Element content = share.element("content");

        if(title != null) {

        if(link != null) {

        if(imageLink != null) {


        String requestXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +

        request.addHeader("Content-Length", Integer.toString(requestXML.length()));
        request.addHeader("Content-Type", "text/xml");

This update is all about sending an xml with the status related information as a POST request to people/~/shares. e.g.

<?xml version="1.0" encoding="UTF-8"?>
  <comment>83% of employers will use social media to hire: 78% LinkedIn, 55% Facebook, 45% Twitter [SF Biz Times] http://bit.ly/cCpeOD</comment>
	 <title>Survey: Social networks top hiring tool - San Francisco Business Times</title>

This example is from the linkedin Share page. We are using Tapestry’s own DOM classes to create the xml.

Finally the component

public class LinkedinConnect implements ClientElement {
    @Parameter(value = "prop:componentResources.id", defaultPrefix = BindingConstants.LITERAL, allowNull = false)
    private String clientId;

    private String assignedClientId;

    private JavaScriptSupport javaScriptSupport;

    private ComponentResources resources;

    private LinkedinService linkedinService;

    void addJavaScript() {
        assignedClientId = javaScriptSupport.allocateClientId(clientId);

    URL getAuthorizationURL() throws MalformedURLException {
        return new URL(linkedinService.getAuthorizationURL());

    Object onAuthorize(
        @RequestParameter(value = "oauth_verifier", allowBlank = true) final String verifier,
        @RequestParameter(value = "oauth_token", allowBlank = true) String oAuthToken,
        @RequestParameter(value = "denied", allowBlank = true) String denied) {

        if(verifier != null) {
            return accessGranted(oAuthToken, verifier);
        } else {
            return accessDenied(denied);

    private Object accessGranted(String oAuthToken, String verifier) {
        Token accessToken = linkedinService.requestAccessToken(oAuthToken, verifier);

        CaptureResultCallback<Object> callback = new CaptureResultCallback<Object>();

        boolean handled = resources.triggerEvent(OAuthConstants.CONNECTION_ESTABLISHED, new Object[] {
            accessToken}, callback);

        if(handled) {
            return callback.getResult();

        return null;

    private Object accessDenied(String denied) {
        CaptureResultCallback<Object> callback = new CaptureResultCallback<Object>();

        boolean handled = resources.triggerEvent(OAuthConstants.CONNECTION_FAILED,
            new Object[] {denied}, callback);

        if(handled) {
            return callback.getResult();

        return null;

    public String getClientId() {
        return assignedClientId;
<t:container xmlns:t='http://tapestry.apache.org/schema/tapestry_5_1_0.xsd'>

    <a href='#' t:type='eventLink' t:event='connectToLinkedin'>


It is almost a copy of the TwitterConnect. When the link is clicked, the event handler returns the authorization URL which redirects the browser to Linkedin authorization. After Linkedin has authorized, it redirects the browser to the callback URL(which is specified in the configuration) which is our onAuthorize() event handler. The event handler, based on the request parameters, decides which callback to call.

Finally the module contribution

public LinkedinService buildLinkedinService(ApplicationStateManager stateManager){
        OAuthConfiguration configurer = new OAuthConfiguration("app_id",
                 "http://localhost:9090/linkedin.linkedinconnect:authorize", null);

        return new LinkedinServiceImpl(configurer, OAuthConstants.DEFAULT_LINKEDIN_API_PREFIX, stateManager);

Using the component in a page is very similar to the previous one

public class Linkedin {

    private LinkedinService linkedinService;

    private String message;

    @OnEvent(value = OAuthConstants.CONNECTION_ESTABLISHED)
    void changeStatus(Token accessToken) {
        linkedinService.send(new LinkedinStatusUpdate(accessToken, "Google", "Google", "http://www.google.com",
        message = "Status Updated";

    void onConnectionFailed(String denied) {
        message = "Failed";



<html xmlns:t='http://tapestry.apache.org/schema/tapestry_5_1_0.xsd'>

        <a t:id='linkedinConnect' t:type='linkedinConnect'>Connect to Linkedin</a>



From http://tawus.wordpress.com/2011/10/14/tapestry-linkedin/

The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.


{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}