2010年10月10日日曜日

node.jsのrequireを使ってみた!

前回node.jsのインストールが出来てサンプルが表示できたと思います!
前回のサンプルにもあった、require('xxx')という物で遊んでみました。

とりあえず、私自身がJavaプログラマーなので、Javaとの比較で説明したいと思います!

では、requireの説明ですが・・・

requireはimportみたいなものです!

以上!

とりあえず、今回のサンプルを見つつ説明させてください!
var http = require('http');
var url = require('url');
var querystring = require('querystring');
var circle = require('./circle');

http.createServer(function(request, response) {
        response.writeHead(200,{'Content-Type': 'text/plain'});
        var hoge = querystring.parse(url.parse(request.url).query).hoge;
        response.end(circle.area(4) + " " + hoge);
}).listen(8124);

console.log('http://localhost:8124');
require('http'),require('url'),require('querystring')はnode.jsが用意している関数をJavaで言うimportしている感じです。
importして、そこに書いてある変数で受け取っている。そんなイメージ。
使うときは、その変数経由で呼び出すことができます!

ちなみに、hogeパラメータを取得するときは、上記サンプルで書かれている通り、このように書きます。
querystring.parse(url.parse(request.url).query).hoge

で、一個だけ毛色の違うrequire('./circle')は、、、なにかというと
独自で作成した関数になっています。
同一階層にcircle.jsというファイルを置いているので、このように記述しています。

・中身はこんな感じです。
var PI = 3.14;
exports.area = function (r) {
  return PI * r * r;
};

exports.circumference = function (r) {
  return 2 * PI * r;
};

ちなみに、requireはrequireされたファイルからさらにrequireを使っていくこともできます!

2010年10月9日土曜日

node.jsインストールしてみた!

最近よく聞くnode.jsを使ってみました!!

なにかというと、サーバサイドJavaScriptです。
JavaScriptでサーバ側の処理を作れるっていう素敵なものです!

本家:http://nodejs.org/

では、インストールしてみましょう!


$ wget http://nodejs.org/dist/node-v0.2.3.tar.gz
$ tar zxvf node-v0.2.3.tar.gz
$ cd node-v0.2.3

# sslを使わないので
$ ./configure --without-ssl
# sslを使う場合はオプションなしでOK!

$ make
$ make install



インストールに成功したら、、、このサンプルを書いてみましょう!
(といっても本家のexampleをそのまま使っています)

・example.js

var http = require('http');


http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.end('Hello World\n');
}).listen(8124);

console.log('Server running at http://127.0.0.1:8124/');


保存したら、あとは実行するだけ!


$ node example.js


実行したら、URLにアクセスする!
http://localhost:8124/

画面に"Hello World"と出力されていればインストールは成功です!

2010年9月11日土曜日

Kindle3買ってしまったよ!

やっとアメリカからKindle3が届きました!
箱を開けると、こんな感じでした↓
予想以上に箱が小さかった、そして、ここに書かれている文字、、、、これシールじゃなかった!!
Kindleすげー





さっそく、書かれている通りPCに接続してみたら
こんな画面が表示された・・・・



英語、、、、読むか・・・
とりあえず、PCにつなげると何も出来ないことがわかった!

仕方ないので、オライリーで買ったebookのデータだけいれてUSBを抜いてみた!
ドキドキで、画面を表示させ本を選んでみると・・・

おーーーーーーーー!!!!!!
大満足です!

予想以上に小さく、予想以上に見やすく、予想以上に気に入った!
とりあえず、文句なし!


2010年7月25日日曜日

開発合宿やってみた(第4回目-2日目&3日目)

2泊3日の開発合宿の中で一番過酷な2日目がやってきました!
(というか、過酷過ぎてブログ書く暇がなかった・・・)


本当は開発合宿に来る前に、使用する技術要素とかの調査は80%くらいは終わらせておきたかったんだが、、、
業務が忙しくなってしまい1日目は調査で終わってしまいました。
といっても調査すら80%くらいしかできませんでした。。。

そして、2日目・・・
順調に機能を追加していったが、chrome extensionsの罠にはまりまくり辛かった。
さっきは動いていたのに、同じソースで動かなかったり・・・まじ困ります

コンテント・スクリプトはどうやら、拡張機能の再読込だけだと反映されないようで、
画面をリロードする必要があるみたい。
まー、コンテント・スクリプトは画面で動くからそういうものなのか?

ちなみに、夕飯はこんな感じです。
量も味も文句なし!
めっちゃ美味しいです。

2泊3日だと2日目は地獄です・・・
1日目の調査があまりはかどらなかったので、3時間くらいしか寝ていないし、、、
実装中に色々とハマる事があったり、、、

3日目は10時から発表するって決まっていたので、残りXX時間しかないっていうプレッシャーもありつつ
省ける機能は省いたり、どうにか発表に持っていく感じです・・・
でも、この感じがいつも面白い!

そして、最終日!
みんなの発表!
いやー、すごかった!
ちゃんと完成させてきて、いい感じのものを見れた。
残念ながら、私のが一番完成度が低かった・・・

いやー、くやしい!
前回の夏の開発合宿も完成しなかった気がする・・・
やっぱ、夏は事前準備がやりにくいのかな、とりあえず次は事前準備バッチリで望みます!

あっ、こんな感じで花火も楽しんだりしてました!
・・・遊びすぎたか(>_<)/

2010年7月17日土曜日

開発合宿やってみた(第4回目-1日目)

群馬県水上のペンション木馬で第4回目の開発合宿をやっています!
今回は12人の参加で、2泊3日の日程です。
最終日に発表会を行ない、そして帰ります!


開発合宿は冬と夏の年に2回のペースでやっていて、今回で4回目です。
そして、この場所は去年も来ています!

ホームページで開発合宿をうたっているだけあって、開発合宿をやるには最適な場所です!
設備も十分だし、食事の時間とか、チェックアウトの時間とかの融通がすごく聞くのがありがたい!
そして、食事が美味しい!

まだ、1日目だが来年もここでやりたい!

ちなみに、バーベキューも出来ます!

川で遊びすぎたら、怪我したww
そして、はしゃぎすぎてメガネをなくした・・・orz
PC作業用のメガネを持ってきていたのでセーフです。
備えあれば憂いなし!

あー、作るものですが
とりあえずGoogle Chrome Extensionsを使って何かを作ろうと思っています。
果たして完成するか・・・

2010年6月19日土曜日

ATNDから自分の参加するイベント一覧を取得してみた

私はATND というサービスをよく利用します。
このサイトは、イベントの参加登録ができるサイトで、よくIT系のイベントが登録されています。

ATNDはAPIが公開されており、APIを使って自由に検索ができるようになっています。
http://api.atnd.org/

そこで、私自身が参加しようとして登録してあるイベント一覧をこのブログに載せるガジェットを作ってみました。

