2010年4月18日日曜日

UbuntuでJavaDocコマンドがインストールできない

UbuntuのJavaDocコマンドがパッケージの依存関係の問題でapt-getでインストールできません。Ubuntuのバージョンは9.10です。下記のようなエラーが出たら同じ現象だと思われます。


sun-java6-doc (6-15-1) を設定しています ...
This package is an installer package, it does not actually contain the
JDK documentation. You will need to go download one of the
archives:

jdk-6u10-docs.zip jdk-6u10-docs-ja.zip

(choose the non-update version if this is the first installation).
Please visit

http://java.sun.com/javase/downloads/

now and download. The file should be owned by root.root and be copied
to /tmp.

[Press RETURN to try again, 'no' + RETURN to abort] no
Abort installation of JDK documentation
dpkg: sun-java6-doc の処理中にエラーが発生しました (--configure):
サブプロセス installed post-installation script はエラー終了ステータス 1 を返しました
以下のパッケージの処理中にエラーが発生しました:
sun-java6-doc
E: Sub-process /usr/bin/dpkg returned an error code (1)


どうやらUbuntuの sun-java6-doc パッケージがおかしいようです。回避方法を色々試したところ、gjdocを無理やりインストールすればjavadocコマンドが使えるようになりました。


sudo apt-get install gjdoc


gjdocとはGNUライセンスで開発されているオープンソースのJVM関連のツールの実装のようですね。sun純正のパッケージの依存関係がおかしいようなので、これを直接インストールすればよかったみたいです。

http://www.gnu.org/software/classpath/cp-tools/

こういった役に立つツールのオープンソースプロジェクトは素晴らしいですね。ちなみにバージョンを表示したら下記のようです。


javadoc --version
gjdoc 0.7.9

2010年4月11日日曜日

Android-EclipsePluginのセットアップ


下記環境でAndroid開発環境をセットアップしてみようかと思います。
1. Eclipse
2. JDK1.6
3. OS Ubunts

下記を参考にしてみます。

Download the Android SDK


In particular, you may need to install the JDK (version 5 or 6 required) and Eclipse (version 3.4 or 3.5, needed only if you want develop using the ADT Plugin).


JDKとEclipseは入っているのでこのままで大丈夫そうです。


2. Download and install the SDK starter package


Select a starter package from the table at the top of this page
and download it to your development computer. To install the SDK,
simply unpack the starter package to a safe location and then add
the location to your PATH.


Eclipseの設定の前にAndroid SDKを設定しないといけなさそうです。下記のページを参考に設定してみます。

Installing the SDK


Optionally, you may want to add the location of the SDK's primary tools directory to your system PATH. The primary tools/ directory is located at the root of the SDK folder. Adding tools to your path lets you run Android Debug Bridge (adb) and the other command line tools without needing to supply the full path to the tools directory.


* On Linux, edit your ~/.bash_profile or ~/.bashrc file. Look for a line that sets the PATH environment variable and add the full path to the tools/ directory to it. If you don't see a line setting the path, you can add one:
export PATH=${PATH}:/tools


どうやらダウンロードしたSDKを展開後、bashのパス設定に展開したディレクトリを含めればいいようです。android-sdk_r05-linux_86.tgzをダウンロードして、自分のホームディレクトリに展開してみました。~/.bashrcに下記のように設定しておきます


export PATH=${PATH}:~/android-sdk-linux_86/tools


このSDKの説明に大事な事が書いてありまして、下記の用に実行するとソフトウェアアップデートがかかるみたいです。Googleの最新API用開発セットも含まれているようなのでせっかくなので全部入れておきます。もしかしてGoogle API アドオンに関係あるんでしょうか?


android update sdk


では、Eclipseを起動し直して、下記を参考にプラグインをインストールします。

ADT Plugin for Eclipse



1. Start Eclipse, then select Help > Install New Software.
2. In the Available Software dialog, click Add....
3. In the Add Site dialog that appears, enter a name for the remote site (for example, "Android Plugin") in the "Name" field.

In the "Location" field, enter this URL:

https://dl-ssl.google.com/android/eclipse/

