2010年10月5日火曜日

AppEngineの設定

どうもユーザガイド的なものをである調で書くと書きにくいのでg3関連は文体を変えることにしました。

さて、g3 version 0.2では、Google AppEngineをサポートしました。

今回はEclipseによる開発環境でg3アプリケーションをGoogle AppEngine上で動作させるセットアップ手順について説明します。


前提


本記事の前提として以下の環境が整っていることとします。


  • EclipseによるGoogle AppEngine開発環境
  • g3アプリケーションのインストール(g3-0.2-bin.zipを展開またはg3-0.2-jar-with-dependencies.jarの配備)

JARファイル

g3アプリケーションのコンパイルや実行に必要なJARファイルを開発環境にコピーします。

コピー先はwar/WEB-INF/libです。コピー後、BuildPathの設定を行ない、コピーしたJARファイルをライブラリとして有効にします。

コピー元には以下の2つの選択肢があります。

  • g3-0.2-bin.zipを展開したディレクトリのlib配下にあるすべてのJARファイル
  • g3-0.2-jar-with-dependencies.jar

後者のg3-0.2-jar-with-dependencies.jarを一つだけコピーする方法が簡単でよいのですが、本番環境に配備時にJARファイルが大きすぎるというエラーになります。このため、開発環境でちょっと試したい場合のみに利用するとよいでしょう。

g3アプリケーションを作成

簡単に試す場合には、本ブログで紹介している基本組込みのサンプルプログラムを使ってもよいでしょう。

web.xml

サーブレットの設定ファイルwar/WEB-INF/web.xmlを設定します。

サーブレットとしてorg.goldenport.g3.servlet.AppEngineServletを設定します。また、g3アプリケーションは、サーブレットのパラメタg3.applicationに指定します。以下の例ではorg.goldenport.g3.app.HelloWorldを指定しています。

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
    <!-- Servlets -->
  <servlet>
    <servlet-name>g3</servlet-name>
<servlet-class>org.goldenport.g3.servlet.AppEngineServlet</servlet-class>
    <init-param>
      <param-name>g3.application</param-name>
      <param-value>org.goldenport.g3.app.HelloWorld</param-value>
    </init-param>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>g3</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
  
  <!-- Default page to serve -->
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>

</web-app>

application-web.xml

続けてAppEngineの定義ファイルであるwar/WEB-INF/application-web.xmlを設定します。必要最小限の設定の場合は、以下のようになります。

application-web.xml
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <application>yourappname</application>
  <version>1</version>
</appengine-web-app>

この例では、AppEngineのアプリケーション名としてyourappnameを指定しています。このため、配備後はhttp://yourappname.appspot.comでアプリケーションを実行することができます。

配備

以上で設定は完了です。 配備ボタンを押して、アプリケーションを配備します。

まとめ

g3アプリケーションをGoogle AppEngine上で動作させる上で一番難しいのが必要なJARファイルの複写のところです。それ以外はごく普通のAppEngineアプリケーションの設定を行うだけです。

サーブレットとしてorg.google.g3.servlet.AppEngineServletを使用することと、サーブレットパラメタg3.applicationにg3アプリケーションのクラス名を記述するのがポイントです。

2010年10月3日日曜日

g3 version 0.2

メッセージング・フレームワークg3のバージョン0.2を公開した。


  • g3-0.2-bin.zip:配布バイナリ。unzipして使用。
  • g3-0.2-jar-with-dependencies.jar:java -jar g3-0.2-jar-with-dependencies.jarで直接使用。

g3 0.2では、Google AppEngineをサポートした。同じg3アプリケーションが、LAMP上でもAppEngine上でも動作する。

また、データストアやWeb UIの改良も行っている。

明日から、各機能の使い方を順に説明していく。

2010年10月2日土曜日

Hello Web & CLI

