Pharo + Seaside で簡単 RESTful サービス

2016.03.02

とあるプログラムのテスト用に、単純な JSON を返却する RESTful サービスを簡単にサクッと作れないかなと思う中、「Pharo Smalltalk」と「Seaside」を使ってみたらとても簡単だったのでご紹介します。

Pharo Smalltalk の準備

基本的にはダウンロードページより各環境用のアーカイブをダウンロードし、任意の場所へ解凍するだけなのですが、Zeroconf Script を用いて構築することもできます。

Windows

アーカイブを解凍した先にある「Pharo.exe」に「Pharo.image」をドラッグアンドドロップします。

Mac OSX

アーカイブを解凍して生成される「Pharo〜.app」をダブルクリックして起動します。

Zeroconf Script

$ cd
$ mkdir rest && cd $_
$ curl get.pharo.org/stable+vm | bash

起動は

$ ./pharo-ui Pharo.image

とします。

起動するとこのようなウィンドウが開きます。

pharo-seaside-restful-service_00

Seaside の導入

World (Desktop) をクリックすると World メニューが開きます。

pharo-seaside-restful-service_01

Configuration Browser を開きたいのでメニューから「Tools > Configuration Browser」を選択します。

pharo-seaside-restful-service_02

Seaside3 を選択して Install Stable Version をクリックします。

pharo-seaside-restful-service_03

しばらく待つとインストールが完了しアイコンが変化します。

pharo-seaside-restful-service_04

Seaside の REST 機能はアドオンとして提供されています。スクリプトを評価して導入を行うので Playground を開きます。

pharo-seaside-restful-service_05

Playground が開いたらここに Smalltalk コードを入力します。

pharo-seaside-restful-service_06

Gofer new
	smalltalkhubUser: #Seaside project: #Seaside30Addons;
	package: 'Seaside-REST-Core';
	package: 'Seaside-Pharo-REST-Core';
	package: 'Seaside-Tests-REST-Core';
	load.

実行ボタンをクリックします。

pharo-seaside-restful-service_07

スクリプトを評価した結果の GoferLoad オブジェクトが返されたら導入完了です。

pharo-seaside-restful-service_08

Web Application Server の起動

Seaside の導入により、World メニューに Seaside Control Panel が追加されます。「Tools > Seaside Control Panel」を選択します。

pharo-seaside-restful-service_09

開いた Seaside Control Panel 上で右クリックするとメニューが開きます。ここから「Add adaptor...」を選択します。

pharo-seaside-restful-service_10

追加するアダプタ「ZnZincServerAdaptor」を選択します。

pharo-seaside-restful-service_11

任意のポート番号を設定します。

pharo-seaside-restful-service_12

一覧に追加されたサーバアダプタを選択し、「Start」をクリックします。

pharo-seaside-restful-service_13

ヒトデのアイコンが明るく変化したらサーバ起動完了です。

pharo-seaside-restful-service_14

イメージの保存(余談)

ここまで「Seasideの導入」「REST アドオンの導入」「アプリケーションサーバの起動」としてきましたが、この状態でイメージを保存しておくと必要な時にすぐ RESTful サービスを作成できるので便利です。(多くの Smalltalk 実装がそうであるように Pharo Smalltalk も仮想マシン上でイメージを展開することで環境が提供されます。VMware や VirtualBox などによる仮想化環境をイメージしてもらえれば理解し易いかと思います。)

World メニューから「Save as...」を選択し「名前をつけて保存」しておきます。

pharo-seaside-restful-service_31

ファイル選択ダイアログが開くので任意のファイル名を指定して保存します。

次回からは、ここで保存したイメージファイルを開けばアプリケーションサーバが起動した状態から始められます。便利ですね。(^_^)

RESTful ハンドラクラスの作成

閑話休題、ここから HTTP リクエストで JSON を返すハンドラを作成するコーディングになります。コーディングには「System Browser」というものを使うので World メニューから選択します。

pharo-seaside-restful-service_15

