Configuração social do Twitter para o Spring

Configuração social do Twitter para o Spring

A primeira parte da série mostra o trabalho inicial do consumindo a API REST StackExchange para recuperar suas principais perguntas. Esta segunda parte se concentrará na configuração do suporte necessário para interagir com as APIs REST do Twitter usando o projeto Twitter social da Spring. O objetivo final é poder twittar essas perguntas, duas por dia, em várias contas, cada uma focada em um único tópico.

*1. Usando o Twitter social do Spring *

As dependências necessárias para usar o projeto Spring Social Twitter são simples. Primeiro, definimos spring-social-twitter:

<dependency>
   <groupId>org.springframework.social</groupId>
   <artifactId>spring-social-twitter</artifactId>
   <version>1.1.0.RELEASE</version>
</dependency>

Em seguida, precisamos substituir algumas de suas dependências por versões mais atualizadas:

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
   <version>4.1.0.RELEASE</version>
</dependency>
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-web</artifactId>
   <version>4.1.0.RELEASE</version>
</dependency>
<dependency>
   <groupId>org.codehaus.jackson</groupId>
   <artifactId>jackson-mapper-asl</artifactId>
   <version>1.9.13</version>
</dependency>

Spring-core e spring-web são definidos como dependências por spring-social-twitter, mas com* versões mais antigas *- 3.0.7.RELEASE e 3.1.0.RELEASE, respectivamente. Substituí-los em nosso próprio pom garante que o projeto esteja usando as versões atualizadas que definimos em vez dessas versões herdadas mais antigas.

===* 2. Criando um aplicativo do Twitter *

Esse uso - twittar em uma* conta pessoal *e não em nome de outros usuários em suas contas é simples. O fato de ser simples nos permite dispensar a maioria dos Orquestração autêntica necessária se o aplicativo precisar twittar para vários usuários, em cada uma das suas contas do twitter.

Portanto, para nosso caso de uso,* criaremos o TwitterTemplate diretamente *, pois podemos configurar manualmente tudo o que precisamos fazer.

A primeira coisa que precisamos é de um aplicativo dev - ele pode ser criado aqui, após o login. Depois de criar o aplicativo, teremos uma Chave do Consumidor e Segredo do Consumidor - que são obtidas na página do Aplicativo - na guia Detalhes, em OAuth settings.

Além disso, para permitir que o Aplicativo twite na conta, Read e Write Access devem ser configurados para substituir os privilégios padrão Read somente.

*3. Aprovisionando um TwitterTemplate *

Em seguida, o TwitterTemplate exige que um* Access Token e um Access Token Secret sejam provisionados. Eles também podem ser gerados na página Aplicativo - na guia Detalhes - Criar meu token de acesso *. O token de acesso e o segredo podem ser recuperados na guia OAuth tool.

Os novos sempre podem ser regenerados na guia Details, através da ação Recreate my token de acesso.

Nesse ponto, temos tudo o que precisamos - a Chave do consumidor e o Segredo do consumidor, bem como o Token de acesso e o segredo do token de acesso - o que significa que podemos prosseguir e criar nosso TwitterTemplate para esse aplicativo:

new TwitterTemplate(consumerKey, consumerSecret, accessToken, accessTokenSecret);

*4. Um modelo por conta *

Agora que vimos como criar um único TwitterTemplate para* uma única conta *, podemos olhar novamente para nossa base de usuários - precisamos twittar em várias contas - o que significa que precisamos de várias instâncias de TwitterTemplate.

Estes podem ser facilmente criados a pedido, com um mecanismo simples:

@Component
public class TwitterTemplateCreator {
   @Autowired
   private Environment env;