Note: If you have trouble acquiring the plugin, you can try using "http" in the URL, instead of "https" (https is preferred for security reasons).

Click OK.
4. Back in the Available Software view, you should now see "Developer Tools" added to the list. Select the checkbox next to Developer Tools, which will automatically select the nested tools Android DDMS and Android Development Tools. Click Next.
5. In the resulting Install Details dialog, the Android DDMS and Android Development Tools features are listed. Click Next to read and accept the license agreement and install any dependencies, then click Finish.
6. Restart Eclipse.


このあとEclipseで使えるようにするには「Window->preferences->android」でAndroid SDKのパスを入力しないといけないようです。(今回の場合~/android-sdk-linux_86)

インストールもうまくいったので早速Hello, Worldを参考にプログラムを作ってみます。

まず事前にエミュレータの設定をする必要があるようです。


:~$ android create avd --target 2 --name my_avd
Android 1.5 is a basic Android platform.
Do you wish to create a custom hardware profile [no]
Created AVD 'my_avd' based on Android 1.5


もう一度Eclipseを起動しなおして、プロジェクトを作ります。詳しくはHello, Worldを参照の事。

ここで気になるのはビルドターゲットと最低SDKのバージョンの関係。下記は大事そうなのでメモをしておく。


ここで、選択した「ビルド ターゲット」で Android 1.1 プラットフォームが使用されることに注目してください。これは、作成するアプリケーションが Android 1.1 プラットフォームライブラリをターゲットとしてコンパイルされることを意味します。先ほど作成した AVD は Android 1.5 プラットフォームで実行されます。バージョンの数字が一致しませんが、Android アプリケーションには上方互換性があるため、1.1 プラットフォーム ライブラリをターゲットとして構築されたアプリケーションでも 1.5 プラットフォームで正常に動作します。ただしその逆の場合は正常に動作しません。


下記はサンプルのソースコードです。


package com.example.helloandroid;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
tv.setText("Hello, Android");
setContentView(tv);
}
}


コンパイルして実行してみます。どうもエミュレータ起動までものすごく時間がかかるようで計測したら1分15秒かかりました。
ここからがかなり大事なのですがAndroidの開発をEclipseでやる場合エミュレータの再起動は必要ありません。修正後、再コンパイルして実行すればエミュレータに最新のプログラムがインストールされます。エミュレータから操作してアプリを再起動させると反映されています。

GoogleAppEngine-RPCの使い方


前回のJDOQLクエリフィルタに引き続き、RPCによるGWTとサーバーの通信を実装します。RPCとは簡単に言うと、クライアントとサーバーでJavaのクラスをそのままやりとりするための通信方式です。

通常AJAXでの通信はXMLもしくはJSOPで行いますが、通信毎にプロトコルの仕様を決めなければなりませんでした。しかしGoogleAppEngineJavaはクライアント画面のGWTとサーバーの両方で使えるJavaのクラスを定義すれば簡単にデータのやりとりができます。

RPCでの通信を行うにはいくつか準備する必要があります。

・通信でやりとりされるオブジェクト
・RemoteServiceインターフェースとサーバー側の実装
・通信結果を受け取る非同期インターフェース

今回はつぶやき情報をサーバーに送る機能を実装してみようかと思います。

TweetPutParam.java
---------------------------

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

public class TweetPutParam implements IsSerializable {
public String tweet;
public double x;
public double y;
public double z;
}

このクラスはつぶやきと、つぶやいた位置情報を保持しています。ここでのポイントはcom.google.gwt.user.client.rpc.IsSerializableクラスをimplemntsしていることです。このインターフェースを使うだけでコンパイル時にシリアライズ処理が実装されるようです。

TweetService.java
---------------------------

package com.devtter.client.rpc;

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

@RemoteServiceRelativePath("tweet")
public interface TweetService extends RemoteService {
public String put(TweetPutParam param) throws IllegalArgumentException;
}


TweetServiceAsync.java
---------------------------

package com.devtter.client.rpc;

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

public interface TweetServiceAsync {
void put(TweetPutParam param, AsyncCallback callback)
throws IllegalArgumentException;
}