System Browser 下部のコードペインにクラス定義のテンプレートが表示されています。

pharo-seaside-restful-service_16

Object subclass: #NameOfSubclass
	instanceVariableNames: ''
	classVariableNames: ''
	category: ''

「WARestfulHandler」クラスを継承した「MyHandler」クラスを「Rest-Service」カテゴリに作成します。

pharo-seaside-restful-service_17

WARestfulHandler subclass: #MyHandler
	instanceVariableNames: ''
	classVariableNames: ''
	category: 'Rest-Service'

コードを編集したら「Accept」します。Windows では 「Ctrl + s」、Mac OSX では「Cmd + s」で Accept できます。

MyHandler クラスを Web アプリケーションとして登録するための初期化メソッドを「クラスメソッド」として定義します。クラスメソッドを作成するには「Class side」をチェックします。

pharo-seaside-restful-service_18

MyHandler が表示されているクラスペインの右にあるメソッドカテゴリペインの「no messages」を選択するとコードペインにクラスメソッドのテンプレートが表示されます。

pharo-seaside-restful-service_19

このテンプレートを次のように変更します。

pharo-seaside-restful-service_20

initialize
	WAAdmin register: self at: 'credentials'

このコードは MyHandler クラスを「credentials」という名前のウェブアプリケーションとして登録することを意味します。

こちらも先ほどと同様に Accept すると名前の入力を促されます。環境の Author を指定するだけなので適当に入力して OK ボタンをクリックします。

pharo-seaside-restful-service_21

クラスメソッド「initialize」が定義されました。メソッドカテゴリペインの「-- all --」を選択すると initialize メソッドが作成されたことが分かります。

pharo-seaside-restful-service_22

この initialize メソッドを評価する簡単な方法は、メソッドの左に表示されているスクリプトアイコンをクリックすることです。

pharo-seaside-restful-service_23

「クラスを(再)初期化してもよい?」と聞かれるので Yes ボタンをクリックします。

pharo-seaside-restful-service_24

これで「http://localhost:9090/credentials」が登録されました!

RESTful ハンドラメソッドの作成

後は JSON を返すインスタンスメソッドを定義するだけです。

クラスメソッドを定義する際にチェックした「Class side」のチェックを外し、クラスメソッドの時と同様にメソッドをコーディングします。

pharo-seaside-restful-service_25

メソッドの内容は次のようになります。

pharo-seaside-restful-service_26

credentials
	<get>
	<produces: 'application/json'>

	^ '{
  "Code": "",
  "LastUpdated": "",
  "Type": "",
  "AccessKeyId": "",
  "SecretAccessKey": "",
  "Token": "",
  "Expiration": ""
}'.
1行目
メソッド名
2行目
HTTP メソッドの GET に反応しますよという get プラグマ
3行目
レスポンスとして JSON を返却しますよという produces: プラグマ
5行目以降
返却される JSON 文字列(^ は return を表します。)

Accept して「http://localhost:9090/credentials」へアクセスすると

pharo-seaside-restful-service_27

pharo-seaside-restful-service_28

JSON が表示されました!ブラウザの DevTools などでコンテンツタイプが「application/json」であることも確認できるはずです。

更にメソッドを以下のように変えて Accept すれば

pharo-seaside-restful-service_29

credentials
	<get>
	<produces: 'application/json'>
	| now |
	now := DateAndTime now.
	^ '\{
  "Code": "",
  "LastUpdated": "{1}",
  "Type": "",
  "AccessKeyId": "AKIAIOSFODNN7EXAMPLE",
  "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
  "Token": "",
  "Expiration": "{2}"
\}' format: {now. now + (1 day)}.

pharo-seaside-restful-service_30

このようになります!アプリケーションサーバの再起動などを要せずにすぐ値を変えられるので便利です!

まとめ

今回私はこのような使いかたをしましたが、本来はしっかりとしたウェブアプリケーションを構築できる環境です。この記事で興味を持たれた方はちょっとしたものから便利に使ってみてはいかがでしょうか。

参考