とりあえず、自分自身が参加登録している一覧を取得するには下記のURLを使用します。
http://api.atnd.org/events/?user_id={個人のID}

私の場合はIDが21348なので
http://api.atnd.org/events/?user_id=21348
となります。

今回はjavascriptで全て実装したいので、jsonp形式でレスポンスをうけとります。
http://api.atnd.org/events/?user_id=21348&count=5&callback=atndCallback&format=jsonp


JSONPについては以前紹介した物がありますので、そちらを参照ください。
JSONPの使い方

作成したガジェット自体は、右の"参加予定のイベント"がそれになります!
javascriptだけで、これだけできるのでやっぱりjavascriptは便利です!
知っておいて損はないなー

・ガジェットのソース
var atndEdit = function() {
 //jsonp
 var url = 'http://api.atnd.org/events/?user_id=21348&count=5&callback=atndCallback&format=jsonp';
 var ele = document.createElement('script');
 ele.type = 'text/javascript';
 ele.src = url;
 document.body.appendChild(ele);
 //今日の日付作製
 var nowDate = new Date();
 var month = (nowDate.getMonth() + 1);
 month = month.length === 2 ? month : '0' + month;
 var day = nowDate.getDate();
 day = day.length === 2 ? day : '0' + day;
 var nowStrDate = nowDate.getFullYear() + month + day;
 //出力先
 var output = document.getElementById('atnd-div');
 var count = 0;
 return {
  disp : function(events) {
   var eventDate = events.ended_at.substring(0, 10).replace(/-/g, '');
   if(eventDate < nowStrDate) {
    if(count == 0) {
     output.innerHTML = '参加予定のイベントはありません';
    }
    return;
   }
   count++;
   var title = events.title;
   var url = 'http://atnd.org/events/' + events.event_id;
   var start = events.ended_at.substring(0, 10);

   var ele = document.createElement('a');
   ele.href = url;
   ele.target = '_blank';
   ele.innerHTML = title;

   var date = document.createElement('span');
   date.innerHTML = '・' + start + '';
   output.appendChild(date);
   output.appendChild(document.createElement('br'));
   output.appendChild(ele);
   output.appendChild(document.createElement('br'));
  }
 };
}();
function atndCallback(data) {
 var events = data.events;
 for(var i = 0; i < events.length; i++) {
  var eventDate = events[i].ended_at.substring(0, 10).replace(/-/g, '');
   atndEdit.disp(events[i]);
 }
}

2010年6月18日金曜日

phpMyAdminを使ってみた

MySQLは以前から使っていたが、基本的にターミナルベースで操作をしていた。

今回は、人が作ったモジュールのテーブルの中身を見たかったので、GUIが欲しくなりインストールしてみました。

といっても、設定は簡単でした。。。

■前提条件
OS: CentOS 5系
Apache: 2系(Apacheインストールを参照)
もちろん、PHPが動くことが必須(PHPが動かない人は、PHPインストールを参照して)

■インストール
とりあえずダウンロードして、解凍する。
今回は、MySQLのバージョンの都合でphpMyAdminが最新のが使えなかったので2系をダウンロードしました。
3系でも基本的に設定は同じなようです。

cd $APACHE_HOME/htdocs
> wget http://sourceforge.net/projects/phpmyadmin/files%2FphpMyAdmin%2F2.11.10%2FphpMyAdmin-2.11.10-all-languages.zip/download
> unzip phpMyAdmin-2.11.10-all-languages.zip
> mv phpMyAdmin-2.11.10-all-languages phpMyAdmin
> cd phpMyAdmin
> cp -ip config.sample.inc.php config.inc.php
> vi config.inc.php
//$cfg['blowfish_secret'] = ''; //ここに適当な文字を入れてあげてください
//$cfg['Servers'][$i]['host'] = 'localhost'; //という項目を見つけ、MySQLのあるサーバ名を記述してください!
以上で、インストールと設定が終わりです。

http://hogehoge/phpMyAdmin
というURLでアクセスすると下記画面が表示されます!
DBのユーザとパスワードをログイン画面に入力すると、ログインできます!
 あとは、直感にしたがって操作すれば、テーブルの中身が見れます!

2010年6月15日火曜日

Geolocation APIを使ってみた

HTML5では位置情報が取得出来るようなので、取得してみました!

緯度経度以外にも、標高も取得出来ます!


・プロパティーの一覧はこんな感じです