HelloWorldやHelloCliでは、"Hello World"という文字列を生成するだけだったので、Webアプリケーションとしては最低限動くというレベルだった。
g3アプリケーションHelloWebでは、Web用にHTMLを生成することで、この問題を解決することができた。
その一方で、HelloWebをコマンドラインから実行してもHTMLが出力されることになる。
Webから実行した場合はHTML、コマンドラインから実行した場合は文字列を出力する、といったように起動方法によって出力するフォーマットを変えたいところである。
この目的を達成するためにHelloWebを拡張したものが以下のHelloWebCliである。

HelloWebCli.sdoc
package org.goldenport.g3.app

import org.goldenport.g3._
import org.goldenport.g3.messages._

class HelloWebCli extends G3Application {
  agent('hello) {
    case _ => "Hello World"
  }

  html('web, "Hello") {
<body>
<h1>Hello</h1>

<g.string/>

</body>
  }

  start invoke("hello")
  port("/") invoke("hello") invoke("web")
}

コマンドラインから起動したときはstartチャネルが、Webからパス「/」をアクセスしたときはportチャネル「/」が実行されることを利用して、startチャネルにはコマンドラインから実行した時の処理、portチャネル「/」にはWebから実行した時の処理を記述している。
ただし、コマンドラインからでもWebからでもアプリケーションロジックは変わらず、出力フォーマットのみが変わるようにしたいので、アプリケーションロジックのみを実行するagentチャネル「hello」を定義している。agentチャネル「hello」は文字列"Hello World"を返す。
コマンドラインからstartチャネルが呼び出されると、agentチャネル「hello」が呼び出され、その結果返された文字列"Hello World"がコンソールに出力される。
一方、portチャネル「/」が呼び出されると、つまりWebのパス「/」が呼び出されると、invokeエージェント経由でagentチャネル「hello」が呼び出される。その"Hello World"の文字列が返されるけれど、この文字列がパイプラインを経由してhtmlチャネル「web」に渡されて、HTMLが生成され、最終的にこのHTMLがHTTPのレスポンスとしてクライアントに返される。このようにパイプライン上にメッセージを流していくのが、g3のプログラミングモデルである。
htmlチャネル「web」ではHTML文書内に「<g.string/>」のタグが記述されている。このタグはhtmlチャネルの入力となった文字列に置換される。この場合は"Hello World"ということになる。

実行


それでは、org.goldenport.g3.app.HelloWebCliを実行してみよう。HelloWebは、g3フレームワークに同梱しているので直接実行することができる。
g3.serverスイッチを用いてJettyベースのWebアプリケーションとして実行することができる。

$ g3 -g3.application:org.goldenport.g3.app.HelloWebCli -g3.server

トップページにアクセすると以下のようにチャネルwebで定義したWebページにチャネルhelloで生成した文字列"Hello World"を埋め込んだものが表示される。



コマンドで実行


次はHelloWebCliをコマンドラインから実行してみよう。
以下のように、コンソールには「Hello World」の文字列が出力される。

$ g3 -g3.application:org.goldenport.g3.app.HelloWebCli
Hello World

2010年10月1日金曜日

htmlチャネル

HelloWorldプログラムでは、コマンドとWebの両方で同じプログラムが実行できた。ただし、出力する情報が"Hello World"の文字列であり、Webアプリケーションとしては最低限の仕事というところ。きちんとレイアウトしたHTMLを出力したいところである。

HelloWorld.sdoc
package org.goldenport.g3.app

import org.goldenport.g3._
import org.goldenport.g3.messages._

class HelloWorld extends G3Application {
  port("/") agent {
    case _ => "Hello World"
  }
}

このような目的には、様々な情報を埋め込んでレイアウトしたHTMLを出力するためのチャネルであるhtmlチャネルを使用する。
g3アプリケーションHelloWeb.scalaでは、htmlチャネルを用いてHTMLページを定義している。
portチャネル「/」が呼び出されると、つまりWebのパス「/」が呼び出されるとinvokeエージェント経由でhtmlチャネル「hello」が呼び出され、htmlチャネル「hello」が生成したHTMLが返され、最終的にクライアントに返される。
htmlチャネルでは、ScalaのXMLリテラルを使用してHTML文書を直接記述する。また、HTMLのhead要素はhtmlチャネル側で生成するのでbody要素のみを定義すればよい。