ここまでがインターフェースの定義です。サーバー側では定義されたTweetServiceをサーブレットとして実装します。具体的にはRPCを処理するcom.google.gwt.user.server.rpc.RemoteServiceServletを実装します。
今回のサンプルではクライアントでつぶやかれた内容をJDOに格納します。

TweetServiceImpl.java
---------------------------

package com.devtter.server.rpc;

import com.devtter.server.model.Tweet;
import com.devtter.server.model.TweetDAO;
import com.devtter.client.rpc.TweetGetParam;
import com.devtter.client.rpc.TweetPutParam;
import com.devtter.client.rpc.TweetResponse;
import com.devtter.client.rpc.TweetService;
import com.devtter.shared.FieldVerifier;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import java.util.logging.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;

@SuppressWarnings("serial")
public class TweetServiceImpl extends RemoteServiceServlet implements TweetService {
private static final Logger log = Logger.getLogger(TweetServiceImpl.class.getName());

public String put(TweetPutParam param) throws IllegalArgumentException{
if (!FieldVerifier.isValidTweet(param.tweet)) {
throw new IllegalArgumentException(
"Tweet must be at less 140 characters long");
}
log.info("put : " + param.tweet);
TweetDAO.tweetAnonymous(param.tweet);
return "";
}
}


次にクライアント側で、つぶやきを送る処理を実装します。実装はちょっと難解な書き方をしますが、まずTweetServiceAsyncをGWTクラスから生成します。これで呼び出す準備ができます。次に実際にコールするときはパラメータとレスポンスを指定することで呼び出すことができます。

TweetPanel.java
---------------------------

private final TweetServiceAsync tweetService = GWT
.create(TweetService.class);

public void sendTweetToServer() {
TweetPutParam putParam = new TweetPutParam();
putParam.tweet = inputPanel.inputBox.getText();
if (!FieldVerifier.isValidTweet(putParam.tweet)) {
return;
}

tweetService.put(putParam,
new AsyncCallback() {
public void onFailure(Throwable caught) {
}

public void onSuccess(String result) {
}
});
}


以上でRPCによるサーバークライアント通信の処理は完了です。慣れるまで敷居が高いですが、一度作ってしまえば、通信内容を変更する時は通信クラスのパラメータをかえるだけで対応出きるのでとても便利です。

なお、今回作ったプログラムは下記に置いてあります
http://code.google.com/p/devtter/source/browse/#svn/trunk/devtter/src/com/devtter/client/rpc
http://code.google.com/p/devtter/source/browse/#svn/trunk/devtter/src/com/devtter/server/rpc
http://code.google.com/p/devtter/source/browse/#svn/trunk/devtter/src/com/devtter/client/ui/tweet

2010年4月10日土曜日

GoogleAppEngine-JDOQLクエリフィルタの使い方

前回のGoogleAppEngine-GWTの使い方の続きです

今回はGWT UIとサーバーを連携させる前に、JDOQLの高度なフィルタ機能を少し説明します。

JDOQLはSQLのような構文でGoogleのストレージを操作することができます。基本的には文字列で条件文を記述すれば操作はできますが、JDOQLにJavaのクラスを混ぜたいときがあります。例えば、オブジェクト内にDateクラスが含まれていて、ある日時以降のデータを検索したい場合です。
そういったときに、JDOQLのクエリフィルタAPIを使用し、高度な条件を指定します。今回は、「指定した位置から指定個数検索する」と「指定時間以降のデータを指定個数検索する」の二つの機能を作ってみます。


Tweet.java
----------------------------------


package com.devtter.server.model;

import java.util.Date;
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;
import com.google.appengine.api.users.User;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Tweet {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;

@Persistent
private User googleId;

@Persistent
private String content;

@Persistent
private Date date;
}


TweetDAO.java
----------------------------------

package com.devtter.server.model;

import java.util.List;
import java.util.Date;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;