位置情報のプロパティcoordsのプロパティ説明
coordscoords緯度
longitude経度
altitude標高(利用できない場合はnull)
accuracy緯度・経度の正確さ(単位はメートル)
altitudeAccuracy標高の正確さ(単位はメートル)
headingデバイスの進行方向。真北に対する時計回りの角度。利用できない場合はnull
speedデバイスの進行速度。利用できない場合はnull
timestamp位置情報を取得した時間(1970/1/1からのミリ秒


-サンプル
GeolocationAPIを一通り使ってみました

緯度経度のみならず、標高も取得出来るのは驚いた。
標高がわかる携帯電話とかから使えば大丈夫なのかな?

2010年6月8日火曜日

HTML5 のWeb Storageを使ってみた

今回は、ローカルストレージと、セッションストレージを使ってみました!

■ローカルストレージ
下記のような 簡単なサンプルを作りました。
storeにて値の登録を行います。そうすると、store dateに登録されている一覧が表示されます。
さらに追加で登録を行うと、下記のようになります。


ローカルストレージのサンプル


・ソース
JavaのHashMapに値を格納するような感覚で使えます!
前回記述した通り、格納した値は消してあげないと消えません。
同一オリジン、同一ブラウザでなら、消されるまで値が保持されます。


■セッションストレージ
セッションストレージのサンプル
キャプチャ的には同じなので貼りません^_^;
基本的には、ローカルストレージのlocalstorageをsessionstorageに置換してあげれば使えます!
API的にも同じものが用意されています!

ただし!
前回説明した通り、別ウィンドウを開くと値はコピーされますが、
その瞬間だけ値が同じなだけでどちらかで更新してももう一方には反映されません!
上記のサンプルにて、試せるようにしてあるので実際に試してみてください。

こちらは、ウィンドウを閉じれば保持していた値は消えるので、特に気になるところはないな。
使い道は、、、別ウィンドウを開くときにパラメータとして渡したいってときぐらいしか使わないか?
渡せるけど、その画面から情報は受け取れないけどねw

■いちおうAPIを書いておきます
・メソッドについて

メソッド解説
lengthストレージ内に格納されているデータ数
key(index)指定されたインデックスのKeyを返す。存在しない場合はnullが返る
getItem(key)指定されたKeyに対応する値を返す
setItem(key, data)ストレージに指定したKey値で値を登録する
removeItem(key)ストレージから指定されたKey値に対応するデータを削除する
clear()すべてのデータをストレージから削除する

・storageイベントのプロパティについて

プロパティ解説
key変更されたKey。clear()メソッドが呼ばれた際にnull
oldValue変更前の値(のコピー)。新しいキーで値が登録された場合はnull。
newValue変更後の値(のコピー)。値が削除された場合にはnull。
urlイベント発生元のドキュメントURL。
storageArea変更されたストレージへの参照。
使い方
なぜか、イベントで処理をするとブラウザがクラッシュすることがありますので、気をつけてください。
使い方が悪いのか?それともブラウザがまだちゃんと対応されていないのか?

2010年6月7日月曜日

HTML5のWeb Storageを使ってみる前に軽くまとめてみた

■Web Storageとは
Web Storageとは、クライアントのディスクにデータを保存出来る仕組みです。
Web Storageは単純な”キー・バリュー”ストレージで、キーは文字列、バリューは任意のJavaScriptオブジェクトとなります。

■Web StorageとCookieの違い
Web Storageと似ている機能に、Cookieがあります。
違いをまとめておきます。

CookieWebStorage
サイズ制限1サイト4KBなし
HTTPリクエストHTTPリクエストに自動的に付加され送信される付加されない
有効期限指定できる指定できない
JavaScriptオブジェクト格納できない格納できる

■Web Storageの種類
Web Storageには、ローカルストレージセッションストレージが存在します。

-ローカルストレージ
Webサイト毎に使用できる、永続化領域の事で永続期間は無制限です。
同一ブラウザ、同一オリジン(プロトコル+ドメイン + ポート番号)にて、共有することができます。

-セッションストレージ
基本的にはローカルストレージと同じ。
ただし、有効範囲と生存期間がwindowオブジェクトと同じになっている。
ウィンドウを閉じられるとセッションストレージ内のデータは削除されます。(再読み込みなら削除されない)
ウィンドウから、別のウィンドウを開いた場合は、ストレージの内容がコピーされて渡されます。
コピーなので、別ウィンドウで書き換えても元のウィンドウには反映されません。逆も同じくコピーされません。

2010年6月1日火曜日

HTML5のWeb Workersを使ってみた

Web WorkersはJavaScriptをバックグラウンドで動かすことができる仕組みです!

バックグラウンドで動くことができるので、重たい処理をJavaScriptで処理させてもブラウザが固まらない!っていうメリットがあります。
使い方によっては、めちゃくちゃ便利だと思います。

ただし、WebWorkersからはDOMを操作ができないので注意!
やらないと思うが、alertも使えないので気をつけてください!

■サンプル1
バックグラウンドで、ひたすらカウントアップした結果を返し表示するだけ
サンプル

-index.html


-worker.js


■解説
①バックグラウンドで実行したいJavaScript(Worker)を指定する
②Workerからのメッセージが送信された際に実行されるイベントを登録する。
③Workerから受け取ったメッセージのデータを取得し、表示させる。
以上が簡単な使い方です!


■サンプル2
バックグラウンドで実行されるWorkerに引数を渡して、それに応じて値を返してもらう
一応、四則演算の結果を返すサンプルにしています。

-index.html


-worker.js
■解説 ①Workerに対して、データを送信する。 ②WorkerがpostMessageをした場合に呼ばれる。 Workerには無駄にカウントアップする処理が含まれている、 通常ならブラウザがロックされてしまい、スクロールができなくなる。 でも、今回はWorkerを使用しているのでDOM側がロックされる事がない。 試しにサンプル画面でスクロールをして見てください。

2010年5月30日日曜日

経済学を勉強してみた(4) -基本的競争モデル-

※経済学を知らない理系人間が経済学を勉強した事を書くだけの記事です。

■基本的競争モデル
基本的競争モデルは3つの構成要素からなる。
(1)消費者がどのように行動するか
(2)企業がどのように行動するか
(3)これらの消費者と企業が依存しあい、交換が行われる市場がどのように動くか

消費者は合理的であると仮定され、企業は利潤極大化を行うと仮定され、市場はきわめて競争的であると仮定される。

ただし、現実の経済がこの競争モデルによっては完全に叙述されない。

-------------------------------------------------------
高いと思ったらみんな買わないわけで、
高くてもみんな買うんだったら企業は価格を上げるわけで、
ここで言っていることは確かにって感じがする。

でも、この競争モデルは完全に経済を叙述していないらしい。
んー、まだ分からないが、、、経済学の勉強を進めて行けばわかるのかな・・・

2010年5月24日月曜日

HTML5のpostMessageを使ってみた

HTML内にあるiframeに対してメッセージを送信することができます。
まずはmain.htmlとframe.htmlのサンプルを見てください!

実際の画面はサンプルを見てください。

■サンプル
-main.html

-frame.html


■解説
otherWindow.postMessage(message, targetOrigin);
-otherWindow
別ウィンドウへの参照。次のような参照が保持されます。例えば、iframe 要素のcontentWindow プロパティの利用、window.open によって返されるオブジェクト、あるいは、 window.frames における名前付きか数による添え字。
-message
送信したい文字列データ
-targetOrigin
イベントが伝達されるべき otherWindow の生成元を "*" というリテラル文字列(指定しないことを示します)か URI のいずれかで指定します。もしイベントが targetOrigin で指定されたものにマッチしない otherWindow の文書のスキーマ、ホスト名、あるいは、ポートに伝達するようになっている場合、そのイベントは伝達されません。つまり、3 つすべてがマッチした場合にだけイベントが伝達されます。この仕組みはメッセージが送られる場所の制御を提供します。例えば、postMessage をパスワードを送るために利用する場合、悪意のある第三者によるパスワードの傍受を防ぐためにこの引数が意図されたパスワードを含むメッセージの受け手と同じ生成元である URI であることは絶対的に致命的なものになるでしょう。

ここで、今回はjson形式の物をframeに対して渡しています!
せっかくjson形式で渡しているのですが、postMessageで扱えるのは文字列だけです。
よって、受け取り側でも文字列として受け取ってしまいます。
なので今回は、evalを使い文字列からjson形式に変換しています。

2010年5月9日日曜日

経済学を勉強してみた(3) -ミクロ経済学とマクロ経済学とは?-

※経済学を知らない理系人間が経済学を勉強した事を書くだけの記事です。

■ミクロ経済学とマクロ経済学
・ミクロ経済学
経済を構成している個々の経済主体、具体的には企業、家計、個人の行動に焦点を当てる。
ミクロ経済では、それぞれの経済主体がどのように選択し、またそのような決定に何が影響を与えているかを取り扱う。

・マクロ経済学
経済全体の行動、全体的な失業率、インフレ率、経済成長率、貿易収支のような集計量の動きを取り扱う。
個々の企業や家計についてではなく、経済全体の事に焦点を当てる。

------------------------------------
んー、経済学を勉強しようとしたキッカケは企業とか会社とかを理解したかったからなので、、、
きっとミクロ経済学を勉強すればいいのかな??
マクロ経済学は、焦点が企業とか会社とかではないので、ミクロ経済学の方を勉強すれば良さそう。

経済学を勉強してみた(2) -3つの主要な市場-

※経済学を知らない理系人間が経済学を勉強した事を書くだけの記事です。

■3つの主要な市場
1.生産物市場(財市場)
企業が自ら生産した財を販売する市場

2.労働市場
家計(個人)が労働サービスを売り、企業がその労働サービスを購入する市場

3.資本市場
資金の借入れや貸出しが行われる市場

※個人は,3つの市場に深くかかわっており,生産物市場では消費者とよばれ,労働市場では,労働者とよばれ,資本市場では,投資家とよばれています.

経済学を勉強してみた(1) -経済学とは何か?-

※経済学を知らない理系人間が経済学を勉強した事を書くだけの記事です。

■経済学とは何か?
社会の資源がどのように選択され、使われるのかを研究する学問。

経済学を理解するためには、トレードオフ、インセンティブ(誘因)、交換、情報、分配という5つの概念を考える必要がある。

・トレードオフとは
ある一つのものをより多く入手することは、他のものをより少ない量しか入手できないことを意味している。
ここで言う、”もの”というの資源、時間などである。
資源は希少であり、トレードオフは基本的に避けられない。

・インセンティブ(誘因)とは
費用と便益を比較する人々の意思決定や行動を変化させるような原因のこと。

・交換
経済学では、交換が起こる状況は全て市場とみなされる。

・情報
選択を行うためには情報が必要である。
情報が他の財と異なる点は、情報は自由に共有できることである。
共有されるだけで情報が減少するわけではない。

・分配
市場は、生産された財とサービスが社会のメンバーにどのように分配されるかを決定する。

HTML5の Canvasで動くものを作ってみた

前回のHTML5の Canvasを使ってみたにて単純な三角形を作ってみました。

ただの三角形だとつまらないので、この三角形を動くようにしてみました!

三角形を動かす仕組みは、setIntervalを使って数秒おきに図形を描いています。

ただーし、図形を描くだけならすぐに出来るのですが、図形を消す方法がわからなかった。
ので、調べました!

context.clearRect(x,y,w,h)を使います!
消す方法はこれしか無いようです。
この関数の引数に消す範囲を渡します。そうすると、その範囲内の図形が消されます。

・ただ、三角形がウニョウニョ動くだけのソースです

・ブラウザが対応していれば、下記リンクから見れます
サンプル

HTML5のCanvasを使ってみた

■HTML5のCanvasとは
JavaScriptを使って、図形を書くことができるものです!
線、四角形、円などいろいろな図形をかけます。

■試しに使ってみた
・作る図形


・ソース
・ブラウザが対応していれば、下記リンクから見れます
サンプル

・解説
-beginPath()
サブパスのリストを空にして、コンテキストのサブパスが 0 個となるようにします。
今回でいうと、関係ないですが一応書いておいきます!

・moveTo(x,y)
指定された地点で新規のサブパスを生成します。
要するに、初期値店を指定することと同意です。

-lineTo(x,y)
コンテキストにサブパスがなければ、(x, y) に対するサブパスを定義します。コンテキストにサブパスがあれば、サブパスの終点から座標 (x, y) に向けて直線を引きます。そして、サブパスに、座標 (x, y) を追加します。
最初にmoveToにてサブパスが生成されていない場合は、線が引かれることはなく、サブパスの定義で終わります。

-closePath()
現在のサブパスを閉じていると記録し、その閉じたサブパスの開始と終了と同じ地点で、新たなサブパスを開始します。

-stroke()
現在のストローク・スタイルを使って、サブパスに線を引きます。

2010年3月15日月曜日

バーチャルホストの設定

1つのサーバで2つ以上ドメインを使いたいと思うことがあると思います!

そんな時に使うのがApacheのバーチャルホストです。

使い方は簡単で、下記の記述をhttpd.confに記述します。
NameVirtualHost *:80
<VirtualHost *:80>
ServerName xxxxx
DocumentRoot "/opt/xxxx"
</VirtualHost>

<VirtualHost *:80>
ServerName hogehoge
DocumentRoot "/opt/hoge"
</VirtualHost>


ドメインがServerNameに一致する場合、その中に記述されている内容が適用されます。
今回で言うと、ServerNameによってDocumentRootが変わります。

詳しくは
http://httpd.apache.org/docs/2.2/ja/vhosts/examples.html
を見るといいかもしれません。

2010年3月14日日曜日

ThreadPoolExecutor について(第2部:指定出来るいろいろな機能)

実際に使用したときに、私が悩んだ項目であるコンストラクタ引数と、タスク登録について紹介したいと思います。

■コンストラクタ引数について
ThreadPoolExecutorには下記の4つのコンストラクタがあります。

1.ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue)
2.ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue
workQueue, RejectedExecutionHandler handler)
3.ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue
workQueue, ThreadFactory threadFactory)
4.ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue
workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)


