2

I'm trying to use Spring Social Facebook in order to read in my application (at moment a simple Java class test)

But I'm having some problems. I created a very simple project (maven oriented) and I'm using Spring social 1.1.0

I created the following Java class:

import it.eng.comi.spring.service.CoMiSocialNetworkingSvc;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.social.connect.support.ConnectionFactoryRegistry;
import org.springframework.social.facebook.api.Facebook;
import org.springframework.social.facebook.api.PagedList;
import org.springframework.social.facebook.api.Post;
import org.springframework.social.facebook.api.impl.FacebookTemplate;
import org.springframework.social.facebook.connect.FacebookConnectionFactory;
import org.springframework.social.oauth2.AccessGrant;
import org.springframework.social.oauth2.OAuth2Operations;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.social.twitter.api.impl.TwitterTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

@Service
public class CoMiSocialNetworkSvcImpl implements CoMiSocialNetworkingSvc
{
    private static final Log logger = LogFactory.getLog(CoMiSocialNetworkSvcImpl.class.getName());
    @Value("${facebook.appId}")
    private String facebookAppId;
    @Value("${facebook.appSecret}")
    private String facebookAppSecret;
    @Value("${facebook.appNamespace}")
    private String facebookAppNamespace;
    @Autowired
    private ConnectionFactoryRegistry cfr;

    @Override
    public PagedList<Post> getPosts() throws Exception
    {

        try
        {

            FacebookConnectionFactory fcc = (FacebookConnectionFactory)cfr.getConnectionFactory("facebook");
            OAuth2Operations oauthOper = fcc.getOAuthOperations();
            String scope = "publish_stream,offline_access,read_stream,user_about_me,manage_pages";
            AccessGrant ag = oauthOper.authenticateClient(scope);
            String accessToken = ag.getAccessToken();
            logger.info("Access Token: "+accessToken);
            Facebook facebook = new FacebookTemplate(accessToken);
            PagedList<Post> result = facebook.feedOperations().getHomeFeed();
            result.addAll(facebook.feedOperations().getFeed());
            return result;
        }
        catch (Exception e)
        {
            String messagge = "Errore nel recupero feed: "+e.getMessage();
            logger.fatal(messagge, e);
            throw e;
        }
    }
}

And I created this simple JUnit test:

import java.util.List;
import it.eng.comi.spring.service.CoMiSocialNetworkingSvc;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.social.facebook.api.PagedList;
import org.springframework.social.facebook.api.Post;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

@ContextConfiguration(value={
        "classpath:application-context-social.xml"
})

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class ComiSocialTests
{
    private static final Log logger = LogFactory.getLog(ComiSocialTests.class.getName());
    @Autowired
    private CoMiSocialNetworkingSvc social;
    @Test
    public void testFeeds()
    {
        try
        {
            PagedList<Post> feeds = social.getPosts();
            for (Post post : feeds)
            {
                logger.info("Caption "+post.getCaption()+" like counts "+post.getLikeCount()+" comments count: "+post.getCommentCount()+" descrizione "+post.getDescription());
            }
        }
        catch (Exception e)
        {
            logger.error(e.getMessage(), e);
        }
    }   
}

This is my application context XML:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:facebook="http://www.springframework.org/schema/social/facebook"
    xmlns:twitter="http://www.springframework.org/schema/social/twitter"
    xmlns:social="http://www.springframework.org/schema/social"
    xmlns:linkedin="http://www.springframework.org/schema/social/linkedin"
    xmlns:c="http://www.springframework.org/schema/c"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/social/facebook http://www.springframework.org/schema/social/spring-social-facebook.xsd
        http://www.springframework.org/schema/social/linkedin http://www.springframework.org/schema/social/spring-social-linkedin.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/social/twitter http://www.springframework.org/schema/social/spring-social-twitter.xsd
        http://www.springframework.org/schema/social http://www.springframework.org/schema/social/spring-social.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">


    <context:property-placeholder location="classpath:configuration.properties" ignore-resource-not-found="true" ignore-unresolvable="true" />
    <context:component-scan base-package="it.eng.comi.spring" />
    <bean id="connectionFactoryLocator"
        class="org.springframework.social.connect.support.ConnectionFactoryRegistry">
        <property name="connectionFactories">
            <list>
                <bean
                    class="org.springframework.social.facebook.connect.FacebookConnectionFactory">
                    <constructor-arg value="${facebook.appId}" />
                    <constructor-arg value="${facebook.appSecret}" />
                </bean>
                <bean
                    class="org.springframework.social.twitter.connect.TwitterConnectionFactory">
                    <constructor-arg value="${twitter.appKey}" />
                    <constructor-arg value="${twitter.appSecret}" />
                </bean>
            </list>
        </property>
    </bean>
