Loading [MathJax]/extensions/tex2jax.js

2010-11-30

GWTでサーバーに直接アクセスする ~Requestbuilderを利用する~

GWTでサーバと通信する場合はGWT-RPCを利用するのがスタイリッシュですが、サーバ内にあるコンテンツやサーブレットにアクセスしたいというときがあります。その際は、Requestbuilderを利用します。使い方は以下のとおり。
  1. @UiHandler("btnSubmit")  
  2.     void onClick(ClickEvent e) {  
  3.         try {  
  4.             final String url = "/test.txt";  
  5.             final RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET, url);  
  6.             requestBuilder.sendRequest("GET"new RequestCallback() {  
  7.   
  8.                 @Override  
  9.                 public void onError(Request request, Throwable exception) {  
  10.                     Window.alert("ファイルの読み込みに失敗しました");  
  11.                 }  
  12.   
  13.                 @Override  
  14.                 public void onResponseReceived(Request request, Response response) {  
  15.                     Window.alert("読み込みました" + response.getText());  
  16.                 }  
  17.             });  
  18.         } catch (RequestException ex) {  
  19.             //エラー処理をここで書く  
  20.         }  
  21.     }  
このサンプルは、ボタンを押したときにサーバ内にあるファイルtest.txtにアクセスしています。アクセスに成功すると、onResponseReceivedメソッドが起きますのでそこで、処理をします。受け取ったデータは引数のResponseクラスに入ってます。なお、GWTはJavaScriptと同じ制約を受けますので、外部のサーバに対してこのようなアクセスをすることは無理です。

2010-11-27

TemplateエンジンVelocityを使ってみよう

今さら感がありますが、TemplateエンジンVelocityについてです。ずいぶん昔からあったフレームワークですが、私自身、以前はJSFベースで作っていたので全く眼中になかったというのが正直なところ。ただ今はGWTに移行したこともあり、Servlet回帰も含めて再評価しているところです。

ライブラリのダウンロードと設定

以下のサイトからダウンロードして下さい。


クラスパスには、"velocity-1.6.4.jar"を追加しておくとよいでしょう。

Velocityの仕組み
利用方法はとてもシンプルです。まず、Templeteとなるファイル(拡張子はvm)を用意し、そこにVelocityの命令文法に従ってテンプレートを記述していきます。Velocityの文法と言っても身構えることはなく、通常のテキスト文の中に命令文法を記述するだけです。その特徴は以下のとおりです。

  • 変数は頭に$を付ける。任意の位置に記述することが可能。
  • foreach, if 文等の繰り返しや条件分岐の処理ができる。
  • Velocityの命令文法を記述した行は先頭に#を付ける

テンプレートファイルの書き方

ここではJSON形式のファイル作成を対象としてみます。

  1. {"name""$user.name""age""$user.age"}  

Javaの記述の仕方は以下のようになります。

  1. StringWriter w = new StringWriter();  
  2.  //マッピングするデータをクラスに格納  
  3.  testUser u = new testUser();  
  4.  u.setName("おち");  
  5.  u.setAge(20);  
  6.  Velocity.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM, new JdkLogChute());  
  7.  Velocity.setProperty(Velocity.INPUT_ENCODING, "UTF-8");  
  8.  Velocity.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");  
  9.  Velocity.init(); // 初期化  
  10.  VelocityContext context = new VelocityContext();  
  11.  //テンプレートとのマッピング  
  12.  context.put("user", u);  
  13.  //テンプレートファイルの指定  
  14.  Template template = Velocity.getTemplate("/WEB-INF/test.vm""UTF-8");  
  15.  //実行。結果はwに出力  
  16.  template.merge(context, w);  
補足しますと、上記のプログラムはテンプレート内の変数とJava内でのデータ変数をクラスの受け渡しによりマッピングさせていることがわかります。

今回はシンプルなJSONを例にしましたが、複雑な形式のファイルをテンプレートを利用して動的に生成することができます。XMLは当然のこと、HTMLの記述もできます。また、Texような文書ファイルにも適用できるでしょう。

これをみて思うのはJSPと何が違うのかということですが、まあVelocityのほうはあくまでもTemplateエンジンとしてシンプルな枠組みになっているような気がします。JSPはあれもこれもいろいろできてしまうわけで、、、
個人的には、XMLとかJSONとかのフォーマットをServlet等で出力する際に、print文とか使ってコード内にガガガッと書かれるのは勘弁してほしいなと思っていたので、VelocityみたいなTemplateエンジンは魅力的なだなぁといまさらながら感じた次第です。

追記:注意事項
上記のサンプルで、testUserというデータクラスを用意していますが、このデータクラスは必ずpublicなものにして下さい。ここをうっかり忘れてて、テンプレートに反映されないという自体に何回か繰り返したので、自分用のメモ追記です。

2010-11-26

GAE/JでAmazon Product Advertising APIを使い始める際の注意事項

Amazon Product Advertising APIで遊んでいるわけですが、ちょっと注意することがあったのでメモ。このAPIについては、認証シグネチャーを要求するようになって、プログラム的にめんどくさそうな感じはしてるが、実際はサンプルプログラムに同梱されているSignedRequestHelperクラスを利用すれば問題ない。。。。はずなんですが、それでも認証のエラーが出ることがあります。これはBASE64エンコードの処理でトラブルらしいのですが、いろいろ情報が錯綜しているようなので,整理してみます。