コンストラクタ引数のうち、私が特に悩んだRejectedExecutionHandlerについて説明したいと思います。

この値(RejectedExecutionHandler)が何かと言うと、JavaDoc的には下記の様に記述されています。
executor がシャットダウンしている場合、または executor が最大スレッド数とワークキュー容量の両方で有限の境界を使用し、かつ飽和状態である場合、execute(java.lang.Runnable) メソッドで送信された新しいタスクは拒否されます。どちらの場合も、execute メソッドは、RejectedExecutionHandler の RejectedExecutionHandler.rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor) メソッドを呼び出します。

要するに、タスク(スレッドで処理されるもの)が処理できなくなった(あふれた)場合に呼び出される処理ということです。
そして、この処理はデフォルトで4種類のポリシーが用意されています。(独自で用意することもできますが)

このポリシーの選択が重要になります!

このポリシーの選択を間違えると、処理して欲しいハズの処理が飛ばされたり、無視されたり、例外を投げられたりすることになります!

なので、このポリシーの選択は慎重に行ってください。

ポリシーは下記の4つが存在します。
ThreadPoolExecutor.AbortPolicy
 RejectedExecutionException をスローする拒否されたタスクのハンドラです。
ThreadPoolExecutor.CallerRunsPolicy
 executor がシャットダウンしていない場合に、execute メソッドの呼び出しで拒否されたタスクを直接実行する、拒否されたタスクのハンドラです。
ThreadPoolExecutor.DiscardOldestPolicy
 executor がシャットダウンしていない場合に、もっとも古い未処理の要求を破棄して execute を再試行する、拒否されたタスクのハンドラです。
ThreadPoolExecutor.DiscardPolicy
 拒否されたタスクを通知なしで破棄する拒否されたタスクのハンドラです。