</beans>

When I try co contact FB with the showed implemetation (method getPosts() of the showed class) I get this error:

11:35:39,501 INFO  [CoMiSocialNetworkSvcImpl] Access Token: 868557579830099|4JH01Jwud-Ot0UTd_FoF_439r50
11:35:45,149 WARN  [RestTemplate] GET request for "https://graph.facebook.com/me/home?limit=25" resulted in 400 (Bad Request); invoking error handler
{"error":{"message":"An active access token must be used to query information about the current user.","type":"OAuthException","code":2500}}
11:35:50,625 FATAL [CoMiSocialNetworkSvcImpl] Errore nel recupero feed: Authorization is required for the operation, but the API binding was created without authorization.
org.springframework.social.MissingAuthorizationException: Authorization is required for the operation, but the API binding was created without authorization.
    at org.springframework.social.facebook.api.impl.FacebookErrorHandler.handleFacebookError(FacebookErrorHandler.java:89)
    at org.springframework.social.facebook.api.impl.FacebookErrorHandler.handleError(FacebookErrorHandler.java:65)
    at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:588)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:546)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:517)
    at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:255)
    at org.springframework.social.facebook.api.impl.FeedTemplate.fetchConnectionList(FeedTemplate.java:367)
    at org.springframework.social.facebook.api.impl.FeedTemplate.getHomeFeed(FeedTemplate.java:106)
    at org.springframework.social.facebook.api.impl.FeedTemplate.getHomeFeed(FeedTemplate.java:95)
    at it.eng.comi.spring.service.impl.CoMiSocialNetworkSvcImpl.getPosts(CoMiSocialNetworkSvcImpl.java:146)
    at it.eng.comi.test.ComiSocialTests.testFeeds(ComiSocialTests.java:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)

Can anyone suggest me how to solve this issue? I'm stuck on this from a couple of days and I can't solve it

thank you Angelo

Angelo Immediata
  • 6,635
  • 4
  • 33
  • 65
  • Facebook requires an access token to invoke that Graph API method. You can get an access token by having a user login to your application with OAuth. – Alex Nov 06 '14 at 00:23
  • @Alex thank for replying me. I know I need an access token and I can get it by using the OAuth dance...the problem is that I'm missing how to do it with Spring Social....and I'm not able in finding some sample code as start point – Angelo Immediata Nov 06 '14 at 07:52
  • Have you tried this? https://github.com/spring-projects/spring-social-samples/tree/master/spring-social-showcase – Alex Nov 08 '14 at 21:29
  • @Alex I gave a look at it.....but I am still missing the following: I have my own FB account and I want to share my wall posts on my site....how can I do it? – Angelo Immediata Nov 09 '14 at 08:46
  • You probably need to create a Facebook app so you will then have a clientId, secret, and accessToken. Then you can plug these values into the spring social example to do an OAuth login using your personal FB account. The result of the OAuth login will be an access token you can use to query Facebook's Graph API. – Alex Nov 10 '14 at 01:29
  • @Alex hi Alex; it's what I did. I created an app on my FB account and I got the clientId and secret token. What I'm missing is: by spring social how can I get the accessToken (with read_stream access) in order to read my wall posts? It seems a very simple question but I'm struggling on it from almost 10 days – Angelo Immediata Nov 11 '14 at 07:54
  • For testing purposes you can give yourself read_stream. But from the FB documentation, my understanding is that there is no way to get read_stream anymore for a web application. That's nothing to do with Spring Social, that's a business decision on FB's part. – Alex Nov 11 '14 at 16:43
  • @Alex always thank you for replying me :) what I don't understand is: how can I use the org.springframework.social.facebook.connect.FacebookConnectionFactory class? In this class I can pass the clientId and Secret and it should be this Factory to manage the "OAuth dance"; If I use it, instead, I can't connect to my App; if on FB site I create a client access token and I use the FacebookTemplate by passing the generated client token I can connect on the home wall. Moreover, it seems to me I can't specify to the FacebookConnectionFactory the read_stream privilege. This is destroying me – Angelo Immediata Nov 12 '14 at 08:25

0 Answers0