public class TweetDAO {

/**
* 指定した位置から指定個数のつぶやきを検索します
*
*
* @param start 開始位置
* @param num 個数
* @return Tweetクラスのリスト
*/
public static List find(int start, int num) {
PersistenceManager pm = PMF.get();
String query = "select from "
+ Tweet.class.getName()
+ " order by date desc range "
+ start + "," + num;
List tweets = (List) pm.newQuery(query).execute();
pm.detachCopyAll(tweets);
pm.close();
return tweets;
}

/**
* 指定時間以降につぶやかれたTweetを検索します。
*
* @param starttime 開始時間
* @param num 個数
* @param desc 降順にするかどうか。
* @return Tweetクラスのリスト
*/
public static List findBeforeStartTime(long starttime, int num, boolean desc) {
PersistenceManager pm = PMF.get();
Date dateStartTime = new Date(starttime);
Query query = pm.newQuery(Tweet.class);
query.declareImports("import java.util.Date");
query.declareParameters("Date ParamStartDate");
query.setFilter("date > ParamStartDate");
if(desc)
query.setOrdering("date desc");
else
query.setOrdering("date asc");

query.setRange(0,num);

List tweets
= (List) pm.newQuery(query).execute(dateStartTime);
pm.detachCopyAll(tweets);
pm.close();
return tweets;
}
}


一つ目のfind関数では、クエリフィルタAPI使わず文字列で検索文を作成し、実効しています。この処理はおおよそ下記のような文字列になります。

select from com.devtter.server.model.Tweet order by date desc range 0, 5

次にfindBeforeStartTime関数ではTweetクラスのDateオブジェクトが指定した日時以降かを条件に検索しています。この処理をするにはまず、declareImports関数でDate型をimportします。これによりQueryクラス内でjava.util.Dateクラスが使えるようになります。次にdeclareParameters関数で変数を宣言します。そして、setFilter関数で条件判定を指示しています。ここで指定しているParamStartDate変数に値を代入するには、検索実行時のexecute関数の引数に変数を代入します。

Twitterのようなアプリケーションを実際に作り込むと、必ず高度な条件での検索が必要になるのでクエリフィルタは重要な機能ですね。
なお今回のプログラムはおおよそ下記にあります。
http://code.google.com/p/devtter/source/browse/trunk/devtter/src/com/devtter/server/model/TweetDAO.java

GoogleAppEngine-GWTの使い方


前回のJDOに引き続き今回はGWTをGoogleAppEngine上で取り扱ってみます。

GWTとは簡単にいえば、JavaのAWTににたライブラリでアプレットのように画面を開発すると、それがJavaScriptに自動的に置き換わる開発キットのことです。
C++やJavaなどで組み込み系やWindows環境でGUIを開発してきたエンジニアにとって、HTMLやJavaScriptは開発スタイルの毛色が異なってやり辛いのですが、こういったクロスコンパイラがあれば今までのやり方でリッチなWEB画面が作れるので、GWTはとても魅力的に感じます。

では早速画面を構成するクラスを提示してみます。今回も引き続きTwitterのようなサイトを作るので、「メインパネルにテキストボックス、送信ボタン、つぶやきリスト」が出てくる部品を作ります。なお、このサンプルはEclipseのGAEプラグインが入っていて、「Web Application Project」というプロジェクトテンプレートを使った開発を想定しています。





TweetPanel.java 画面の部品がすべて乗ってくるパネル
-----------------------------

package com.devtter.client.ui.tweet;
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.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Label;

public class TweetPanel extends VerticalPanel {
public TweetInputPanel inputPanel;
public TweetListPanel listPanel;

public TweetPanel(){
this.inputPanel = new TweetInputPanel();
this.listPanel = new TweetListPanel();
super.add(inputPanel);
super.add(listPanel);

MyHandler handler = new MyHandler();
inputPanel.sendButton.addClickHandler(handler);
inputPanel.inputBox.addKeyUpHandler(handler);
}

class MyHandler implements ClickHandler, KeyUpHandler {
public void onClick(ClickEvent event) {
}

public void onKeyUp(KeyUpEvent event) {
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
}
}

private void sendTweetToServer() {
}
}
}


TweetPanelクラスのMyHandlerと言うインナクラスはパネルに対するイベント処理を行います。ここではキーイベントとクリックイベントのリスナが用意されており、送信ボタンが押されたときなどはここにサーバーへの通信処理を記述します。


