Aruna,
I put the status in the URL, so my example does not need to send a body with the message. Of course there are lots of ways to do things. I thought maybe if you tried it my way and got it working, you would see what was different. This is how I build the URL string:
// status being posted is in 'msg' below...
String url =
http://api.twitter.com/1/statuses/update.json?" + "status=" + URLEncoder.encode( msg, "UTF-8" );
Maybe your are not saving/restoring the tokens correctly, I save mine to an XML file under the user's App folder. No, you don't need to set any parameter to state that the user has authenticated, just sign the request. Below is some code for the save/restore. Note that I am requiring the user to type the PIN one time, not using the callback URL, when attempting to use the callback URL I was getting 401 errors, and never figured out why, just figured I would move on since the user only needs to authenticate once if you save the tokens indefinitely. This was back in the spring and I never revisited it. So, I do not restore the user tokens in the same session as when they first authenticate with the PIN. They type the PIN in to my browser app one time, then on later sessions the tokens are retrieved automatically. I hope the undefined variables are self-explanatory. Have you tried to print out details of the error? Twitter supposedly places detailed error messages in the response body.
Hopefully someone more knowledgeable about authentication or signpost can chime in, I struggle with this stuff too. :)
-Gary
public String GetRequestToken()
{
try
{
log.debug("Fetching request token from Twitter...");
// not using a callback URL, user must type PIN to authenticate the first time
String authUrl = this.oauth_provider.retrieveRequestToken( this.oauth_consumer, OAuth.OUT_OF_BAND );
log.trace("Request token: " + this.oauth_consumer.getToken());
log.trace("Token secret: " + this.oauth_consumer.getTokenSecret());
SaveConsumerTokens( "request_token", this.oauth_consumer.getToken(),
"token_secret", this.oauth_consumer.getTokenSecret() );
return authUrl;
}
catch( OAuthMessageSignerException ex )
{
Config.HandleException( this, ex );
}
catch( OAuthNotAuthorizedException ex )
{
Config.HandleException( this, ex );
}
catch( OAuthExpectationFailedException ex )
{
Config.HandleException( this, ex );
}
catch( OAuthCommunicationException ex )
{
Config.HandleException( this, ex );
}
return null;
}
public void SaveConsumerTokens( String ... tokens )
{
try
{
String folderName = config.APP_DIR + File.separator + this._screen_name;
File folder = new File( folderName );
if( ! folder.exists() )
folder.mkdir();
String fileName = folder.getAbsolutePath() + File.separator + "oauth_tokens.xml";
File file = new File( fileName );
if( ! file.exists() && ! file.createNewFile() )
throw new Exception( "Can't create file for saving consumer tokens: " + file.getAbsolutePath() );
FileWriter fw = new FileWriter( file );
StringWriter strwriter = new StringWriter();
XMLOutputFactory factory = XMLOutputFactory.newInstance();
XMLStreamWriter writer = factory.createXMLStreamWriter( strwriter );
writer.writeStartDocument( "utf-8", "1.0" );
writer.writeStartElement( "oauth_consumer" );
for( int i = 0; i < tokens.length; i += 2 )
{
writer.writeStartElement( tokens[i] );
writer.writeCharacters( tokens[i+1] );
writer.writeEndElement();
}
writer.writeEndElement();
writer.writeEndDocument();
writer.close();
fw.write( strwriter.toString() );
fw.close();
log.debug( "Consumer tokens saved." );
}
catch( Exception ex )
{
Config.HandleException( this, ex );
}
}
public void RestoreConsumerTokens()
{
try
{
log.debug( "Restoring consumer tokens..." );
String folderName = config.APP_DIR + File.separator + this._screen_name;
File folder = new File( folderName );
if( ! folder.exists() )
return; // nothing there
String fileName = folder.getAbsolutePath() + File.separator + "oauth_tokens.xml";
File file = new File( fileName );
if( ! file.exists() )
return; // nothing there
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader( new FileReader( file ) );
log.debug( "Reader initialized." );
while( reader.hasNext() )
{
switch( reader.getEventType() )
{
case XMLStreamReader.START_ELEMENT:
log.trace( "Got START_ELEMENT" );
if( reader.getName().toString().equals( "access_token" ) )
{
reader.next();
this.consumer_access_token = reader.getText();
log.trace( "Got access_token: " + this.consumer_access_token );
}
else
if( reader.getName().toString().equals( "token_secret" ) )
{
reader.next();
this.consumer_token_secret = reader.getText();
log.trace( "Got token_secret: " + this.consumer_token_secret );
}
else
if( reader.getName().toString().equals( "request_token" ) )
{
reader.next();
this.consumer_request_token = reader.getText();
log.trace( "Got request_token: " + this.consumer_request_token );
}
break;
case XMLStreamReader.END_ELEMENT:
log.trace( "Got END_ELEMENT: " + reader.getName() );
break;
default:
log.trace( "Got event: " + reader.getEventType() );
break;
}
reader.next();
}
log.trace( "Reader done." );
reader.close();
if( this.consumer_access_token != null )
{
this.oauth_consumer.setTokenWithSecret( this.consumer_access_token, this.consumer_token_secret );
log.debug( "Consumer access tokens restored." );
}
}
catch( Exception ex )
{
Config.HandleException( this, ex );
return;
}
}
Hi Gary,
Thanks for your response. Yes I am signing the request before I submit it.
Iam using below PostEnabledOAuthConsumer class for creating new consumer object. I tried using way you suggested but it gives unauthorized error even for normal authorization flow. Problem is with status parameter it has to be signed along with request.