【GAE/J上で動作させる場合】

  • commons-codec-1.3を利用するとOK
  • 最新版であるcommons-codec-1.4を利用するとエラーになります。

参考までに、

【GAE/J以外で動作させる場合(例えばGlassfishの場合)】

  • commons-codec-1.4での動作OK

ということらしいです。

また、いろいろ検索して出てくる

Base64 encoder = new Base64(); を Base64 encoder = new Base64(0); に修正する

というのもやらなくても動きました。(逆に0を追記するとエラーになりました。1.4では)これは古い情報なのでしょうか?

2010-11-20

[C++/CLI] UDPプログラミング ~非同期通信編~

クライアント側で受信する際に、非同期で処理をしたほうがスムーズに動作する場合があります。以下は、クライアント側のソースです。
using namespace System::Net;
using namespace System::Net::Sockets;
usc = gcnew UdpStateClass();
Socket ^listener = gcnew Socket(AddressFamily::InterNetwork, SocketType::Dgram, ProtocolType::Udp);
usc->endPnt = gcnew IPEndPoint(IPAddress::Any, 11000);//
usc->udpClt = gcnew UdpClient(11000); //接続相手
usc->udpClt->BeginReceive(gcnew AsyncCallback(this,&Clientwww::Form1::receiveCallback),usc);
//コールバック関数の定義
void receiveCallback(IAsyncResult ^ar){
ImageConverter ^imgconv = gcnew ImageConverter();
UdpClient ^uc = (safe_cast<UdpStateClass^>(ar->AsyncState))->udpClt;
IPEndPoint ^iep = (safe_cast<UdpStateClass^>(ar->AsyncState))->endPnt;
//受信データを配列に格納
receiveData = uc->EndReceive(ar, iep);
//コールバック再読み込み
usc->udpClt->BeginReceive(gcnew AsyncCallback(this,&Clientwww::Form1::receiveCallback),usc);
}
view raw udpClient.cpp hosted with ❤ by GitHub
BeginReceiveが実行されると、非同期で受信を行いコールバック関数が呼び出されます。この方法を利用することで、受信を行うまでに次の処理にすすめることができます。

2010-11-13

Twitterアプリを開発でOAuthを利用する際のはじめのはじめの一歩

卒研で、OAuth認証を利用したTwitterアプリを作らせているのですが、ちょっとつまづいたのでそのメモ書き。

まず、TwitterAPIを利用するには、IDとパスワードが必要なわけで、2010年8月まではBASIC認証ができましたが、それ以降はできなくなりました。その代替としてOAuth/xAuthを利用する事になります。この手順としては基本は以下のとおりです。

事前準備
  1. OAuthを使うアプリケーションをTwitterサイトで事前登録する 
  2. 設定画面よりConsumer keyとConsumer secret(アプリのIDとパスワードみたいなもの)を入手
(開発する)アプリでの手順
  1. ユーザにアプリが自身のIDを利用してTwitterにアクセスできるように許可をさせる。具体的にはConsumer keyとConsumer secretを利用して、アプリで認証のためのURLを入手し、そのサイトへユーザをアクセスさせる。
  2. サイト上でユーザが許可するとPINCODE(暗証番号)が表示される
  3. Consumer key、Consumer secret、PINCODEを利用して、AccessTokenとAccessTokenSecretを入手する(これが、ユーザのID、パスワード替りになります)。
  4. 以後、 Consumer key、Consumer secret、AccessToken、AccessTokenSecretを利用してAPIにアクセスする
基本的に、PINCODEの入手は一度だけでいいです。(これを短期間で何回もやってると 401エラーがでるような気がします。真偽は未確認ですが、、、)

アプリを開発する際には、
  • アプリ認証のためにブラウザを起動し認証用URLへ行かせる記述が必要。ウェブアプリの際には、自分のサイトへ戻ってこさせる記述も必要。
  • PINCODEをユーザに入力させる画面とそれを保存する記述が必要。
  • AccessToken、AccessTokenSecretを保存する記述が必要
ということになります。

以上が基本的な考え方ですが、アプリの形態によりちょっとした補足をしておきます。


【マルチユーザでないアプリの場合】
自分しか使わない、あるいはbotのようなアプリの際に、わざわざPINCODEを入手してAccessToken、AccessTokenSecretを入手するプログラムの記述と操作をするのははばからしいです。Twitter上のアプリのサイトには、自分用のAccessToken、AccessTokenSecretを入手するボタンがあります。これをコードに埋め込んでおけば、手軽に利用できます。

【PINCODE入手させることが困難な場合】
アプリによっては、PINCODE入手のためにウェブサイトにアクセスさせることが困難なケースが考えられます。あるいは、いったんウェブブラウザでサイトに行かせるというのは、ユーザビリティの観点からもいまいちです。その際には、xAuth認証(AccessToken、AccessTokenSecretを入手する最初の時だけ、ID、パスワードを入力させる)という枠組みもあります。これを利用する際には、Twitterへメール申請が別途必要です。