TweetInputPanel.java 入力用のテキストボックスと送信ボタン
-----------------------------

package com.devtter.client.ui.tweet;

import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.TextBox;

public class TweetInputPanel extends HorizontalPanel {
public TextBox inputBox;
public Button sendButton;

public TweetInputPanel() {
inputBox = new TextBox();
sendButton = new Button("Send");
sendButton.addStyleName("sendButton");
super.add(inputBox);
super.add(sendButton);
inputBox.setFocus(true);
inputBox.selectAll();
}
}


TweetListPanel.java つぶやきリスト。ラベルを乗せる
-----------------------------

package com.devtter.client.ui.tweet;
import com.google.gwt.user.client.ui.VerticalPanel;

public class TweetListPanel extends VerticalPanel {
public TweetListPanel(){
}

public void putItem(String content){
TweetListItemPanel item = new TweetListItemPanel();
item.setText(content);
super.insert(item, 0);
}
}


TweetListItemPanel.java 一つ一つのつぶやき。最初はlabelで実装しておく
-----------------------------

package com.devtter.client.ui.tweet;

import com.google.gwt.user.client.ui.Label;;

public class TweetListItemPanel extends Label{
public TweetListItemPanel(){
this("");
}
public TweetListItemPanel(String label){
super(label);
}
}

-----------------------------

これで最低限の画面構成クラスはできました。これを表示するにはメインで使われるHTMLテンプレートにコンテナを記述するのと、そのコンテナにaddするプログラムを記述します。まず、メインが面に対応したHTMLファイルにmainContainerというidを作ります。これにより、この位置にパネルを配置できるようになります。

war/Devtter.html

<h1>devtter</h1>

<table align="center">
<tr>
<td colspan="2" style="font-weight:bold;">What's Happening?</td>
</tr>
<tr>
<td id="mainContainer"></td>
</tr>
<tr>
<td colspan="2" style="color:red;" id="errorLabelContainer"></td>
</tr>
</table>

---------------------------

次にEntoryPointクラスの初期処理に、UIを乗せる記述をします。なおcom.google.gwt.core.client.EntryPointは画面が最初に呼び出されるエントリーポイントを表すクラスです。通常HTMLのテンプレートとセットで扱います。

Devtter.java 画面表示時に最初に呼び出されるクラス

package com.devtter.client;

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

public class Devtter implements EntryPoint {
public void onModuleLoad() {
final TweetPanel tweetPanel = new TweetPanel();
RootPanel.get("mainContainer").add(tweetPanel);
}
}


これでUIのベースができました。次回はサーバーと連携するプログラムを付け足します
今回作成したプログラムはおおよそ下記にあります

http://code.google.com/p/devtter/source/browse/#svn/trunk/devtter/src/com/devtter/client/ui/tweet

GoogleAppEngine-JDOの使い方

GoogleAppEngineの練習としてTwitterのようなサイトを作ってみようと思います。

JDOとは簡単にいえば、Googleの高性能ストレージにデータを保存するためのインターフェースです。今回はJDOを使ってつぶやきデータの保存が出きるような機能を用意してみます。

最初に定義するのはTweetクラスとPositionクラスです。Tweetクラスはつぶやきを表しPositionクラスは発言時の位置情報を表します。ポイントとしてはJDO用のオブジェクトが親子関係になる場合のアノテーションの書き方です。子クラスの方はimport com.google.appengine.api.datastore.Keyをプライマリーキーに使います。

Tweet.java

package com.devtter.server.model;

import java.util.Date;
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;
import com.google.appengine.api.users.User;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Tweet {

@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;

@Persistent
private User author;

@Persistent
private String content;

@Persistent
private Date date;

@Persistent
private Position pos;

public Tweet(User author, String content, Date date) {
this.author = author;
this.content = content;
this.date = date;
}

public Long getId() {
return id;
}

public User getAuthor() {
return author;
}

public String getContent() {
return content;
}

public Date getDate() {
return date;
}

public void setAuthor(User author) {
this.author = author;
}

public void setContent(String content) {
this.content = content;
}

public void setDate(Date date) {
this.date = date;
}

public Position getPotision() {
return pos;
}

public void setPosition(Position pos) {
this.pos = pos;
}
}


Position.java


package com.devtter.server.model;

import java.util.Date;
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;
import com.google.appengine.api.datastore.Key;


@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Position {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;

@Persistent
public double x;
@Persistent
public double y;
@Persistent
public double z;
@Persistent
private Date date;

public Key getKey(){
return key;
}

public Date getDate() {
return date;
}

public void updateDate() {
this.date = new Date();;
}
}


次に、オブジェクトを操作するクラスです。ポイントはdetachCopyAll関数を使って、PersistenceManagerをクローズ後もJDOオブジェクトに参照出きるよう、オブジェクトをデタッチしているところです。簡単に言えばオブジェクトのインスタンスのコピー、Java風に言えばクローンを作成します。これをしないでクローズ後に参照しようとすると下記のエラーが発生します。

org.datanucleus.exceptions.NucleusUserException: Object Manager has been closed

JDOがORマッピングのような作りになっているので、実際にデータをストレージに反映
するタイミングとメモリ上のインスタンスの差分の関係を解決するためにこういった設計に
なっていると思われます。

TweetDAO.java


package com.devtter.server.model;

import java.util.List;
import java.util.Date;
import javax.jdo.PersistenceManager;

public class TweetDAO {

public static void tweetAnonymous(String comment){
Tweet t = new Tweet(null, comment, new Date());
save(t);
}

public static void save(Tweet t) {
PersistenceManager pm = PMF.get();
pm.makePersistent(t);
pm.close();
}

public static List find(int start, int num) {
PersistenceManager pm = PMF.get();
String query = "select from "
+ Tweet.class.getName()
+ " order by date desc range "
+ start + "," + num;
List tweets = (List) pm.newQuery(query).execute();
pm.detachCopyAll(tweets);
pm.close();
return tweets;
}
}



この作りでデータを格納していくと、もしこれがMySQLなどであれば一つのテーブルにすべてのつぶやきが入ってしまうことになります。しかしGoogleAppEngineの説明を読む限り、GAE上でJDOを使う限りは負荷分散は自動化されるようです。この作りで大量にデータを投入し、パフォーマンスがどうなるか実験してみようかと思います。


引用:
Google App Engine なら、そのようなことを気にする必要はありません。
App Engine のインフラは、シンプルな API を使って、データの配布、
複製、負荷分散を一手に引き受けます。ユーザーは強力なクエリ エンジン
とトランザクションのメリットを享受できます。



今回使ったプログラムはおおよそ下記にあります。

http://code.google.com/p/devtter/source/browse/trunk/devtter/src/com/devtter/server/model/

2010年4月7日水曜日

Qt4 で 「手抜き」OpenGL入門


前回、UbuntuでOpenGLとQtの環境を作ることを説明した続きです。

まず、OpenGLの一番有名な床井先生の入門サイトの紹介です

GLUTによる「手抜き」OpenGL入門 和歌山大学 システム工学部 デザイン情報学科 床井浩平

このサイトではGLUTを使ったサンプルや説明がされています。OpenGLの説明自体は前述のサイトを参照していただくとして、今回はこのサイトで取り上げられているサンプルを、GLUTではなく、Qt4のQGLWidgetで実装してみます。ソースコードは下記です。


http://svn.xp-dev.com/svn/algos/algos3d/qt4sample/sample02/


コンパイルと実効は下記です

----------------
make
./sample02

----------------

実行するとQtの画面上でキューブが回転します。今回はQGLWidgetとQThreadを使います。
OpenGLのバッファの制御はQGLWidgetを使っています。ただし、これだけだとアニメーション処理ができないので、QThreadクラスを使って連続描画を行っています。

GLUTはWindowsに持っていった時に終了イベントがとれなかったり、UIも日本語対応が甘かったり意外と融通が効かないので、Qtベースでの実装も試してみると良い事があるかもしれません。


MyGLWidget.h
----------------------------

#include "qapplication.h"
#include "qthread.h"
#include "qgl.h"

#ifndef MYGLWIDGET_H_
#define MYGLWIDGET_H_

