SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Google App Engine for Javaを使ってみよう!

Google App Engine for Javaを使ってみよう!
(5)Datastore Java API

Google App Engine for Javaを使ってみよう! (5)

データストアからデータを取得する

プロジェクトの作成

 以下の設定でGWTプロジェクトを作成してください。GWTプロジェクトの作成手順については、第1回の解説を参照してください。今回は日本語(2バイトコード)を扱いたいので、言語設定は必ず[UTF-8]に設定してください。

プロジェクトの設定
Project name ShowGrap
Package com.daisukeyamashita.test.jdo

ライブラリの追加

 データは、Google Visualization APIを利用して、グラフで表示します。

 まず、GWT用のライブラリをダウンロードしてください。アーカイブファイルの中にある「gwt-visualization.jar」ファイルをプロジェクト直下にコピーして、プロジェクトのライブラリパスに追加してください。

 このライブラリはGWTのコンパイル時にのみ利用するので、「WEB-INF/lib」にコピーする必要はありません。

プログラムの作成

 まず、「src/com/daisukeyamashita/test/jdo/ShowGrap.gwt.xml」の<module>タグの直後(4行目)に<inherits name="com.google.gwt.visualization.Visualization" />を挿入してください

 PMFクラスは先ほどと同じです。

com.daisukeyamashita.test.jdo.server.PMFクラス
package com.daisukeyamashita.test.jdo.server;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;

public class PMF {

    private static final PersistenceManagerFactory pmfInstance = JDOHelper
            .getPersistenceManagerFactory("transactions-optional");

    private PMF() {
    }

    public static PersistenceManagerFactory get() {
        return pmfInstance;
    }
}

 StoreDataクラスは先ほどのクラスに、Getterメソッドを追加したものです。Datastore Java APIでは、Getter/Setterメソッドは必要なければ定義する必要がありません。

