Over a million developers have joined DZone.

Tweeting with Tapestry

· Java Zone

Check out this 8-step guide to see how you can increase your productivity by skipping slow application redeploys and by implementing application profiling, as you code! Brought to you in partnership with ZeroTurnaround.

For tweeting in java, there are not many options like there are in other languages especially ruby. The best solution I have found is scribe-java. Interfacing with this library is very easy but you waste a lot of time trying to find what to do when.

The first step was to make the library talk like Tapestry. To do that we create a base service for OAuth.

public interface BaseOAuthService {
    String getAuthorizationURL();

    Token requestAccessToken(String temporaryToken, String verifier);

    JSONObject send(OAuthResource resource);

    Token newRequestToken();

    OAuthConfiguration getConfiguration();

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)

        if (configuration.getScope() != null) {

        service = builder.build();

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

    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());

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

        Response response = request.send();


        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;

As you can see there is not much going on. It is just a wrapper which allows us to request a resource specified by OAuthResource. The response is checked for status and if it is not success (HTTP CODE : 200) an exception is thrown.

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;

    public Verb getMethod() {
        return method;

    public String getURL() {
        return resource;

    public Token getAccessToken(){
        return accessToken;

    public void initialize(OAuthRequest request){


    public void process(Response response) {


getMethod returns the method which should be used to request the resource. getURL() returns the URL of the resource. getAccessToken() return the access token which is to be passed to the request for authorization purposes. initialize() method is used to pass parameters to the request and process() is used to process the response. Such an interface can be best understood by an implementation.

public class Tweet extends AbstractOAuthResource {

    private String tweet;

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

        this.tweet = tweet;

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


Twitter APIs expect a POST request for resource "statuses/update.json" for updating user status, in plain english, to tweet. The tweet text is passed as a parameter to the request in initialize() method.

The configuration to the service is passed as

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;



To use this service, let’s create a component which gives us access to a twitter account

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

    private String assignedClientId;

    private JavaScriptSupport javaScriptSupport;

    private ComponentResources resources;

    private TwitterService twitterService;

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

    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>


When the link is clicked, the browser is redirected to twitter’s authorization link. Before returning the URL, getAuthorizationURL() first requests a request token from twitter. The twitter authorizes and redirects the browser to the callback URL(callback URL is configured in the application module) which triggers onAuthorize(), which in term based on whether the authorization was successful or not triggers different events.

The services have to be contributed to the application module

public TwitterService buildTwitterService() {

    OAuthConfiguration configurer = new OAuthConfiguration("MY_API_KEY",

    return new TwitterServiceImpl(configurer, OAuthConstants.DEFAULT_TWITTER_API_PREFIX);

Please note the URL has to point to the event handler of TwitterConnect's authorize event. (I know this part is a hack, but will replace with a better solutions soon)

And finally the page using it. As you would have guessed from the URL above, twitter page is Tweet

public class Tweet {

    private TwitterService twitterService;

    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'>

      <a href='#' t:id='twitterconnect' t:type='twitterConnect'>Connect to Twitter</a>



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

The Java Zone is brought to you in partnership with ZeroTurnaround. Check out this 8-step guide to see how you can increase your productivity by skipping slow application redeploys and by implementing application profiling, as you code!


Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}