class MyGLWidget : public QGLWidget, public QThread
{
Q_OBJECT;
public:
MyGLWidget();
protected:
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
void run();
double r;
};

#endif /* MYGLWIDGET_H_ */

MyGLWidget.cpp
----------------------------
#include "MyGLWidget.h"

MyGLWidget::MyGLWidget()
{
QThread::start();
}

void MyGLWidget::initializeGL()
{
glEnable(GL_DEPTH_TEST);
glClearColor( 1.0, 1.0, 1.0, 1.0 );
}

void MyGLWidget::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}

void MyGLWidget::paintGL()
{
GLdouble vertex[][3] = {
{ 0.0, 0.0, 0.0 }, /* A */
{ 1.0, 0.0, 0.0 }, /* B */
{ 1.0, 1.0, 0.0 }, /* C */
{ 0.0, 1.0, 0.0 }, /* D */
{ 0.0, 0.0, 1.0 }, /* E */
{ 1.0, 0.0, 1.0 }, /* F */
{ 1.0, 1.0, 1.0 }, /* G */
{ 0.0, 1.0, 1.0 } /* H */
};

int face[][4] = {
{ 0, 1, 2, 3 },
{ 1, 5, 6, 2 },
{ 5, 4, 7, 6 },
{ 4, 0, 3, 7 },
{ 4, 5, 1, 0 },
{ 3, 2, 6, 7 }
};
GLdouble color[][3] = {
{ 1.0, 0.0, 0.0 },
{ 0.0, 1.0, 0.0 },
{ 0.0, 0.0, 1.0 },
{ 1.0, 1.0, 0.0 },
{ 1.0, 0.0, 1.0 },
{ 0.0, 1.0, 1.0 }
};

int i,j;

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();
gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

if(r>360)r=0;
glRotated(r, 0.0, 1.0, 0.0);
glRotated(r+=2, 1.0, 1.0, 0.0);

glBegin(GL_QUADS);
for (j = 0; j < 6; ++j) {
glColor3dv(color[j]);
for (i = 0; i < 4; ++i) {
glVertex3dv(vertex[face[j][i]]);
}
}
glEnd();
}

void MyGLWidget::run()
{
while(1){
QThread::usleep(10000);
update();
}
}

2010年4月6日火曜日

初めてのDeploy




何とかアプリケーションアカウントを設定後、Eclipseプラグインから
シンプルなスケルトンを作成し、deployボタンを押しつつメールアドレスやら
パスワードを設定したらなんと!
動きました!!

http://devtter.appspot.com/

この環境はすごい。Eclipseと完全に連動している。完全に時代は変わった。

GoogleAppEngineアカウント取得!


GoogleAppEngineのアカウントが急に取得できました!
諦めてアマゾン使おうかと落ち込んでいたら急にgmailにメールが
きてちょっと感動!
問い合わせフォームから書き込んだのがよかったのかな?

GoogleAppEngineのダッシュボードが何だか作戦会議室見たいでかっこいいです。


-
Hello,
You're receiving this email because you indicated you'd had some problems verifying your Google App Engine account using SMS. We just wanted to let you know we've enabled your account--you should be able to create applications now!
To start creating applications with Google App Engine, simply follow this link:
https://appengine.google.com/
Thanks!
The Google App Engine Team


俄然やる気が出てきました!

2010年4月5日月曜日

Ubuntu aptコマンドメモ パッケージ情報表示

Ubuntuでよく忘れるコマンドのメモです。

パッケージの情報表示

apt-cache show <パッケージ名>

パッケージを探す

apt-cache search "パターン"

インストールされたパッケージ一覧を表示する

dpkg -l

2010年4月4日日曜日

Qt4とQGLWidget


「Qt使って練習がてらオープンソースやってみない?」と誘われたのがきっかけ
でQtを調べてみたのですが、どうもこのQtライブラリはかなり整備されていて驚
きました。
どうやらQtデベロップメントフレームワークス社で開発されたC++用のオープン
ソースのアプリケーションフレームワークのようです。
クロスプラットフォーム対応を目指しているようで、Lunix, Windows, Macの
グラフィックやネットワークAPIの差を吸収してくれそうな期待が持てます。
採用実績としてはWeb ブラウザ OperaやGoogle Earthで使われているようです。

ドキュメントは下記のようです。
http://doc.trolltech.com/4.6/index.html

OpenGL関係もC++で使いやすくラッピングしているようで、デモを見るかかぎり
3Dグラフィック上に2DのGUIも載せれるようなので、ゲームの開発もなかなか
やりやすいのではないでしょうか。

http://doc.trolltech.com/4.6/demos-boxes.html


OpenGLの実装は下記のWidgetを使いつつOpenGLのAPIを組み合わせて描画するようです。
QGLWidget Class Reference:
http://doc.trolltech.com/4.6/qglwidget.html



ブラウザではちょっと厳しいアプリ開発をやるときはなかなか良さそうです。

UbuntuでQt4 + OpenGL

UbuntuにQt4ベースのOpenGL開発ライブラリを追加する。

------------------------------------------------
sudo apt-get install qt4-qmake
sudo apt-get install libqglviewer-qt4-dev
------------------------------------------------

開発ライブラリが入ったのでプロジェクトフォルダを作りそこにとりあえず
簡単な画面を出すプログラムを配置する。

------------------------------------------------
mkdir sample
cd sample
------------------------------------------------

sampleディレクトリにmain.cppというファイルを配置する。


------------------------------------------------

#include "qapplication.h"
#include "qgl.h"

int main(int argc, char *argv[])
{
QApplication window(argc, argv);
QGLWidget *mainwindow = new QGLWidget;
window.setActiveWindow(mainwindow);
mainwindow->show();
return window.exec();
}

------------------------------------------------

このmain.cppを配置した状態でqmakeを実行すると、このプログラムを認識したうえで
プロジェクトの雛形が作成される。


------------------------------------------------
qmake-qt4 -project
------------------------------------------------

出来上がったsample.proにOpenGLオプションを追記する

------------------------------------------------
QT += opengl
------------------------------------------------

下記のコマンドでMakefileを生成する

------------------------------------------------
qmake-qt4
------------------------------------------------

下記コマンドでコンパイルができる。

------------------------------------------------
make
------------------------------------------------

./sampleを実行すると真っ黒なだけのWindowsが出れば下準備は完了。

まとまったサンプルはこちら
http://svn.xp-dev.com/svn/algos/algos3d/qt4sample/sample01/


GoogleAppEngineのSMSメールが来ない

Google App Engine はローカル環境でも十分開発できるのだが、やはり
Google側にアカウントを用意しておきたい。作ったものが公開できる
保証がないと落ち着かないので。

しかし一晩待っても携帯電話にGoogle App EngineのSMS verification
messageメールがこないので下記のFAQを読んでみた。

http://code.google.com/intl/ja/appengine/kb/sms.html


-----------------------------------
現在問題が発生している携帯サービス会社

現在、次の携帯サービス会社への SMS メッセージ送信には問題があります。

* 日本 - DoCoMo
* 日本 - KDDI

確認コードを記載した SMS メッセージを受信できない場合は、SMS の問題のフォームに記入してください。
-----------------------------------


どうも携帯電話のメール送信が完全ではないようだ。
しょうがないので下記の申告フォームに調べてもらえるように書いてみる。

http://appengine.google.com/waitlist/sms_issues

とりあえずしばらくまた待つことにする。

路線変更

GoogleCodeを使っていたら、GoogleAppEngineが便利そうなことに
気づいたのでこちらを試すことに。

試しに下記から開発用のアカウントをとろうかと思ったのですが

https://appengine.google.com/start

携帯電話のアドレスを入れてもエラーがでるばかりでよくわからない
明日またチャレンジ。

2010年4月2日金曜日

「C++でWebAppを書きたいんだが、フレームワーク作ってみる」
と友達にいったら、Webサービスの方が需要があるんじゃないかと
言われたので、路線変更してそちらも調べてみることに。

GoogleAppEngineを調べてみると、Eclipseプラグインでスラスラ
作れるようなので開発環境だけ整えてみました。

今日はこのくらい。