金曜日, 3月 26, 2010

【Google App Engine】 GDataAPIを非同期に実行するライブラリ このエントリーを含むはてなブックマーク


 App Engine 1.3.1からJavaでも非同期URLFetchが使えるようになって、これまで悩まされ続けていた5秒タイムアウト問題が解消されつつある。

 非同期URLFetchは以下のような感じ。

非同期URLFetchのサンプル


import java.io.IOException;
import java.net.URL;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.appengine.api.urlfetch.HTTPHeader;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;

public class URLFetchServlet {

  public void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws IOException {
    URL url = new URL("http://www.virtual-tech.net/");
    URLFetchService service = URLFetchServiceFactory.getURLFetchService();
    // FetchOptions.Builder. fetchOptions = new FetchOptions();
    // HTTPRequest freq = new HTTPRequest(url, method);
    // Future asyncHttpResp = service.fetchAsync(freq);
    Future asyncHttpResp = service.fetchAsync(url);
    resp.getWriter().println("async fetch");
    try {
      HTTPResponse httpResp = asyncHttpResp.get();
      resp.getWriter().println(
          "content : " + httpResp.getContent());
      for (HTTPHeader header : httpResp.getHeaders()) {
        resp.getWriter().println(
            header.getName() + ": " + header.getValue());
      }
    } catch (InterruptedException e) {
      resp.getWriter().println(e);
    } catch (ExecutionException e) {
      resp.getWriter().println(e);
    }
  }
}



Asynchronous GData API


 せっかくなので、GData APIを非同期実行できるようなパッチを作ってみた。

 これは、5秒を超えて使えると思う。Google Docsで全文検索とか、Google Appsと連携とか、これまで紹介したような外部連携アプリを(やっと)本格的に作れるようになった。

ソース:
gdataclientpatch

 使い方は簡単で、GoogleGDataRequest.javaとHTTPGDataRequest.javaとMediaService.javaを自分のアプリに置くだけ。(パッケージ名は変えないで)

 jarについては、gdata client libにもいくつか入れているが、必要であれば、GData APIの最新版(http://gdata-java-client.googlecode.com/files/gdata-src.java-1.41.1.zip)をダウンロードして必要なjarを入れてほしい。

注意点


 1. AppEngine内でnewできるDocServiceは同時に一つだけとなる。 <= APPNAMEパラメータ(下の例では"Google Service")を適当に変えることで複数のインスタンスを保持できた。スレッドセーフか!?
 2. GoogleDocsにはアクセス制限が存在し、1つのIPから同時に接続できるのは10程度である。アカウントを複数に別けても増えることはない。フロントエンドがリクエストIPを見てるっぽい。
 3. privateでは認証が必要になるが以下のようにリトライしないとうまく取れない。

<追記>
getRequestStream()に一部不具合があったので修正しています。≧‐≦(2010/3/30)




  DocsService service = null;
  for (int r = 0; r < Constants.NUM_RETRIES; r++) {
   try {
    service = new DocsService("Google Service");
    service.setUserCredentials(email, password);
    logger.warning("login OK!");
    return service;

   } catch (ServiceException e) {
    logger.warning(""+e.getStackTrace());
    
    if (r == (Constants.NUM_RETRIES - 1)) {
     return null;
    }
    sleep(Constants.SLEEP_MILL_SECOND);
   }
  }
  return null;





0 件のコメント:

 
© 2006-2015 Virtual Technology
当サイトではGoogle Analyticsを使ってウェブサイトのトラフィック情報を収集しています。詳しくは、プライバシーポリシーを参照してください。