HelloWeb.scala
package org.goldenport.g3.app

import org.goldenport.g3._
import org.goldenport.g3.messages._

class HelloWeb extends G3Application {
  html('hello, "Hello") {
<body>
<h1>Hello</h1>

Hello World!

</body>
  }

  port("/") invoke("hello")
}


実行


それでは、org.goldenport.g3.app.HelloWebを実行してみよう。HelloWebは、g3フレームワークに同梱しているので直接実行することができる。
g3.serverスイッチを用いてJettyベースのWebアプリケーションとして実行することができる。

$ g3 -g3.application:org.goldenport.g3.app.HelloWeb -g3.server

トップページにアクセすると以下のようにチャネルhelloで定義したWebページが表示される。

2010年9月30日木曜日

startチャネル

以下のHelloWorldプログラムでは、コマンドとWebの両方で同じプログラムが実行できた。

一方で、コマンドからのみ起動したいプログラムを記述したい場合もある。


HelloWorld.sdoc
package org.goldenport.g3.app

import org.goldenport.g3._
import org.goldenport.g3.messages._

class HelloWorld extends G3Application {
  port("/") agent {
    case _ => "Hello World"
  }
}

そのような場合に使用するのがstartチャネルである。startチャネルを使用したHelloWorldプログラムが以下のHelloCli.scala。

startチャネルから"Hello World"を出力するエージェントを呼び出している。


HelloCli.scala
package org.goldenport.g3.app

import org.goldenport.g3._
import org.goldenport.g3.messages._

class HelloCli extends G3Application {
  start agent {
    case _ => "Hello World"
  }
}


実行


それでは、org.goldenport.g3.app.HelloCliを実行してみよう。HelloCliは、g3フレームワークに同梱しているので直接実行することができる。

以下のように-g3.applicationスイッチでg3アプリケーションorg.goldenport.g3.app.HelloCliを指定して実行する。引数にポート「/」は指定していない。

実行の結果、"Hello World"がコンソールに出力された。


$ g3 -g3.application:org.goldenport.g3.app.HelloCli
Hello

2010年9月29日水曜日

Webアプリケーション

g3は、RESTアーキテクチャを一つの軸にしている。具体的には、メッセージフローとしてチャネルやエージェント間を流れるメッセージとしてRESTのGETやPOST、そのコンテンツとしてAtomFeedやHTMLを用いている。
g3では、GETやPOSTに対してHTMLページを返信することで、通常のWebアプリケーション的なUIを構築することができる。
具体例として、3つのWebページを配信するWebアプリケーションUsageをみていこう。

Usage.scala
package org.goldenport.g3.app

import org.goldenport.g3._
import org.goldenport.g3.messages._

class Usage extends G3Application {
  html('top, "g3 Getting Started") {
<body>
<h1>g3 Getting Started</h1>

Getting Started.
</body>
}

  html('cli, "CLI") {
<body>
<h1>Command Line Interface</h1>

Command Line Interface.
</body>
}

  html('web, "Web") {
<body>
<h1>Web</h1>

Using g3 on web browser.
</body>
}

  port("/") invoke("top")
  port("/cli") invoke("cli")
  port("/web") invoke("web")
}

org.goldenport.g3.app.Usageは、ポート「/」、「/cli」、「/web」、チャネル「top」、「cli」、「web」から構成されている。チャネル「top」、「cli」、「web」はいずれもHTMLチャネルで、HTMLページを生成するチャネルである。
htmlチャネルでは、第1引数にチャネル名、第2引数にページタイトル、第3引数にHTMLページに埋め込むHTML断片をXMLリテラルで記述する。HTMLのheader要素などはHTMLチャネルが生成する。
また、ポート「/」、「/cli」、「/web」は、それぞれチャネル「top」、「cli」、「web」を呼び出すようになっている。このため、たとえばポート「/」にアクセスするとチャネル「top」が呼び出され、チャネル「top」が生成したHTMLが返され、最終的にポート「/」の結果としてクライアントに返されることになる。

実行


