GWTで作ってみた


Twitterのユーザー名で検索すると、その人のアイコン、名前、紹介分が表示され
その下にフォローしてる人たちのアイコン、タイムラインが表示される簡単なやつ。
なんかWindowsアプリみたいな感覚でできるのが驚き。
あと、ソースコードはutf8にしないと日本語文字化けるので気をつける。

エントリーポイント
package org.ham007.twitterviewer.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;

public class TwitterViewer implements EntryPoint {
	
	public void onModuleLoad() {
		MainPage main_page = new MainPage();
		main_page.setWidget(RootPanel.get("main_panel"));
	}
}
ページクラス
package org.ham007.twitterviewer.client;

public class MainPage implements KeyDownHandler, ClickHandler {
	//サービス
	private final GetTwitterUserServiceAsync sv_getuser = GWT.create(GetTwitterUserService.class);
	private final GetFriendTimeLineServiceAsync sv_gettimeline = GWT.create(GetFriendTimeLineService.class);
	//メイン
	private final VerticalPanel main_panel = new VerticalPanel();
	//検索領域
	private final HorizontalPanel search_panel = new HorizontalPanel();
	private final TextBox txt_userid = new TextBox();
	private final Button btn_search = new Button("Search");
	//検索結果表示
	private final HTML result_usr_html = new HTML();
	//タイムライン
	private final Grid time_line_grid = new Grid();
	
	public MainPage(){
		search_panel.add(txt_userid);
		search_panel.add(btn_search);
		txt_userid.addKeyDownHandler(this);
		btn_search.addClickHandler(this);
		
		main_panel.add(search_panel);
		main_panel.add(result_usr_html);
		main_panel.add(time_line_grid);
	}
	
	public void setWidget(RootPanel root_panel){
		root_panel.add(main_panel);
	}

	@Override
	public void onKeyDown(KeyDownEvent event) {
		if(event.getNativeKeyCode() == KeyCodes.KEY_ENTER)
			procSearch();
	}

	@Override
	public void onClick(ClickEvent event) {
		procSearch();
	}
	
	private void procSearch(){
		procDispUser();
		procDispTimeLine();
	}
	
	private void procDispUser(){
		sv_getuser.getUser(txt_userid.getText(), new AsyncCallback<TwitterUserBean>(){
			@Override
			public void onFailure(Throwable caught) {
				//Todo:ダイアログボックス表示でエラーを伝える
				caught.printStackTrace();
			}
			@Override
			public void onSuccess(TwitterUserBean result) {
                                //Todo:やっぱりこういうのは仕方ない?
				StringBuilder sb = new StringBuilder();
				sb.append("</br>Your Infomation</br>");
				sb.append("<table border=\"1\">");
				sb.append("<tr>");
				sb.append("<td>");
				sb.append("<img src=\"" + result.getPofileImageUrl() + "\" alt=\"アイコン\" />");
				sb.append("</td>");
				sb.append("<td>");
				sb.append(result.getScreenName());
				sb.append("</td>");
				sb.append("</tr>");
				sb.append("<tr>");
				sb.append("<td colspan=\"2\">");
				sb.append(result.getDescription());
				sb.append("</td>");
				sb.append("</tr>");
				sb.append("</table></br>");
				result_usr_html.setHTML(sb.toString());
			}
		});
	}
	
	private void procDispTimeLine(){
		sv_gettimeline.getTimeLine(txt_userid.getText(), new AsyncCallback<List<TwitterStatusBean>>(){
			@Override
			public void onFailure(Throwable caught) {
				//Todo:ダイアログボックス表示でエラーを伝える
				caught.printStackTrace();
			}
			@Override
			public void onSuccess(List<TwitterStatusBean> result) {
				time_line_grid.resize(result.size() + 1, 2);
				time_line_grid.setBorderWidth(1);
				
				//ヘッダ設定
				time_line_grid.setText(0, 0, "Icon");
				time_line_grid.setText(0, 1, "Message");
				
				for(int i=0;i<result.size();i++){
					HTML img = new HTML();
					TwitterUserBean usr = result.get(i).getUser();
					img.setHTML("<a href=\"http://www.twitter.com/" + usr.getScreenName() + "\" target=\"_blank\"><img src=\"" + usr.getPofileImageUrl() + "\" alt=\"" + usr.getName() + "\" /></a>");
					
					int row_idx = i + 1;
					time_line_grid.setWidget(row_idx, 0, img);
					time_line_grid.setText(row_idx, 1, result.get(i).getText());					
				}
			}
		});
	}
}
ユーザー情報取得サービスインターフェイス
package org.ham007.twitterviewer.client.service;