下の2つ(DiscardOldestPolicy,DiscardPolicy)はタスクを破棄されてしまうので、それで問題ない場合は使用しましょう!
私が使用した時の要件では、絶対にタスクを破棄されてしまっては困るので上の2つ(AbortPolicy,CallerRunsPolicy)のどちらかを使う必要がありました。

私が考えた、この2つのポリシーのメリット・デメリットをまとめます
・CallerRunsPolicy
 メリット
  タスクがあふれた場合は、親スレッドが処理を行うので効率よくタスクを処理してくれる。
 デメリット
  スレッドごとにトランザクションを管理している場合に、親スレッドのトランザクションが中断されてしまう可能性がある。
  (親スレッドは、mainの最初に開始し、mainの最後にかならずトランザクションを終了させたい場合に、親がタスクの処理を行うとタスクの開始時にトランザクションを張ろうとしてネストしたトランザクションになってしまいます。
   また、タスクの終了時にトランザクションを閉じるので、mainの最後でトランザクションを終了させることができなくなってしまいます)

・AbortPolicy
 メリット
  親スレッドはタスクを処理しないので、CallerRunsPolicyのデメリットが発生しない。
  (この点はDiscardOldestPolicy,DiscardPolicyでも同じことが言えます)
  デメリットの項目とカブるが、タスクが溢れるようなロジックを作っていた場合に、例外が発生するため、間違に気付ける。
 デメリット
  タスクがあふれた場合は、例外が発生してしまう。
  タスクをあふれさせないように、ロジックで制御する必要がある

CallerRunsPolicy、AbortPolicyをこのように分類し、最終的には両方とも使用しました。
トランザクションを考える必要がない場所ではCallerRunsPolicyを使い、そうでない場合はAbortPolicyを使いました。

■タスク登録方法
ThreadPoolExecutorには、タスクとして扱える形式が2つ存在します。
1つ目がRunnableインタフェースを実装する方法、2つ目がCallableインタフェースを実装する方法です。
RunnableインタフェースとCallableインタフェースの簡単な違いは、Callableインタフェースの場合は戻り値を受け取れるということです。
使用用途によって分けるのもいいでしょう!
ただ、RunnableとCallableはタスクの登録方法が若干違うので設計するときは注意しましょう!

・Runnable
1.コンストラクタ引数として渡す、BlockingQueueに格納しておく
2.executeメソッドに引数として渡す
3.submitメソッドに引数として渡す

・Callable
1.submitメソッドに引数として渡す


Runnableの方がいろいろな方法でタスク登録できます。
使用する状況によって分けてみましょう!


こんな感じでThreadPoolExecutorにはいろいろな設定ができるので、
使用用途にあった使い方を吟味してしようしてください。

2010年3月6日土曜日

ThreadPoolExecutor について(第1部:基本的な使い方)

本当に基本的な使い方を紹介します。

■前提条件
スレッド数:3
スレッド消失時間:500ms
スレッド実行される処理(タスク)はRunnableインタフェースを実装させます。
(Callableインタフェースでもできます(タスクの登録方法がRunnableと若干異なります))

■実ソース

package sample.thread.basic;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class SampleMain {

public static void main(final String[] args) {
new SampleMain().go();
}

public void go() {
System.out.println("処理開始");
final BlockingQueue<Runnable%gt; queue = new LinkedBlockingQueue]<Runnable>();
// queueに事前に積んでおくこともできる
for (int i = 0; i < 50; i++) {
queue.add(new TestRunnable());
}
final ThreadPoolExecutor tpe = new ThreadPoolExecutor(3, 3, 500, TimeUnit.MILLISECONDS, queue, new ThreadPoolExecutor.CallerRunsPolicy());
try {
// shutdown()を呼ぶ前であれば、タスクを後から追加することもできる
for (int i = 0; i < 50; i++) {
tpe.execute(new TestRunnable());
}
} finally {
// 必ずshutdownを実行する。実行しないとスレッドが開放されないので処理が一生
System.out.println("ShutDown実行。");
tpe.shutdown();
}
while (true) {
if (tpe.isTerminated()) {
break;
}
try {
System.out.println("タスク終了待ち 1000ms.");
Thread.currentThread();
Thread.sleep(1000);
} catch (InterruptedException ignore) {
}
}
System.out.println("処理終了");
}

/**
* スレッド実行されるタスク。
*/
private static class TestRunnable implements Runnable {

private static volatile int count = 0;

@Override
public void run() {
System.out.println(count++);
}
}
}


■気をつける点
必ずshutdown()メソッドを呼ぶ必要があります!
これを忘れるとMainスレッドが終了してもスレッドだけプーリングされている状態となり、処理が終わりません。
shutdown()メソッドを実行してもすぐに処理が終了するわけではありません。
すべてのスレッドを正常に処理し終えるまでスレッドは開放されません。
すべてのタスクの処理が終わるのを待ちたいのであれば、終了を待つ必要があります。

ThreadPoolExecutor.terminated()をオーバーライドして、終了処理を書くこともできます。


こんな簡単な記述で、スレッドをプーリングすることができます。
次回は、ThreadPoolExecutorをインスタンス化する際に指定できる、いろいろな機能について触れたいと思います。

2010年3月3日水曜日

ThreadPoolExecutorについて(第0部)

業務でこのクラスを使用する機会があったので、ちょっとまとめておこうと思います。

今回の業務の制約はだいたい下記の通りです。
1.Javaでバッチを作成する必要があった
2.性能を追求する必要があった
3.本番環境のCPUの数が8個あった(もちろんメモリもたくさんありました)

このような条件があったので、スレッドを使用することにしました。
そして、Javaでスレッドを使用するならプーリングして使った方が効率がいいので、プーリング機能を提供しているThreadPoolExecutorを使うことになりました。

今回は、このThreadPoolExecutorを使って実現できたこと、はまったことなどを紹介できたらと思います。

一応、全3部構成(今回を入れると4部ですが)で紹介しようと思います。
構成は下記のような感じで進めようと思います。

第0部
 使ったきっかけ
第1部
 基本的な使い方
第2部
 指定出来るいろいろな機能

では、今日はこの目次で終わります。

2010年2月28日日曜日

PukiWikiのインストール

pukiwikiはPHPで出来ているため、PHPをインストールする必要があります。

■PHPのインストール
PHPをインストールするためには、Flexとlibxml2 が必要です。
まずはこれらをインストールしてしまいましょう!
$ yum -y install flex libxml2-devel


PHPの最新版を取得し、インストールして行きます。
$ cd /opt/local/src/
$ wget http://www.php.net/get/php-5.3.1.tar.gz/from/jp.php.net/mirror
$ tar zxvf php-5.3.1.tar.gz
$ cd php-5.3.1
$ ./configure --prefix=/opt/local/php --enable-mbstring --with-apxs2=/opt/local/apache/bin/apxs
$ make
$ make install


Apacheのhttpd.confに下記設定が追加されていることを確認する。追加されていなかったら追加してください。
LoadModule php5_module modules/libphp5.so


index.phpをDirectoryIndexに登録します。
すでにindex.htmlという記述があるので、その後に"index.php"を追記してください
<IfModule dir_module>
DirectoryIndex index.html index.php
</IfModule>


続いて、*.php,*.phtmlをPHPファイルとして認識させるために
"IfModule mime_module"内に下記記述を追記してください
<IfModule mime_module>
・・・・
AddType application/x-httpd-php .php .phtml
</IfModule>


これで、PHPの設定が終わったのでApacheの設定ファイルのテストをしてみましょう!
$ ./bin/apachectl configtest
httpd: Syntax error on line 100 of /opt/local/apache/conf/httpd.conf: Cannot load /opt/local/apache/modules/libphp5.so into server: /opt/local/apache/modules/libphp5.so: cannot restore segment prot after reloc: Permission denied

きっと、このようなエラーメッセージがでるはずです。
(でなければ、インストールが終わっているので飛ばしてください)
このエラーはSELinuxが邪魔をしているのため出ています。
特にSELinuxは使わないのであれば、下記設定を行い再起動すれば解決できます。
$ vi /etc/sysconfig/selinux
SELINUX=enforcing

SELINUX=disabled
$ reboot


サーバが起動したらApacheを起動しましょう!
$ cd /opt/local/apache
$ ./bin/apachectl configtest
Syntax OK
$ ./bin/apachectl start


■pukiwikiのインストール
pukiwikiホームページよりutf-8バージョンの最新をダウンロード。
$ cd /opt/local/apache/htdocs
$ wget "http://sourceforge.jp/frs/redir.php?m=iij&f=%2Fpukiwiki%2F12957%2Fpukiwiki-1.4.7_notb_utf8.zip"
$ unzip pukiwiki-1.4.7_notb_utf8.zip
$ mv pukiwiki-1.4.7_notb_utf8 wiki

これで下記URLにてpukiwikiのページが表示されるはずです。
http://192.168.1.xx/wiki/

もし表示できなかった場合は、pukiwiki関連のファイル、ディレクトリのパーミッションを正しく設定してください。

pukiwikiの詳しい設定は
pukiwikiのインストール手順ページで確認してください

■Basic認証
pukiwikiを公開すると、誰でも編集できてしまいます。
pukiwikiの認証を使ってもいいのですが、今回はApacheのBasic認証を使用してみましょう!
$ mkdir -p /opt/local/apache/conf/basic/
$ cd /opt/local/apache/bin
// ./htpasswd -c パスワードファイル 認証ID
$ ./htpasswd -c /opt/local/apache/conf/basic/wiki_auth aa
New password:
Re-type new password:
Adding password for user aa

これで認証用の設定ファイルの作成が完了しました!

では、Apacheの設定をします!
下記記述をApacheのhttpd.confの一番最後にでも追加してください。
<Directory "/opt/local/apache/htdocs/wiki">
AuthType Basic
AuthName "aa"
AuthUserFile /opt/local/apache/conf/basic/wiki_auth
Require user aa
</Directory>


追記したら、Apacheを再起動しましょう!
$ ./apachectl configtest
Syntax OK
$ ./apachectl restart


それでは、wikiのページにアクセスしてみてください!
きっと、認証を求められるハズです!

ApacheとTomcatの連携

mod_proxy_ajpを使用してTomcatとApacheの連携をします。

■前提条件
Tomcatのインストールが終わっていること
今回は、
Tomcatのインストール
Apacheのインストール
にてインストールしたものを使います。

■mod_proxy系のインストール
前回Apacheをインストールした時に、mod_proxy系はインストールしませんでした。
よって、mod_proxy系のモジュールのインストールを行います。(DSOを使います)
(インストール済みの人は飛ばしてください)

mod_proxy系のコンパイル
$ cd /opt/local/src/httpd-2.2.14/modules/proxy
$ /opt/local/apache/bin/apxs -i -c mod_proxy.c proxy_util.c
$ /opt/local/apache/bin/apxs -i -c mod_proxy_http.c proxy_util.c
$ /opt/local/apache/bin/apxs -i -c mod_proxy_ajp.c ajp*.c


ファイルが作成されている事を確認してください
$ ls -ltr /opt/local/apache/modules/mod_proxy*


httpd.confに下記記述を足してmod_proxy_ajpを使えるようにしてください
$ su -
$ vi /opt/local/apache/conf/httpd.conf
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so


ちゃんと組み込めたかを確認する
$ cd /opt/local/apache/bin
$ ./apachectl configtest
Syntax OK

"Syntax OK"と表示されればOKです!
これで、Apacheへの組み込みが終了しました。

■TomcatとApacheの連携
まずはTomcatの設定を見ます。
$TOMCAT_HOME/conf/server.xml
の"AJP/1.3"の部分のポート番号を見つけてください。
<!-- Define an AJP 1.3 Connector on port 8009 -->
<connector port="8009" protocol="AJP/1.3" redirectport="8443">
</connector>

今回はデフォルトの8009ポートです。

ではApacheとの連携を行います。

下記設定ファイルを作成します。
$ su -
$ cd /opt/local/apache/conf/extra
$ vi httpd-proxy.conf
<Location /examples/>
ProxyPass ajp://localhost:8009/examples/
</location>


この作成した設定ファイルをApacheに読み込ませる必要があるので、下記1文を最終行にでも書いてください。
$ su -
$ cd /opt/local/apache/conf
$ vi httpd.conf
Include conf/extra/httpd-proxy.conf


設定が終わったので、エラーがないかを確認しましょう!
$ su -
$ cd /opt/local/apache/bin
$ ./apachectl configtest
Syntax OK

"Syntax OK"とでればOKです!

Apacheを再起動してみましょう!
$ su -
$ cd /opt/local/apache/bin
$ ./apachectl restart


Tomcatが起動していることを確認して自分のWEBサーバにアクセスしてください。
http://192.168.1.xx/examples/

画面が見れたら、ApacheとTomcatの連携ができました!
※URLの最後に"/"を入れないと、ちゃんとマッピングしてくれません
※最後の"/"がなくてもいいように素るにはRewriteルールなどを使ってやってみてください

本当にApacheを経由しているか確認したければ、下記ファイルを見てリクエストがきた事を確認してください。
$ cd /opt/local/apache/logs
$ cat access_log

Tomcatのインストール

Tomcatを使うためにはJavaがインストールされている必要があります。
よって、Javaのインストールから説明します!

■前提条件
・OS
CentOS5.3
(別にFedoraでもいいです。RedHat系が好きです)
・インストール場所
/home/worker/local/tomcat
(別にどこでもいいです。今回はworkerの持ち物としてインストールします)