それでは、org.goldenport.g3.app.Usageを実行してみよう。
Usageは、g3フレームワークに同梱しているので直接実行することができる。
まず、Webアプリケーションとして。
Usageは、以下のようにg3.serverスイッチを用いてJettyベースのWebアプリケーションとして実行することができる。

$ g3 -g3.application:org.goldenport.g3.app.Usage -g3.server

トップページにアクセすると以下のようにチャネルtopで指定したWebページが表示される。



「/cli」や「/web」にアクセすると以下のようにそれぞれ、チャネルcli、チャネルwebで指定したWebページが表示される。





コマンドで実行


Usageはコマンドから実行することもできる。
以下のようにg3.serverスイッチを指定せず、引数に「/」を指定することで、ポート「/」をコマンドから実行することができる。
実行結果として、HTMLページがコンソールに出力されている。

$ g3 -g3.application:org.goldenport.g3.app.Usage /
<html><head><title>g3 Getting Started</title></head><body>
<h1>g3 Getting Started</h1>

Getting Started.
</body></html>

ポート「/cli」、「/web」に対する実行結果は以下の通りとなる。

$ g3 -g3.application:org.goldenport.g3.app.Usage /cli
<html><head><title>CLI</title></head><body>
<h1>Command Line Interface</h1>

Command Line Interface.
</body></html>


$ g3 -g3.application:org.goldenport.g3.app.Usage /web
<html><head><title>Web</title></head><body>
<h1>Web</h1>

Using g3 on web browser.
</body></html>

2010年9月28日火曜日

HelloWorld

Hello Worldのプログラムとして以下のものを用意した。

HelloWorld.sdoc
package org.goldenport.g3.app

import org.goldenport.g3._
import org.goldenport.g3.messages._

class HelloWorld extends G3Application {
  port("/") agent {
    case _ => "Hello World"
  }
}

g3はメッセージフロー・フレームワークであり、g3プログラムはメッセージ・フローとして記述する。
HelloWorldでは、「port("/")」の後ろに「agent {…}」を記述している。これは、チャネル「port」の出力メッセージをエージェント「agent」の入力とし、エージェント「agent」の出力メッセージをチャネル「port」の出力とするという意味である。
チャネルportは、外部に公開されたチャネルでコマンドラインやHTTPで外部からアクセスすることができる。
エージェントagentは、メッセージを処理するScalaプログラムを記述するためのエージェント。Scalaのケースシーケンス句(PartialFunction)を記述する。Hello Worldでは、「すべての場合に"Hello World"」を出力する、というScalaプログラムが記述されている。
まとめると、Hello Worldは、外部に公開されたチャネル「/」にアクセスがあると、"Hello World"を返すという処理を行うプログラムである。


コマンドで実行


org.goldenport.g3.app.HelloWorldは、本体のjarに入れているので、特に設定なしで、そのまま実行することができる。
-g3.applicationスイッチにorg.goldenport.g3.app.HelloWorldを指定すると、g3フレームワーク上でorg.goldenport.g3.app.HelloWorldが実行される。-g3.applicationスイッチに続く「/」はorg.goldenport.g3.app.HelloWorldに対する引数で、実行するポートを指定している。この場合は、port("/")が実行されることになる。

$ g3 -g3.application:org.goldenport.g3.app.HelloWorld /
Hello World

実行の結果、「Hello World」がコンソールに表示された。

Webで実行


g3は、以下のように-g3.serverスイッチを指定することで、Jettyを用いてWebアプリケーションとして実行することができる。

$ g3 -g3.application:org.goldenport.g3.app.HelloWorld -g3.server

Jettyが起動され、g3サービスがWebとして公開される。使用するポートは7865である。
localhost:7865にブラウザでアクセスするとブラウザの画面に「Hello World」の文字が出力される。
g3はサーブレットを用意しているので、g3に組込みのJettyを用いなくても、サーブレットを直接TomcatなどのWebコンテナに登録して動作させることもできる。

ポイント


  • g3アプリケーションは、メッセージフローでプログラムを記述する。
  • g3アプリケーションは、そのままコマンドラインとWebアプリケーションのいずれの方式でも動作させることができる。