Develop a Facebook-App with Spring-Social – Part I: Behind the Scenes

In this series of Mini-How-Tow’s I will describe how to develop a facebook app with the help of Spring-Social.

In the last and first part of this series, I prepared you for our little course.

In this part we will take a look behind the scenes and learn more about the autoconfiguration performed by Spring-Boot, which made our first small example so automagically.

The Source is With You

You can find the source-code on http://juplo.de/git/examples/facebook-app/ and browse it via gitweb. Check out part-01 to get the source for this part of the series.

Our Silent Servant Behind the Scenes: Spring-Boot

While looking at our simple example from the last part of this series, you may have wondered, how all this is wired up. You can log in a user from facebook, access his public profile and all this without one line of configuration.

This is achieved via Spring-Boot autoconfiguration.

What comes in very handy in the beginning, sometimes get’s in your way, when your project grows. This may happen, because these parts of the code are not under your control and you do not know what the autoconfiguration is doing on your behalf. Because of that, in this part of our series, we will rebuild the most relevant parts of the configuration by hand. As you will see later, this is not only an exercise, but will lead us to the first improvement of our little example.

What Is Going On Here?

In our case, two Spring-Boot configuration-classes are defining the configuration. These two classes are SocialWebAutoConfiguration and FacebookAutoConfiguration. Both classes are located in the package spring-boot-autoconfigure.

The first one configures the ConnectController, sets up an instance of InMemoryUsersConnectionRepository as persitent store for user/connection-mappings and sets up a UserIdService on our behalf, that always returns the user-id anonymous.

The second one adds an instance of FacebookConnectionFactory to the list of available connection-factories, if the required properties (spring.social.facebook.appId and spring.social.facebook.appSecret) are available. It also configures, that a request-scoped bean of the type Connection<Facebook> is created for each request, that has a known user, who is connected to the Graph-API.

Rebuild This Configuration By Hand

The following class rebuilds the same configuration explicitly:

  1. @Configuration
  2. @EnableSocial
  3. public class SocialConfig extends SocialConfigurerAdapter
  4. {
  5. /**
  6. * Add a {@link FacebookConnectionFactory} to the configuration.
  7. * The factory is configured through the keys <code>facebook.app.id</code>
  8. * and <,code>facebook.app.secret</code>.
  9. *
  10. * @param config
  11. * @param env
  12. */
  13. @Override
  14. public void addConnectionFactories(
  15. ConnectionFactoryConfigurer config,
  16. Environment env
  17. )
  18. {
  19. config.addConnectionFactory(
  20. new FacebookConnectionFactory(
  21. env.getProperty("facebook.app.id"),
  22. env.getProperty("facebook.app.secret")
  23. )
  24. );
  25. }
  26. /**
  27. * Configure an instance of {@link InMemoryUsersConnection} as persistent
  28. * store of user/connection-mappings.
  29. *
  30. * At the moment, no special configuration is needed.
  31. *
  32. * @param connectionFactoryLocator
  33. * The {@link ConnectionFactoryLocator} will be injected by Spring.
  34. * @return
  35. * The configured {@link UsersConnectionRepository}.
  36. */
  37. @Override
  38. public UsersConnectionRepository getUsersConnectionRepository(
  39. ConnectionFactoryLocator connectionFactoryLocator
  40. )
  41. {
  42. InMemoryUsersConnectionRepository repository =
  43. new InMemoryUsersConnectionRepository(connectionFactoryLocator);
  44. return repository;
  45. }
  46. /**
  47. * Configure a {@link UserIdSource}, that is equivalent to the one, that is
  48. * created by Spring-Boot.
  49. *
  50. * @return
  51. * An instance of {@link AnonymousUserIdSource}.
  52. *
  53. * @see {@link AnonymousUserIdSource}
  54. */
  55. @Override
  56. public UserIdSource getUserIdSource()
  57. {
  58. return new AnonymousUserIdSource();
  59. }
  60. /**
  61. * Configuration of the controller, that handles the authorization against
  62. * the Facebook-API, to connect a user to Facebook.
  63. *
  64. * At the moment, no special configuration is needed.
  65. *
  66. * @param factoryLocator
  67. * The {@link ConnectionFactoryLocator} will be injected by Spring.
  68. * @param repository
  69. * The {@link ConnectionRepository} will be injected by Spring.
  70. * @return
  71. * The configured controller.
  72. */
  73. @Bean
  74. public ConnectController connectController(
  75. ConnectionFactoryLocator factoryLocator,
  76. ConnectionRepository repository
  77. )
  78. {
  79. ConnectController controller =
  80. new ConnectController(factoryLocator, repository);
  81. return controller;
  82. }
  83. /**
  84. * Configure a scoped bean named <code>facebook</code>, that enables
  85. * access to the Graph-API in the name of the current user.
  86. *
  87. * @param repository
  88. * The {@link ConnectionRepository} will be injected by Spring.
  89. * @return
  90. * A {@Connection}, that represents the authorization of the
  91. * current user against the Graph-API, or null, if the
  92. * current user is not connected to the API.
  93. */
  94. @Bean
  95. @Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
  96. public Facebook facebook(ConnectionRepository repository)
  97. {
  98. Connection connection =
  99. repository.findPrimaryConnection(Facebook.class);
  100. return connection != null ? connection.getApi() : null;
  101. }
  102. }

If you run this refined version of our app, you will see, that it behaves in exact the same way, as the initial version.

Coming next

You may ask, why we should rebuild the configuration by hand, if it does the same thing. This is, because the example, so far, would not work as a real app. The first step, to refine it, is to take control of the configuration.

In the next part of this series, I will show you, why this is necessary. But, first, we have to take a short look into Spring Social.

Funded by the Europian Union

This article was published in the course of a resarch-project, that is funded by the European Union and the federal state Northrhine-Wetphalia.

Europäische Union: Investitionen in unsere Zukunft - Europäischer Fonds für regionale Entwicklung EFRE.NRW 2014-2020: Invesitionen in Wachstum und Beschäftigung

Leave a Reply

Your email address will not be published. Required fields are marked *