Статьи

Твиттер с гобеленом

Для твитов в Java не так много вариантов, как в других языках, особенно в ruby. Лучшее решение, которое я нашел, это писец-ява . Взаимодействие с этой библиотекой очень просто, но вы тратите много времени, пытаясь найти, что делать, когда.

Первым шагом было заставить библиотеку говорить как Гобелен. Для этого мы создаем базовый сервис для OAuth.

//Interface
public interface BaseOAuthService {
    String getAuthorizationURL();

    Token requestAccessToken(String temporaryToken, String verifier);

    JSONObject send(OAuthResource resource);

    Token newRequestToken();

    OAuthConfiguration getConfiguration();
}

//Implementation
public class BaseOAuthServiceImpl implements BaseOAuthService {

    private OAuthService service;

    private String apiPrefix;

    private OAuthConfiguration configuration;

    private static final Logger logger = LoggerFactory.getLogger(BaseOAuthServiceImpl.class);

    public BaseOAuthServiceImpl(OAuthConfiguration configuration,
        Class<? extends Api> provider, String apiPrefix) {
        ServiceBuilder builder = new ServiceBuilder().provider(provider)
                .apiKey(configuration.getApiKey()).apiSecret(configuration.getApiSecret())
                .callback(configuration.getCallbackURL());

        if (configuration.getScope() != null) {
            builder.scope(configuration.getScope());
        }

        service = builder.build();

        this.apiPrefix = apiPrefix;
        this.configuration = configuration;
    }

    @Override
    public String getAuthorizationURL() {
        return service.getAuthorizationUrl(newRequestToken());
    }

    public Token newRequestToken() {
        return service.getRequestToken();
    }

    public Token requestAccessToken(String oAuthToken, String verifier) {

        Token accessToken = service.getAccessToken(
                new Token(oAuthToken, configuration.getApiSecret()), new Verifier(verifier));

        return accessToken;
    }

    public JSONObject send(OAuthResource resource) {
        OAuthRequest request = new OAuthRequest(resource.getMethod(), apiPrefix
                + resource.getURL());

        resource.initialize(request);
        service.signRequest(resource.getAccessToken(), request);

        Response response = request.send();
        checkResponse(response);

        resource.process(response);

        return new JSONObject(response.getBody());
    }

    private void checkResponse(Response response) {
        if (response.getCode() != HttpServletResponse.SC_OK) {
            logger.error("Failed sending request : " + response.getBody());
            throw new OAuthException("Failure sending request");
        }
    }

    public OAuthService getOAuthService() {
        return service;
    }

    public OAuthConfiguration getConfiguration(){
        return configuration;
    }
}

Как вы можете видеть, там мало что происходит. Это просто оболочка, которая позволяет нам запрашивать ресурс, указанный OAuthResource. Ответ проверяется на статус и, если он не успешен (HTTP-код: 200), генерируется исключение.

public interface OAuthResource {

    Verb getMethod();

    void initialize(OAuthRequest request);

    String getURL();

    Token getAccessToken();

    void process(Response response);

}

//An abstract implementation
public abstract class AbstractOAuthResource implements OAuthResource {

    private Verb method;

    private String resource;

    private Token accessToken;

    public AbstractOAuthResource(Token accessToken, Verb method, String resource){
        this.accessToken = accessToken;
        this.method = method;
        this.resource = resource;
    }

    @Override
    public Verb getMethod() {
        return method;
    }

    @Override
    public String getURL() {
        return resource;
    }

    @Override
    public Token getAccessToken(){
        return accessToken;
    }

    @Override
    public void initialize(OAuthRequest request){

    }

    @Override
    public void process(Response response) {
    }

}

getMethod возвращает метод, который должен использоваться для запроса ресурса. getURL () возвращает URL ресурса. getAccessToken () возвращает токен доступа, который должен быть передан в запрос для авторизации. Метод initialize () используется для передачи параметров в запрос, а process () — для обработки ответа. Такой интерфейс лучше всего понять при реализации.

public class Tweet extends AbstractOAuthResource {

    private String tweet;

    public Tweet(Token token, String tweet){
        super(token, Verb.POST, "statuses/update.json");

        this.tweet = tweet;
    }

    @Override
    public void initialize(OAuthRequest request){
        request.addBodyParameter("status", tweet);
        request.addBodyParameter("wrap_links", "true");
    }

}

API-интерфейсы Twitter ожидают POST-запрос ресурса «statuses / update.json» для обновления статуса пользователя на простом английском языке, чтобы твитнуть. Текст твита передается как параметр в запрос в методе initialize ().

Конфигурация для сервиса передается как

public class OAuthConfiguration {

    private String apiKey;

    private String apiSecret;

    private String callbackURL;

    private String scope;

    public OAuthConfiguration(String apiKey, String apiSecret,
        String callbackURL, String scope) {
        this.apiKey = apiKey;
        this.apiSecret = apiSecret;
        this.callbackURL = callbackURL;
        this.scope = scope;
    }

    public OAuthConfiguration(String apiKey, String apiSecret, String callbackURL){
        this(apiKey, apiSecret, callbackURL, null);
    }

    public String getApiKey() {
        return apiKey;
    }

    public String getApiSecret() {
        return apiSecret;
    }

    public String getCallbackURL() {
        return callbackURL;
    }

    public String getScope() {
        return scope;
    }

    public void setScope(String scope){
        this.scope = scope;
    }

}

использование

Чтобы использовать этот сервис, давайте создадим компонент, который дает нам доступ к учетной записи Twitter

@Events({OAuthConstants.CONNECTION_ESTABLISHED, OAuthConstants.CONNECTION_FAILED})
public class TwitterConnect implements ClientElement {
    @Parameter(value = "prop:componentResources.id", defaultPrefix = BindingConstants.LITERAL)
    private String clientId;

    private String assignedClientId;

    @Inject
    private JavaScriptSupport javaScriptSupport;

    @Inject
    private ComponentResources resources;

    @Inject
    private TwitterService twitterService;

    void setupRender() {
        assignedClientId = javaScriptSupport.allocateClientId(clientId);
    }

    @Override
    public String getClientId() {
        return assignedClientId;
    }

    URL onConnectToTwitter() throws MalformedURLException {
        return new URL(twitterService.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 = twitterService.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 class OAuthConstants {

    public static final String DEFAULT_TWITTER_API_PREFIX = "http://api.twitter.com/1/";

    public static final String CONNECTION_ESTABLISHED = "connectionEstablished";

    public static final String CONNECTION_FAILED = "connectionFailed";

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

   <a href='#' t:type='eventlink' t:event='connectToTwitter'><t:body/></a>

</t:container>

Когда ссылка нажата, браузер перенаправляется на ссылку авторизации Twitter. Перед возвратом URL getAuthorizationURL () сначала запрашивает токен запроса из твиттера. Твиттер авторизует и перенаправляет браузер на URL-адрес обратного вызова (URL-адрес обратного вызова настраивается в модуле приложения), который запускает onAuthorize (), который в зависимости от того, была ли авторизация успешной или нет, инициирует различные события.

Услуги должны быть внесены в модуль приложения

public TwitterService buildTwitterService() {

    OAuthConfiguration configurer = new OAuthConfiguration("MY_API_KEY",
            "MY_API_SECRET",
            "http://127.0.0.1:9090/tweet.twitterconnect:authorize");

    return new TwitterServiceImpl(configurer, OAuthConstants.DEFAULT_TWITTER_API_PREFIX);
}

Обратите внимание, что URL-адрес должен указывать на обработчик события авторизации TwitterConnect. (Я знаю, что эта часть взломана, но скоро заменит лучшие решения)

И наконец страница, использующая это. Как вы могли догадаться из приведенного выше URL, твиттер-страница — Tweet

public class Tweet {

    @Inject
    private TwitterService twitterService;

    @SuppressWarnings("unused")
    @Property
    @Persist(PersistenceConstants.FLASH)
    private String message;

    void onConnectionEstablishedFromTwitterConnect(Token accessToken) {

        twitterService.tweet(accessToken,  "Hello from scribe-twitter at " + new Date());

        message = "Tweeted";
    }

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

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

   <body>
         ${message}<br/>
      <a href='#' t:id='twitterconnect' t:type='twitterConnect'>Connect to Twitter</a>
   </body>

</html>

 

От http://tawus.wordpress.com/2011/08/14/tweeting-with-tapestry/