com.daisukeyamashita.test.jdo.server.StoreDataクラス
package com.daisukeyamashita.test.jdo.server;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class StoreData {
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Long id;
    @Persistent
    private String name;
    @Persistent
    private Integer data;

    public StoreData(String name, Integer data) {
        this.name = name;
        this.data = data;
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public Integer getData() {
        return data;
    }
}

 ChartDataクラスはGWTのAjax通信で送受信するためのシリアライズクラスです。シリアライズクラスであることをGWTコンパイラに通知するために、com.google.gwt.user.client.rpc.IsSerializableインターフェイスをimplementsしておく必要があります。

com.daisukeyamashita.test.jdo.client.ChartDataクラス
package com.daisukeyamashita.test.jdo.client;

import com.google.gwt.user.client.rpc.IsSerializable;

public class ChartData implements IsSerializable {

    private String name;
    private Integer num;

    public ChartData() {
    }

    public ChartData(String name, Integer num) {
        this.name = name;
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getNum() {
        return num;
    }

    public void setNum(Integer num) {
        this.num = num;
    }
}

 GWTのAjax通信用のクライアントサイドのソースコードを定義します。

com.daisukeyamashita.test.jdo.client.GreetingServiceクラス
package com.daisukeyamashita.test.jdo.client;

import java.util.List;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

/**
 * The client side stub for the RPC service.
 */
@RemoteServiceRelativePath("greet")
public interface GreetingService extends RemoteService {
    List<ChartData> getList(String name);
}

com.daisukeyamashita.test.jdo.client.GreetingServiceAsyncクラス
package com.daisukeyamashita.test.jdo.client;

import java.util.List;

import com.google.gwt.user.client.rpc.AsyncCallback;

/**
 * The async counterpart of <code>GreetingService</code>.
 */
public interface GreetingServiceAsync {
    void getList(String name, AsyncCallback<List<ChartData>> callback);
}

 GWTのAjax通信のサーバサイド部分のソースコードを定義します。ここで、データストアからデータを引き出しています。

com.daisukeyamashita.test.jdo.server.GreetingServiceImplクラス
package com.daisukeyamashita.test.jdo.server;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;

import com.daisukeyamashita.test.jdo.client.ChartData;
import com.daisukeyamashita.test.jdo.client.GreetingService;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService {

    private Logger logger = Logger.getLogger(GreetingServiceImpl.class.toString());

    @SuppressWarnings("unchecked")
    public List<ChartData> getList(String name) {
        PersistenceManager pm = PMF.get().getPersistenceManager();
        String query = "select from " + StoreData.class.getName();
        logger.info("query = " + query);
        List<StoreData> list = (List<StoreData>) pm.newQuery(query).execute();
        ArrayList<ChartData> listChartData = new ArrayList<ChartData>();
        for (StoreData storedData : list) {
            String nameRandom = storedData.getName();
            logger.info("name = " + nameRandom);
            Integer numRandom = storedData.getData();
            logger.info("num  = " + numRandom);
            listChartData.add(new ChartData(nameRandom, numRandom));
        }
        return listChartData;
    }

}

 クライアント部分のソースコードを定義します。

com.daisukeyamashita.test.jdo.client.ShowGrapクラス
package com.daisukeyamashita.test.jdo.client;

import java.util.HashMap;
import java.util.List;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.visualization.client.DataTable;
import com.google.gwt.visualization.client.AbstractDataTable.ColumnType;
import com.google.gwt.visualization.client.visualizations.PieChart;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class ShowGrap implements EntryPoint {

    /**
     * Create a remote service proxy to talk to the server-side Greeting
     * service.
     */
    private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
    private Widget widget = new Label("データを表示します");

    /**
     * This is the entry point method.
     */
    public void onModuleLoad() {
        // final TextBox nameField = new TextBox();
        // nameField.setText("GWT User");
        final AsyncCallback<List<ChartData>> callback = new AsyncCallback<List<ChartData>>() {

            public void onSuccess(List<ChartData> result) {
                HashMap<String, Integer> map = new HashMap<String, Integer>();
                for (ChartData random : result) {
                    String name = random.getName();
                    Integer num = map.get(name);
                    if (num == null) {
                        num = new Integer(0);
                    }
                    num += random.getNum();
                    map.put(name, num);
                }
                DataTable data = DataTable.create();
                data.addColumn(ColumnType.STRING, "Task");
                data.addColumn(ColumnType.NUMBER, "Hours per Day");

                data.addRows(map.size());
                int count = 0;
                for (String name : map.keySet()) {
                    data.setValue(count, 0, name);
                    data.setValue(count, 1, map.get(name));
                    count++;
                }
                /* create pie chart */

                PieChart.Options options = PieChart.Options.create();
                options.setWidth(400);
                options.setHeight(240);
                options.set3D(true);
                options.setTitle("GAEのデータ");
                RootPanel.get("nameFieldContainer").remove(widget);
                widget = new PieChart(data, options);
                RootPanel.get("nameFieldContainer").add(widget);
            }

            public void onFailure(Throwable caught) {
                // TODO Auto-generated method stub

            }
        };

        final Button btnGet = new Button("Get!");
        btnGet.addClickHandler(new ClickHandler() {

            public void onClick(ClickEvent event) {
                greetingService.getList("", callback);
            }
        });

        RootPanel.get("nameFieldContainer").add(widget);
        RootPanel.get("sendButtonContainer").add(btnGet);
    }
}
war/ShowGrap.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- The HTML 4.01 Transitional DOCTYPE declaration-->
<!-- above set at the top of the file will set     -->
<!-- the browser's rendering engine into           -->
<!-- "Quirks Mode". Replacing this declaration     -->
<!-- with a "Standards Mode" doctype is supported, -->
<!-- but may lead to some differences in layout.   -->

<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">

    <!--                                                               -->
    <!-- Consider inlining CSS to reduce the number of requested files -->
    <!--                                                               -->
    <link type="text/css" rel="stylesheet" href="ShowGrap.css">

    <!--                                           -->
    <!-- Any title is fine                         -->
    <!--                                           -->
    <title>Web Application Starter Project</title>

    <!--                                           -->
    <!-- This script loads your compiled module.   -->
    <!-- If you add any GWT meta tags, they must   -->
    <!-- be added before this line.                -->
    <!--                                           -->
    <script type="text/javascript" language="javascript" src="showgrap/showgrap.nocache.js"></script>
    <script type="text/javascript" src="http://www.google.com/jsapi"></script>  </head>

  <!--                                           -->
  <!-- The body can have arbitrary html, or      -->
  <!-- you can leave the body empty if you want  -->
  <!-- to create a completely dynamic UI.        -->
  <!--                                           -->
  <body>

    <!-- OPTIONAL: include this if you want history support -->
    <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>

    <script type="text/javascript">
      google.load("visualization", "1", {'packages' : ["piechart", "table"] });
    </script>
    <h1>Web Application Starter Project</h1>

    <table align="center">
      <tr>
        <td id="nameFieldContainer"></td>
        <td id="sendButtonContainer"></td>
      </tr>
    </table>
  </body>
</html>

実行する

 これまでの手順で、Datastore Java APIを利用したプログラムが完成しました。プロジェクト名を右クリックして、[Run As]-[Web Application]を選択してください。

 次のように表示されていればOKです。[Get!]ボタンをクリックします。

 ローカル環境にはデータが保存されていませんので、次のように[No data]と表示されているのを確認してください。

 ローカル環境で正常に動作することが確認できたら、アプリケーションをGoogle App Engineにデプロイしてください。先ほどのアプリケーションで保存したデータを確認したいので、先ほどのアプリケーションと同じ場所にデプロイしてください。

 デプロイが完了したら、[Get!]ボタンを押してデータを表示してみてください。次のようなグラフが表示されると思います。

 円グラフの一部をクリックするとデータの内容を確認することができます。

まとめ

 今回はDatastore Java APIを勉強しましたが、いかがでしたでしょうか? 今回の記事で、Javaからデータストアを簡単に操作できることが分かっていただけたかと思います。

 今回はDatastore Java APIのさわりしか勉強していません。Datastore Java APIでは、もっと高度な制御ができますので、興味のある方はGoogle App Engineのドキュメントを参考に勉強されることをお勧めします。

 この連載でも機会があれば、Datastore Java APIの高度な利用方法を書きたいと思います。

参考資料

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
Google App Engine for Javaを使ってみよう!連載記事一覧

もっと読む

この記事の著者

山下 大介(ヤマシタ ダイスケ)

  京都大学を中心とした、産官学共同プロジェクトのSOBAプロジェクトに参加後、同プロジェクトで開発したP2P配信によるVoIP技術を2005年に商業化。オープンソース、VoIP、P2P、クラウドコンピューティングに精通。趣味はGoogleの追っかけ。現在は、株式会社SOBAプロジェクト取締役。ブログ:『~ ミネルヴァの梟は黄昏とともに飛び始める ~』所属:株式会社SOBAプロジェクトGoogle Developer Day 2008サポーター, 2009サポーターGoogle App Engine API Expert

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/3904 2009/05/27 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー