Intergrating Twitter OAuth using java/spring/Twitter4j


The comprehensive link about Twitter approach for using Oauth (its same for other cases too ) can be found
TwitterOAuth
To cut it short following are the important steps:

Get the consumer key and consumer secret.Dev Twitter

Twitter API

Note: If you are going to make an webapp dont forget to put a valid url in the “CallBack Url” field. The valid url can be back to your localhost. But dont put “localhost” as twitter doesnt provide support. I had put http://127.0.0.1:8080/SpringMVC/callback for this application. The value of url can be changed at runtime.

Following are the steps using browser.. My homepage url is

http://localhost:8080/SpringMVC/welcome


When a user clicks on the hyperlink an oauth authorize request is sent to twitter by sharing the token key and token secret and user is redirected to twitter page.

After login into Twitter the user will be redirected to the callback url and the username will be displayed.

I am using Twitter4j for connecting with Twitter.

@RequestMapping("/welcome")
@Controller
public class WelcomeController {
        @Autowired
	private OAuthToken oauthToken;
        Twitter twitter = new TwitterFactory().getInstance();

	@Autowired
	private MyAccessToken accestoken;
	@RequestMapping(method = RequestMethod.GET)
	
	public String printWelcome(HttpServletResponse response,HttpServletRequest request) {

		twitter.setOAuthConsumer(oauthToken.getConsumerKey(),
		oauthToken.getConsumerSecret());
		RequestToken requestToken;
		try {
			
			String callbackURL = "http://127.0.0.1:8080/SpringMVC/callback";
             requestToken = twitter.getOAuthRequestToken(callbackURL);
             String token = requestToken.getToken();
 			String tokenSecret = requestToken.getTokenSecret();
			accestoken.setTokensecret(tokenSecret);
			accestoken.setToken(token);
			String authUrl = requestToken.getAuthorizationURL();
			request.setAttribute("authUrl", authUrl);
		} catch (TwitterException e) {
			e.printStackTrace();
		} 
		
		return "login";
	}
}

The callback url can be set as shown above. The MyAcessToken is used to persist the token for the request.

My login.jsp is

 <a href='<%=request.getAttribute("authUrl") %>'>Sign in with Twitter</a>

So when the user enters http://127.0.0.1/SpringMVC/welcome , they will be redirected to login.jsp.

When the user clicks on the “Sign in” link , it will be redirected to Twitter login site and then will be redirected to the callback url set. The controller to handle callback url is

@Controller
@RequestMapping("/callback")
public class CallBackController extends AbstractController{</code>

	@Autowired
	private OAuthToken oauthToken;
	
	@Autowired
	private MyAccessToken accessToken; 
	@Override
	@RequestMapping(method={RequestMethod.GET,RequestMethod.POST})
	protected ModelAndView handleRequestInternal(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
			Twitter twitter = new TwitterFactory().getInstance();
			
			twitter.setOAuthConsumer(oauthToken.getConsumerKey(), oauthToken.getConsumerSecret());
			String verifier = request.getParameter("oauth_verifier");
	       RequestToken requestToken = new RequestToken(accessToken.getToken(), accessToken.getTokensecret());
	       AccessToken accessToken = twitter.getOAuthAccessToken(requestToken,verifier);
	       twitter.setOAuthAccessToken(accessToken);
	       User user = twitter.verifyCredentials();
	       System.out.println(user.getName());
	       ModelAndView model = new ModelAndView("hello");
	       model.addObject("message", user.getName());
	       return model;
	}
}

Once the user comes back it will be redirected to “hello.jsp” with user name displayed.Note the MyAccessToken set for user before request is made is used here.

<html>;
<body>
<h1>Twitter Login successful for : ${message}</h1>
</body>
</html>

The oauthtoken is stored and configured in dispatcher-servlet xml which is loaded using web.xml

<bean>
<context:component-scan base-package="com.common.controller" />

<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="oauthToken" class="com.common.OAuthToken">
<property name="consumerKey" value="yourconsumerkey"/>
<property name="consumerSecret" value="yourconsumersecret"/>
</bean>
<bean id="accessToken" class="com.mkyong.common.MyAccessToken"/>
</beans>

The other model classes OAuthToken and MyAccessToken :

public class OAuthToken {

	public String consumerKey;
	public String consumerSecret;
	public String getConsumerKey() {
		return consumerKey;
	}
	public void setConsumerKey(String consumerKey) {
		this.consumerKey = consumerKey;
	}
	public String getConsumerSecret() {
		return consumerSecret;
	}
	public void setConsumerSecret(String consumerSecret) {
		this.consumerSecret = consumerSecret;
	}
}
public class MyAccessToken {

	private String token;
	private String tokensecret;
	public String getTokensecret() {
		return tokensecret;
	}
	public void setTokensecret(String tokensecret) {
		this.tokensecret = tokensecret;
	}
	public String getToken() {
		return token;
	}
	public void setToken(String token) {
		this.token = token;
	}
	
}

Download Source Code

Advertisements

Using Spring form to add enum values of JSP page


At times it is required to add Enum values on the jsp page so that its easy to handle on the server side. To display this feature i am using spring 3.0 version.
Lets create a Java Enum Class and override some of its behavior

public enum WorkingDay {</code>

Monday("Monday"),
Tuesday("Tuesday");
Wednesday("Wednesday");
Thursday("Thursday");

private String description;

private WorkingDay(String description) {
this.description = description;
}

public String getValue() {
return name();
}

public void setValue(String value) {}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

}

I just want 4 working days in a week 🙂 .

Now register a binder to the controller.

