📜 ⬆️ ⬇️

How to update your Facebook, LinkedIn & Twitter status using spring-social

Not so long ago, I already wrote about the new project SpringSource: spring-social . Today I want to tell (or rather show an example) how to use this library. As an example, we use the simplest application that allows you to log in to all three services and update the status at the same time in all three (caution - there are a lot of letters and code under the cut and there are no pictures at all).
imageimageimageimage

The status update was taken as an example because:
* it is simple and clear;
* This function is not supported by spring-social for LinkedIn, that is, you can see how to add the implementation of API methods of services that are not implemented in spring-social by default.
In principle, any other functionality can be in place of the status update.

The developers themselves are advised to look at their GreenHouse application as an example of using the library - but the application is quite large and isolating the “social” part is not so easy. It was also published a couple of examples - but rather primitive - not giving a "complete picture." That's why I decided to write a small example (to figure it out myself and show it to others) which, on the one hand, would represent with myself some complete example from login to service to sending status, and on the other hand it would be as simple as possible. Because - I'm sorry that html is naked without any styles - plus the java-code is not “beautiful” everywhere - in some places the code could be done “more correctly”, for example, by inheritance, but it would “zymylylo” example - would have to deal with additional class hierarchy.

This post is a free translation of my English-language post .
All sources are available in svn: http://svn.emforge.net/svnroot/akakunin-experiments/update-status
Sources can also be viewed on the EmForge website.
')

Basic application


As a “base” we use the simplest application on the spring framework and spring-mvc. This application uses the standard gentleman's set:
* Maven to build;
* Spring Framework 3.0.5;
* Spring-Security 3.0.5;
* JPA (via Hibernate);
* HSQL as a base.

In principle, everything is as standard and simple as possible. There is a single Entity - net.emforge.updatestatus.entity.User - which stores users (userName, password). For each user, the tokens are also saved, which are used to work with each of the services.
There is a DAO class UserDao , and a UserServiceImpl service.
The application has two pages - the main (index) with a form for login and registration (processed by UserController ), and the status page is accessible only to logged in users - we'll talk about it later.

All together, this is the simplest application where a user can register or log in, and on the status page connect with one of the services and update the status.

Application registration


In order for this example to work, you will first need to register your application with the services you intend to use:
* Registration on Facebook is carried out on page http://developers.facebook.com/setup/ - only please use localhost : 8080 / update-status / as SiteURL - otherwise the callback will not work;
* Sign up for Twitter: http://dev.twitter.com/apps/new ;
* Register on LinkedIn: https://www.linkedin.com/secure/developer

In each case, you will receive two keys - the application key (or application id) & security-token - they should be saved in src / main / resources / config.properties

Run Quick


If you want to quickly see how it works and you have java & maven (I hope that this is so :)), then just take the source from svn and execute (after you write your keys in config.properties)
mvn tomcat:run

After that, the application should be available at http: // localhost: 8080 / update-status
Create a new user - and go ahead, and we will see how it is all implemented

Connect on LinkedIn and Twitter


To work with both services, OAuth is used and the connection procedure is similar - so I'll show you with a twitter example.
To work with the service, we write the simplest class TwitterProvider the main method in which is getOAuthService:
public OAuthService getOAuthService() {
OAuthConfig config = new OAuthConfig();
config.setRequestTokenEndpoint( "https://api.twitter.com/oauth/request_token" );
config.setAccessTokenEndpoint( "https://api.twitter.com/oauth/access_token" );
config.setAccessTokenVerb(Verb.POST);
config.setRequestTokenVerb(Verb.POST);
config.setApiKey(apiKey);
config.setApiSecret(apiSecret);
config.setCallback(callbackUrl);

return new OAuth10aServiceImpl(
new HMACSha1SignatureService(),
new TimestampServiceImpl(),
new BaseStringExtractorImpl(),
new HeaderExtractorImpl(),
new TokenExtractorImpl(),
new TokenExtractorImpl(),
config);
}


apiKey, apiSecret & callbackUrl are injected from config.properties (where we first write from).

For the connection, add the link / connet / twitter and hang the handler (in SocialController ):
@RequestMapping(value = "/connect/twitter" , method = RequestMethod.GET)
public String requestConnectionToTwitter(WebRequest request) {
// get request token
Token requestToken = twitterProvider.getOAuthService().getRequestToken();
// store request token in session
request.setAttribute( "twitter_request_token" , requestToken, WebRequest.SCOPE_SESSION);

return "redirect:" + twitterProvider.getAuthorizeUrl() + "?oauth_token=" + requestToken.getToken();
}



In essence, this handler redirects to Twitter in order to pass the login in it. In the case of a successful login, Twitter will redirect to callbackUrl and transfer the user's keys there. Let's hang up the handler for callBack in SocialController:
/** Callback from twitter on success login
*
* @param verifier
* @param request
* @return
*/
@RequestMapping(value = "/callback/twitter" , method = RequestMethod.GET, params = "oauth_token" )
public String authorizeTwitterCallback(@RequestParam(value = "oauth_verifier" , defaultValue = "verifier" ) String verifier,
WebRequest request) {
// get request token from session
Token requestToken = (Token)request.getAttribute( "twitter_request_token" , WebRequest.SCOPE_SESSION);

// get access token
Token accessToken = twitterProvider.getOAuthService().getAccessToken(requestToken, new Verifier(verifier));
String userName = getCurrentUser().getName();
userService.updateTwitterAuthentication(userName, accessToken.getToken(), accessToken.getSecret());

return "redirect:/status" ;

}

In this handler, we get the tokens and save them to the user for future use.

Facebook Connect


On Facebook, things are a little trickier. In order to connect to Facebook we place the button “Connect to Facebook” on our status.jsp page using the following code:
< form id ="fb_signin" action ="<c:url value=" / connect / facebook " /> " method="post" >
< div class ="formInfo" >
</ div >
< div id ="fb-root" ></ div >
< p >< fb:login-button perms ="email,publish_stream,offline_access" onlogin ="$('#fb_signin').submit();" v ="2" length ="long" > Connect to Facebook </ fb:login-button ></ p >
</ form >

< facebook:init />


It is important to pay attention to the following points:
* facebook: init tag is implemented in the spring-social library and it needs a $ {facebookProvider} bin in the context of the spring context - we have it implemented in the FacebookProvider class. In fact, the tag takes only keys from this bin;
* fb: login-button generates the "Connect to Facebook" button;
* form-action / connect / facebook will be used as a callback in case of a successful login.

Just for this code to work it is necessary to connect tagLib
<%@ taglib uri="http://www.springframework.org/spring-social/facebook/tags" prefix="facebook" %>

and connect jQuery - in my case I just did



Well, you need to write a callback handler that will come to / connect / facebook:
@RequestMapping(value= "/connect/facebook" , method=RequestMethod.POST)
public String connectAccountToFacebook(@FacebookAccessToken String accessToken,
@FacebookUserId String facebookUserId) {
if (facebookUserId != null && accessToken != null ) {
// store facebook information
String userName = getCurrentUser().getName();
userService.updateFacebookAuthentication(userName, accessToken, facebookUserId);
}
return "redirect:/status" ;
}

* This source code was highlighted with Source Code Highlighter .


In this example, we will see two interesting annotations: @FacebookAccessToken and @FacebookUserId is one of the spring-social features, but in order for it to work, we need to add a special WebArgResolver to the project. To do this, add to applicationContext.xml :
< bean id ="facebookWebArgResolver" class ="org.springframework.social.facebook.FacebookWebArgumentResolver" >
< constructor-arg name ="apiKey" value ="${facebook.appId}" />
</ bean >

* This source code was highlighted with Source Code Highlighter .

Handling callback is similar to Tiwtter & Linkedin - saving keys (in our case, facebookUserId & facebookToken) for further use.

Posting status on Twitter & Facebook


Log out, logged in, now you can update the status. On the status page, we have a textArea where the user enters text and sends a message. The form handler looks like this:
@RequestMapping(value = "/status" , method = RequestMethod.POST)
public String sendStatus(@Valid StatusForm statusForm, BindingResult result, ModelMap modelMap) {
User user = getCurrentUser();

LinkedInTemplateExt linkedInTemplate = linkedInProvider.createTemplate(user);
FacebookTemplate facebookTemplate = facebookProvider.createTemplate(user);
TwitterTemplate twitterTemplate = twitterProvider.createTemplate(user);

// send message to LinkedIn
if (linkedInTemplate != null ) {
linkedInTemplate.updateStatus(statusForm.getStatus());
}

// send message to Facebook
if (facebookTemplate != null ) {
facebookTemplate.updateStatus(statusForm.getStatus());
}

// send message to Twitter
if (twitterTemplate != null ) {
twitterTemplate.updateStatus(statusForm.getStatus());
}
return "redirect:/status" ;
}

* This source code was highlighted with Source Code Highlighter .

In this handler, we get the FacebookTemplate & TwitterTemplate (both classes from spring-social) using the keys of the current user and call their updateStatus method

Posting LinkedIn Status


LinkedIn got a little more complicated - the LinkedInTemplate implemented in spring-social does not contain a method for updating the status - so we have to write it ourselves (using the REST-API call api.linkedin.com/v1/people/~/person -activities ). To do this, we write the class LinkedInTemplateExt - the successor of the “original” LinkedInTemplate in which:
* Initialize our own object of the RestOperations class - using the special OAuth1RequestSignerFactory.getRequestSigner for “correct” call coding (another spring-social feature);
* Implement the updateStatus method itself:
public void updateStatus(String message) {
LinkedInPersonActivity personActivity = new LinkedInPersonActivity(message);

restOperationsExt.postForLocation( "http://api.linkedin.com/v1/people/~/person-activities" , personActivity);
}

* This source code was highlighted with Source Code Highlighter .


we also need to write a class LinkedInPersonActivity - to pass the status:
@XmlRootElement(name = "activity" )
public class LinkedInPersonActivity {
public LinkedInPersonActivity() {
}
public LinkedInPersonActivity(String body) {
this .body = body;
}

@XmlElement(name = "content-type" )
String contentType = "linkedin-html" ;

@XmlElement(name = "body" )
String body;
}

* This source code was highlighted with Source Code Highlighter .


Everything - the method is ready - as you can see - despite the fact that LinkedInTemplate initially supports very few functions from the API - adding new functions is not such a difficult task.

That's all - I hope this example will be useful.

Source: https://habr.com/ru/post/108824/


All Articles