■JDKのインストール
最新のJDKをダウンロードします
$ wget -O jdk-6u18-linux-i586.bin http://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_Developer-Site/en_US/-/USD/VerifyItem-Start/jdk-6u18-linux-i586.bin?BundledLineItemUUID=RzJIBe.lTIAAAAEnznIRHw2n&OrderID=s2VIBe.l4eYAAAEnxHIRHw2n&ProductID=6XdIBe.pudAAAAElYStRSbJV&FileName=/jdk-6u18-linux-i586.bin


インストールの実行します
$ bash jdk-6u18-linux-i586.bin

スペースを押しまくって、最後まで行き"yes"と入力する

これでインストール終わりです。
使い易いようにシンボリックリンクを貼っておきます。
$ cd /opt/local
$ ln -s src/jdk1.6.0_18 java


パスを毎回通すのがめんどいので、bashrcに最終行に追記する
$ vi /etc/bashrc
export JAVA_HOME=/opt/local/java
export PATH=$JAVA_HOME/bin:$PATH


ターミナルを入りなおせば、javaにパスが通っています。

■Tomcatのインストール
最新のTomcatをダウンロードします。
$ wget http://ftp.kddilabs.jp/infosystems/apache/tomcat/tomcat-6/v6.0.24/bin/apache-tomcat-6.0.24.tar.gz
$ tar zxvf apache-tomcat-6.0.24.tar.gz


使い易いようにシンボリックリンクをはっておきます
$ cd /home/worker/local
$ ln -s src/apache-tomcat-6.0.24 tomcat


Tomcatの起動
$ cd /home/worker/local/tomcat
$ ./bin/startup.sh


ブラウザからアクセスしたければ、iptablesを編集し8080ポートを開放する必要があります。
$ cd /etc/sysconfig/
$ vi iptables
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT
$ /etc/rc.d/init.d/iptables restart
ファイアウォールルールを適用中: [ OK ]
チェインポリシーを ACCEPT に設定中filter [ OK ]
iptables モジュールを取り外し中 [ OK ]
iptables ファイアウォールルールを適用中: [ OK ]
iptables モジュールを読み込み中ip_conntrack_netbios_ns [ OK ]

これで、ブラウザからhttp://192.168.1.xx:8080/にてアクセスできます!

Tomcatの停止
$ cd /home/worker/local/tomcat
$ ./bin/shutdown.sh


Tomcatのログ
$ cd /home/worker/local/tomcat
$ cat logs/catalina.out

2010年2月27日土曜日

Apacheのインストール

いろいろと紹介する前に、基本のApacheの設定を書いておきます。

■前提条件
・OS
CentOS5.3
(別にFedoraでもいいです。RedHat系が好きです)
・インストール場所
/opt/local/apache

■ソースダウンロード
・Apacheホームページ
http://httpd.apache.org
downloadページへいって"Unix Source"を取得します

■インストール方法
$ su -
$ cd /opt/local/src
$ wget http://ftp.riken.jp/net/apache/httpd/httpd-2.2.14.tar.gz
$ tar zxvf httpd-2.2.14.tar.gz
$ cd httpd-2.2.14
$ ./configure --enable-mods-shared=most --enable-so --enable-rewrite=shared --prefix=/opt/local/apache
$ make
$ make install

これでApacheのインストールは終了です。
ちなみに、configureのログは下記で見れます
$ cat /opt/local/src/httpd-2.2.14/config.log


では、Apacheを起動してみましょう!
$ cd /opt/local/apache
$ ./bin/apachectl start

公開出来ているでしょうか?
IP確認しましょう!
$ /sbin/ifconfig
eth0 Link encap:Ethernet HWaddr 01:30:1B:BD:7A:E5
inet addr:192.168.1.13 Bcast:192.168.1.255 Mask:255.255.255.0

では、私のApacheをインストールしたマシンは192.168.1.13ということがわかったので
http://192.168.1.13/
をブラウザのURLに入力しましょう!

きっと、ファイヤーウォールを有効にしている場合はアクセス出来ないと思います。

■ファイヤーウォールの設定
Apacheの使用する80番ポートを開放します。
(Apacheのポート番号は$APACHE_HOME/conf/httpd.confに"Listen 80"こんな風に書いてあります)
下記手順でiptablesに1文を追加してください。
$ cd /etc/sysconfig/
$ vi iptables
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT

これで、設定ファイルの修正が終わりました。
これだけだと、設定ファイルを修正をしただけなので、ファイヤーウォールの再起動をします。
$ /etc/rc.d/init.d/iptables restart
ファイアウォールルールを適用中: [ OK ]
チェインポリシーを ACCEPT に設定中filter [ OK ]
iptables モジュールを取り外し中 [ OK ]
iptables ファイアウォールルールを適用中: [ OK ]
iptables モジュールを読み込み中ip_conntrack_netbios_ns [ OK ]

では、先程のURLを入力してみましょう!
画面に"It works!"と表示されると思います!


これで、Apacheのインストール終了です。

■外部公開
これまでの設定だと、家の中(イントラ環境)からしかアクセスできません。
外から(職場とか、学校とか)見れるようにするためには、ルータの設定をする必要があります。

今回は、固定IPを持っていない動的IP環境での設定を記述します。
(固定IPを持っていても、この設定でいけますが)

動的IPとは、接続する度にIPアドレスが変化するモノをいいます。
通常のプロバイダ契約だと、動的IPになっていると思います。

IPが動的に変わるのに、どうやって自分のサイトにアクセスするんだよ?
って感じると思いますが、世の中にはダイナミックDNS(以下、DDNSとする)というサービスを提供してくれている人がいます。
今回はこのサービスで、しかも無料のものを使って設定したいと思います。

DDNSについて詳しく知りたければ、ググってください。

ちなみに、私は"Dynamic DO!.jp"様のサイトを利用させていただいています。
なので、以下の説明も"Dynamic DO!.jp"の設定になります。

まずは、サイトにてドメインを取得してください。
このドメインと、自宅のIPを常にマッピングし続ける必要があります。
マッピング自体はDDNSにてやってもらえますが、自宅のIPアドレスを定期的に教えてあげる必要があります。

そのため、この様なシェルを作りましょう!
※"Dynamic DO!.jp"用の設定になるので、他のサービスを利用している場合は、別の方法でやってください。
※/home/apahe/binにシェルを置いた場合の設定です。

cd /home/apache/bin
vi ddns.sh
#!/bin/bash

HOME="/home/apache"

cd $HOME/bin
source ../.bashrc

wget -O - 'http://free.ddo.jp/dnsupdate.php?dn=ドメイン名&pw=パスワード'


このシェルを定期的に実行することによって、ドメインと、このリクエストを飛ばしたIP(要するに自宅のIP)をマッピングしてもらえます。