@InitBinder
protected void initBinder(HttpServletRequest request,
ServletRequestDataBinder binder) {</code>

binder.registerCustomEditor(WorkingDay.class, new PropertyEditorSupport() {
@Override
public void setAsText(String value) throws IllegalArgumentException {
if(StringUtils.isBlank(value))
return;

setValue(WorkingDay.valueOf(value));
}

@Override
public String getAsText() {
if(getValue() == null)
return "";

return ((WorkingDay) getValue()).name();
}
});

Set the WorkingDay object to the model object for the view. It should be in the same controller in which the above binder is registered.

@RequestMapping(value="/form", method = RequestMethod.GET)
public ModelAndView showForm() {
ModelAndView model = new ModelAndView("/view_my_jsp");
model.addObject("workingday", WorkingDay.values());
return model;
}

Add the code in “view_my_jsp.jsp”

<form:radiobuttons path="type" items="${workinday}" />

The value of path should match the field name of the property of the command object passed.
The jsp page will contain four radio buttons.

MongoDb Java Driver


Its very easy to integrate the MongoDB with a java driver …
Download Java Driver
Once downloaded the connection to the mongodb is made using configServer() and other methods are self explanatory.

public class MongoDB {

	private String hostname ="localhost";
	private int port = 27017;
	private String dbStore = "myFirstApplication";
	private DB database;
	private DBCollection collection;
	public MongoDB(){
		
		configServer();
	}

	/**
	 * doing the configuration. By default the collection is set to testing.
	 */
	private void configServer() {
		try {
			Mongo mongo = new Mongo(hostname,port);
			 database = mongo.getDB(dbStore);
			 collection = database.getCollection("testing");
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (MongoException e) {
			e.printStackTrace();
		}
	}
	/**
	 * Insert the json object to DB
	 * @param jsonString
	 */
	public void insert(String jsonString){
		DBObject dbobject = (DBObject) JSON.parse(jsonString);
		collection.insert(dbobject);
	}
	
	/**
	 * find the json object using the key.. Not very efficient though
	 * @param key
	 * @param value
	 * @return
	 */
	public DBObject find(String key,String value){
		BasicDBObject query = new BasicDBObject(key,value);
		DBObject dbObject = collection.findOne(query);
		return dbObject;
	}
	
	
	/**
	 * find an object with the unique object id.
	 *  This throws IllegalArgumentException if the object id doesnt exist 
	 * @param objectId
	 * @return
	 */
	
	public DBObject find(ObjectId objectId) {
		BasicDBObject query = new BasicDBObject("_id",objectId);
		return collection.findOne(query);
	}
	/**
	 * delete the json on the basis of key
	 * @param key
	 * @param value
	 */
	public void delete (String key,String value){
		BasicDBObject query = new BasicDBObject(key,value);
		collection.remove(query);
		
	}
	
	/**
	 * delete by the uniqied id given by mongo
	 * @param objectId
	 */
	public void deleteById(ObjectId objectId){
		BasicDBObject query = new BasicDBObject("_id",objectId);
		collection.remove(query);
	}
	/*
	 * update the value of key in json string. First the object is found using "_id"
	 */
	public boolean update(String key,String value,ObjectId objectId){
		BasicDBObject query = new BasicDBObject("_id",objectId);
		DBObject dbObject = collection.findOne(query);
		if(dbObject != null){
			DBObject newObject = new BasicDBObject(key, value);
			DBObject oldObject = (DBObject) dbObject.get(key);
			if(oldObject != null){
				collection.update(dbObject,new BasicDBObject("$set",new BasicDBObject(key,value)));
				return true;
			}
		}
		return false;
	}
}

Rails 3 + MongDB , MongoMapper beginner tutorial


I recently used MongoDB at my work for mobile app and was tempted to try more. So i wrote a simple app in rails to play with it..

Lets assume rails is already installed.

References for tutorial:
MongoDb installation
MongoDB with Rails
Railcast of integrating rails with Mongo

The installation of MongoDB can be done using the first reference.
Lets create a rails project now to record daily expenses.

rails new expense_record --skip-active-record

We need to update the gemfile by adding mongo dependencies:

require 'rubygems'
require 'mongo'

gem 'rails', '3.0.10'

# Bundle edge Rails instead:
# gem 'rails', :git =&gt; 'git://github.com/rails/rails.git'
source 'http://gemcutter.org'

gem "mongo_mapper"
gem "bson_ext", "1.3.1"
gem "bson" ,"1.3.1"
gem  "mongo","1.3.1"

Now run

bundle install

Create a new filemongo_config.rb in config/initializers folder.
Lets add the following code :

MongoMapper.connection = Mongo::Connection.new('localhost', 27017)
MongoMapper.database = "#expense-#{Rails.env}"

if defined?(PhusionPassenger)
   PhusionPassenger.on_event(:starting_worker_process) do |forked|
     MongoMapper.connection.connect if forked
   end
end

NOTE: here the #expense is the name of the database. By default Mongo listens to 27017 port. Also the database name should not contain “.”, such as “expense1.0” is wrong.

Now lets create an expense model with field “expense_name” “date_spent” “amount”.

rails g scaffold expense expense_name:string date_spent:string amount:integer --skip-migration --orm mongo_mapper

All the classes are created as expected except the model class expense

class Expense
  include MongoMapper::Document

  key :expense_name, String
  key :date_spent, String
  key :amount, Integer

end

Instead of ActiveRecord , MongoMapper is used which behaves pretty much the same.

Now we are good to run the project.

rails s 
<a href="http://localhost:3000/expenses"></a>

Happy coding..