@RemoteServiceRelativePath("gettwitteruser")
public interface GetTwitterUserService extends RemoteService  {
	TwitterUserBean getUser(String target_id);
}

public interface GetTwitterUserServiceAsync {
	void getUser(String target_id, AsyncCallback<TwitterUserBean> callback);
}
Twitterユーザー情報取得サービスサーバー実装
外部ライブラリのtwitter4jを使用
外部ライブラリ使用時は手動で、war\WEB-INF\libフォルダにjarファイル配置する必要あり?
自環境、設定では手動で配置しないとClassNotFoundExceptionを吐いた。
package org.ham007.twitterviewer.server.service;

@SuppressWarnings("serial")
public class GetTwitterUserServiceImpl extends RemoteServiceServlet implements GetTwitterUserService {
	
	@Override
	public TwitterUserBean getUser(String target_id) {
		try
		{
                        //MyTwitter -> シングルトンなクラス。Twitterインスタンスを取得する。
			Twitter twitter = MyTwitter.get();
			User user = twitter.getUserDetail(target_id);
			
			TwitterUserBean usr_bean = new TwitterUserBean();
			setupTwitterUserBean(usr_bean, user);
			
			return usr_bean;
		}
		catch(TwitterException e)
		{
			e.printStackTrace();
			return null;
		}
	}
	
	private void setupTwitterUserBean(TwitterUserBean bean, User org){
		bean.setDescription(org.getDescription());
		bean.setId(org.getId());
		bean.setName(org.getName());
		bean.setPofileImageUrl(org.getProfileImageURL().toString());
		bean.setScreenName(org.getScreenName());
		if(org.getURL() != null)
			bean.setUrl(org.getURL().toString());
	}
}
twitter4j.Userの簡易ラッパークラス。
サーバーから戻ってくるユーザー定義クラスの例
client側のパッケージに配置する必要がある。
プリミティブ型、コレクション、IsSerializable実装クラス以外は使用できない。
(コメントアウト箇所は実行時エラーになる。)
package org.ham007.twitterviewer.client;

//import twitter4j.User;
import com.google.gwt.user.client.rpc.IsSerializable;

public class TwitterUserBean implements IsSerializable {
	
    private int id = Integer.MIN_VALUE;
    private String name = "";
    private String screenName = "";
    private String description = "";
    private String profileImageUrl = "";
    private String url = "";
    
    public TwitterUserBean(){}
    
//    public TwitterUserBean(User src){
//    	id = src.getId();
//    	name = src.getName();
//    	screenName = src.getScreenName();
//    	description = src.getDescription();
//    	profileImageUrl = src.getProfileBackgroundImageUrl();
//    	
//    	if(src.getURL() != null)
//    		url = src.getURL().toString();
//    }
    
    public int getId(){
    	return id;
    }
    
    public void setId(int id){
    	this.id = id;
    }
    
    public String getName(){
    	return name;
    }
    
    public void setName(String name){
    	this.name = name;
    }
    
    public String getScreenName(){
    	return screenName;
    }
    
    public void setScreenName(String screenName){
    	this.screenName = screenName;
    }
    
    public String getDescription(){
    	return description;
    }
    
    public void setDescription(String description){
    	this.description = description;
    }
    
    public String getPofileImageUrl(){
    	return profileImageUrl;
    }
    
    public void setPofileImageUrl(String profileImageUrl){
    	this.profileImageUrl = profileImageUrl;
    }
    
    public String getUrl(){
    	return url;
    }
    
    public void setUrl(String url){
    	this.url = url;
    }
    
    @Override
    public String toString() {
    	StringBuilder sb = new StringBuilder();
    	sb.append("Id:");
    	sb.append(addWQ(Integer.toString(id)));
    	sb.append("Name:");
    	sb.append(addWQ(name));
    	sb.append("ScreenName:");
    	sb.append(addWQ(screenName));
    	sb.append("Description:");
    	sb.append(addWQ(description));
    	sb.append("ProfileImageUrl");
    	sb.append(addWQ(profileImageUrl));
    	sb.append("Url");
    	sb.append(addWQ(url));
    	
    	return sb.toString();
    }
    
    private String addWQ(String val){
    	return "\"" + val + "\"";
    }
}