定期的に、自分でこのシェルを実行してもいいのですが、寝ているあいだとかは無理なのでcron登録しましょう。
下記コマンドを実行し、下記1文を記述しましょう!
$ crontab -e
*/20 * * * * /home/apache/bin/ddns.sh >/dev/null 2>&1


これで、20分毎にこのシェルを実行してもらえます!

以上がDDNSの設定になります。

ただ、これで終わりではありません!

これだけだと、きっと自宅のルータに邪魔をされています。
ファイヤーウォールの設定と同じように、ルータにもポートフィルタリング機能があるため、ルータの80番ポートも開放する必要があります。

この設定自体はルータによって違うので、説明書を読んでみてください。
普通は(192.168.1.1とか192.168.0.1)にブラウザからアクセスするとできると思います。

基本的には、80番ポートへのアクセスを、内部のIPアドレス(今回で言うと192.168.1.13)の80番ポートにマッピングします。
この設定はGUI上でできるので、簡単にできると思います。

これで、外部から自宅のWEBサーバへアクセスすることができます!
外に出て、登録したドメイン名でアクセスしてみましょう!
(めんどくさかったら携帯電話からアクセスしてみてください)

2010年2月25日木曜日

Googleカレンダーの直近スケジュールを表示させる

GoogleカレンダーにIT関連イベントを登録しているのですが、このデータをブログのサイドに表示させたかったので作ってみました。
実際に作成したものは、このブログのサイドに表示させています。

■データ取得方法
まずは、Googleカレンダーからカレンダー情報をJSONP形式で取得します。
JSONP形式のデータを取得するためには、下記URLで実現できます。
http://www.google.com/calendar/feeds/bosh0h7tg9ddmhav7a537bguh4%40group.calendar.google.com/public/full?alt=json-in-script&callback=insertCalendar

もし、自分のカレンダーで試したいのであればURLを下記のようにしてください
"http://www.google.com/calendar/feeds/" + GoogleカレンダーURL + "/public/full?alt=json-in-script&callback=insertCalendar"

これで、JSONP形式でレスポンスを得ることができました。
callback関数名はパラメータに渡したinsertCalendarになります!

ここまでくればあとちょっと!

日付順で取得したいので
"orderby=starttime&sortorder=ascending"をパラメータに追加!

未来の予定が欲しいので
"futureevents=true"をパラメータに追加!

最大件数は7件がいいので
"max-results=7"をパラメータに追加!

これでURLが完成!
http://www.google.com/calendar/feeds/bosh0h7tg9ddmhav7a537bguh4%40group.calendar.google.com/public/full?alt=json-in-script&callback=insertCalendar&orderby=starttime&max-results=7&singleevents=true&sortorder=ascending&futureevents=true

ちなみに参考API
http://code.google.com/intl/ja/apis/gdata/docs/json.html

■データ表示
前回のJSONPの使い方で紹介した方法を使い表示部分の実装していきます。

コールバック関数名がinsertCalendarなので、この関数名で実装します。
今回、このブログでは下記のソースを使用しています。

var edit = function() {
// ① scriptタグを出力し、サーバから取得できる下記文字列をHTML上に展開させる
// insertCalendar({jsonデータ});
var url = 'http://www.google.com/calendar/feeds/bosh0h7tg9ddmhav7a537bguh4%40group.calendar.google.com/public/full?alt=json-in-script&callback=insertCalendar&orderby=starttime&max-results=7&singleevents=true&sortorder=ascending&futureevents=true';
var ele = document.createElement('script');
ele.type = 'text/javascript';
ele.src = url;
document.body.appendChild(ele);
// 文字列を出力する場所を取得
var output = document.getElementById('ak-javascript');
return {
disp : function(events) {
// ③ 1個のイベント情報を表示様に整形して行く
var title = events.title.$t;
var content = events.content.$t;
var start = events.gd$when[0].startTime;
var link;
if(content) {
var contents = content.split('\n');
for(var i = 0; i < contents.length; i++) {
var con = contents[i];
if(con.indexOf("http",0) == 0) {
link = con;
break;
}
}
}
var ele;
if(link) {
ele = document.createElement('a');
ele.href = link;
ele.target = '_blank';
ele.innerHTML = title;
} else {
ele = document.createElement('span');
ele.innerHTML = title;
}
var date = document.createElement('span');
date.innerHTML = '・' + start + '';
// ④ HTML上に出力する
output.appendChild(date);
output.appendChild(document.createElement('br'));
output.appendChild(ele);
output.appendChild(document.createElement('br'));
}
};
}();
// ② コールバック関数
function insertCalendar(data) {
var feed = data.feed;
if(!feed) {
return;
}
var events = feed.entry;
for(var i = 0; i < events.length; i++) {
edit.disp(events[i]);
}
}

■解説
ソースの①~④までが順番に呼ばれます。
①にて、scriptタグをHTML上に出力すると、urlに書かれている場所からデータをダウンロードします。
ダウンロードしたデータにはinsertCalendarを実行するように記述されたデータが返されるため、②の関数が実行されます。
②の関数の実行時に渡されるjsonデータを分解し、1個ずつの登録データに分けて出力処理を行います。
③にて、データの整形を行っています。今回はカレンダーに登録されている詳細情報からURLを抽出して、リンクをつけるように整形しています。
最後に、④にてHTML上に出力を行っています。

以上の流れで、このブログ上にGoogleカレンダーから取得したイベントデータが表示されています。

JSONPを使うことによって、このように別のサーバからデータを取得することができます。
そして、アイデア次第でいろんな便利な事ができます!
ぜひ試してみてください!

JSONPの使い方

JavaScriptで別のドメインのデータを取得したいとすると、クロスドメイン問題にぶつかると思います。
この問題を解決するためには、JSONP(JSON with paddingの略)というモノを使用することになると思います。
他にも方法はありますが、きっとこれが一番簡単なのではないでしょうか?

実際の使い方を書きます
下記URLにアクセスすると、
http://always.ddo.jp/blog/jsonp/test.jsonp

test( { "name" : "hoge", "age" : "100" } );
このような文字列が返却されます。

この文字列をよく見ると、
javascriptのtest関数に'{ "name" : "hoge", "age" : "100" }'というjson形式のデータを渡しているように見えると思います。

JSONPについては、これが全てです!

下記ソースをFirebugのコンソールなどに貼って実行してみてください。

別のドメインの情報を取得して、ページ内で取得データを使用できるようになりました!

■解説
ソースに存在する無名関数にて、scriptタグを生成しています。
このscriptタブのsrc属性に、最初に記述したjsonpデータを返却するURLを記述します。
そうすると、帰ってきたデータがクライアントのHTML上に展開され、javascriptのtest関数を呼びます。
test関数は、自分で好きな様に記述できるので、引数を受け取って今回はalertしています。

次回はGoogleカレンダーと連携した、もう少し面白い使い方を紹介したいと思います。