   public Twitter getTwitterTemplate(String accountName) {
      String consumerKey = env.getProperty(accountName + ".consumerKey");
      String consumerSecret = env.getProperty(accountName + ".consumerSecret");
      String accessToken = env.getProperty(accountName + ".accessToken");
      String accessTokenSecret = env.getProperty(accountName + ".accessTokenSecret");
      Preconditions.checkNotNull(consumerKey);
      Preconditions.checkNotNull(consumerSecret);
      Preconditions.checkNotNull(accessToken);
      Preconditions.checkNotNull(accessTokenSecret);

      TwitterTemplate twitterTemplate =
         new TwitterTemplate(consumerKey, consumerSecret, accessToken, accessTokenSecret);
      return twitterTemplate;
   }
}

Os quatro artefatos de segurança são, obviamente, externalizados em um arquivo de propriedades , por conta; por exemplo, para a conta SpringAtSO:

SpringAtSO.consumerKey=nqYezCjxkHabaX6cdte12g
SpringAtSO.consumerSecret=7REmgFW4SnVWpD4EV5Zy9wB2ZEMM9WKxTaZwrgX3i4A
SpringAtSO.accessToken=1197830142-t44T7vwgmOnue8EoAxI1cDyDAEBAvple80s1SQ3
SpringAtSO.accessTokenSecret=ZIpghEJgFGNGQZzDFBT5TgsyeqDKY2zQmYsounPafE

Isso permite uma boa combinação de flexibilidade e segurança - as credenciais de segurança não fazem parte da base de código (que é opensource), mas vivem independentemente no sistema de arquivos e são capturadas pelo Spring e disponível no ambiente Spring através de uma configuração simples:

@Configuration
@PropertySource({ "file:///opt/stack/twitter.properties" })
public class TwitterConfig {
   //
}

link:/properties-with-spring [Propriedades na primavera] são um assunto que já foi discutido antes, portanto não entraremos em mais detalhes sobre esse assunto aqui.

Por fim, um teste verificará se uma conta possui as informações de segurança necessárias prontamente disponíveis no Spring Environment; se as propriedades não estiverem presentes, a lógica getTwitterTemplate deve falhar no teste com uma NullPointerException:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TwitterConfig.class })
public class TwitterTemplateCreatorIntegrationTest {
   @Autowired
   private TwitterTemplateCreator twitterTemplateCreator;
  //
   @Test
   public void givenValidAccountSpringAtSO_whenRetrievingTwitterClient_thenNoException() {
      twitterTemplateCreator.getTwitterTemplate(SimpleTwitterAccount.SpringAtSO.name());
   }
}

*5. Tweeting *

Com o TwitterTemplate criado, vamos passar para a ação real de* twittar *. Para isso, usaremos um serviço muito simples, aceitando um TwitterTemplate e usando sua API subjacente para criar um tweet:

@Service
public class TwitterService {
   private Logger logger = LoggerFactory.getLogger(getClass());

   public void tweet(Twitter twitter, String tweetText) {
      try {
         twitter.timelineOperations().updateStatus(tweetText);
      } catch (RuntimeException ex) {
         logger.error("Unable to tweet" + tweetText, ex);
      }
   }
}

*6. Testando o TwitterTemplate *

E, finalmente, podemos escrever um teste de integração para executar todo o processo de provisionamento de um TwitterTemplate para uma conta e twittar nessa conta:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TwitterConfig.class })
public class TweetServiceLiveTest {
   @Autowired
   private TwitterService twitterService;
   @Autowired
   private TwitterTemplateCreator twitterCreator;

   @Test
   public void whenTweeting_thenNoExceptions() {
      Twitter twitterTemplate = twitterCreator.getTwitterTemplate("SpringAtSO");
      twitterService.tweet(twitterTemplate, "First Tweet");
   }
}

===* 7. Conclusão *

Nesse ponto, a API do Twitter que criamos é completamente separada da API StackExchange e pode ser usada independentemente desse caso de uso específico, para twittar qualquer coisa.

O próximo passo lógico no processo de twittar perguntas das contas do Stack Exchange é criar um componente - interagindo* com as APIs do Twitter e do StackExchange * que apresentamos até agora - este será o foco do próximo artigo desta série.