May 25, 2008

Spring Framework 2.5.4 リリース

4月28日付けで、Spring Framework 2.5.4 がリリースされていました。
オフィシャルサイトのトップページにも、RSS 配信にも無かったので今日まで気づきませんでした・・・

http://sourceforge.net/project/showfiles.php?group_id=73357&package_id=173644&release_id=595476

2.5.3 からの主な変更点は下記の通り。

  • AspectJ が 1.6 になった(1.5.x との互換性あり)
  • JdbcTemplate で CallableStatement から null の ResultSets が返るのを検出してスキップするようになった
  • BeanPropertySqlParameterSource は MySQL との互換性のために JDBC 3.0 の Types.BOOLEAN をデフォルトで使わないようになった
  • Hibernate3.2 + ピュア Spring 管理 JTA トランザクションで、クエリ発行前にフラッシュ実行をサポート

詳細は下記を参照してください。
http://static.springframework.org/spring/docs/2.5.x/changelog.txt


あまり大きな変更点はありませんね。
ニュースにするまでもないってコトでしょうか。

May 12, 2008

SaaS 普及のカギ

今 SaaS を手がける代表的な企業といえば、Google と SalesForce.com です。

しかし、両社のサービスに私は不満です。

何がって?

SaaS Office Suite
(残念ながら?)世の中の人々(特に企業ユーザー)は、MS Office を手放せません。SaaS ドキュメントにも MS Office 完全互換を求めています。
Google Document が MS を打倒できない理由は、ズバリ MS Office 完全互換でないからです。一応 MS Office 形式でエクスポートは可能ですが、マクロは動作しないし、レイアウトが崩れたりします。
OOo の普及が進まないのも、MS Office 完全互換ではないからという理由に他ならないからでしょう・・・

MS さん!何やってるんですか?
Office ドキュメントと Web 上のドキュメントのインポート/エクスポートを完全に行える SaaS 形式の Office Suite をリリースすればみんな使うのに・・・
結局、最終的にはローカルへのインポート/ローカルからのエクスポートの需要はあるのだから、ユーザーが増えれば(減らなければ)Office は売れ続けるのに・・・
マクロも消えない、完全互換の SaaS ドキュメントは(現在のところ) MS だけが作れるものなのに・・・
「オープンである」とかはきれい事。特に企業ユーザからは MS Office 完全互換が求められているのが事実だと思います。
Web にインポート/エクスポートできる MS Office ドキュメントは厳密に言えば SaaS ではないのですが、ユーザが求める物を提供することは大事ですよね。


クラウド/ PaaS
SalesForce.com の Force.com は Apex という独自言語と独自 API がネックですね。他のプラットフォームへ移植できませんから。
Google App Engine も、同じ理由で Bigtable がネックです。

Sun さん!何やってるんですか?
完全 Pure Java なクラウド環境をリリースすればみんな使うのに・・・
Glassfish が使えて、H2 や Derby (JavaDB) が動作すれば言うことナシです。
Google App Engine なんてメじゃないのに・・・
完全 Pure Java なクラウド環境がリリースされれば Java テクノロジはますます躍進するでしょう。そして、Sun は PaaS 分野のリーダーとなれるでしょう。

・・・とここまで書いて思い出しました。たしか、Sun は非営利団体等へ仮想化サーバスペースを無償で提供するというソリューションをやっていたはず。・・・
ただし、米 Sun のサービスで日本語文字コードセットの扱いに問題があったような。
具体的な資料は探し出せず。。。残念。



Web メール
SaaS の普及がもっとも進んでいる分野が Web メールでしょう。Gmail、Hotmail (Windows Live! Mail)、Yahoo! Mail を利用している人はとても多いと思います。
しかし、メインではメーラーによる POP アクセスが主で、Web メールの利用はプライベートでは 30%、ビジネス利用では 10% 以下です。(2007年9月の記事による)

Web メールメイン利用、仕事では約9%・自宅では約30%
http://japan.internet.com/research/20070920/1.html

Web メールの利用はセカンドアドレスや「漏洩・流出してもかまわない、いざとなったら捨てられるアドレス」としての利用が大多数なのではないでしょうか。企業ユースではさらに比率が下がりますが、これは情報漏洩対策等の結果でしょう。


SaaSを使わない理由
こんな記事もありました。

SaaSを使わない理由――IT投資調査から
http://www.itmedia.co.jp/enterprise/articles/0805/14/news015.html
それなりに多いSaaS普及への課題
http://www.itmedia.co.jp/enterprise/articles/0804/25/news007.html

May 11, 2008

au one メール

au は Google と提携して、au one メールに Gmail を採用しているのですが・・・

Gmail の新バージョンになかなか対応しません。

au one メールは POP や IMAP を禁じているなど、標準の Gmail そのままではなくてかなりカスタマイズしている模様です。
おそらく、このカスタマイズゆえに Gmail 新バージョンへの対応が追いついていないのでしょう。

バージョンアップや機能追加に対応できないのなら、SaaS の意味が半減してしまいます。

変にカスタマイズしないで、デフォルトのまま Google Apps を利用すればいいのに・・・

ちなみに、livedoor mail がそのスタイルですね。

May 8, 2008

MySQL、新機能のクローズトソース化の決定を撤回

先月、「MySQL、新機能追加は有償版の「MySQL Enterprise」だけを対象に」という記事が Technobahn より出て、Sun が各方面の OSS 支持者の非難を浴びるという事件がありました。

MySQL、新機能追加は有償版の「MySQL Enterprise」だけを対象に
http://www.technobahn.com/cgi-bin/news/read2?f=200804172000


こんな苦しいフォローもありましたが・・・

「一部報道で、MySQLに対する今後の新機能追加は有償版である「MySQL Enterprise」のみに適用されるとあり、これがコミュニティーから強い不快感を招いているが、実際には、「一部」の機能やドライバがMySQL Enterpriseにのみに搭載されるという趣旨である。」
http://www.itmedia.co.jp/enterprise/articles/0804/21/news118.html


やっぱりこうなりましたね。

MySQL、新機能のクローズトソース化の決定を撤回
http://www.technobahn.com/news/2008/200805071431.html

クローズドソース化は MySQL の方針で、Sun の意向に反する(と主張している)ところが引っかかりますが・・・


ベンダーのオープンソース戦略の難しさを感じさせる一件だと思います。
オープンソースと言えば Linux カーネルや、Apache Software Foundation だった時代は、「オープンソース=有志によるボランティア活動」という色も強かったのですが、IBM の Eclipse が普及してきた頃から、ソフトウェアベンダーが自社製品をオープンソースライセンスで公開するという動きが急速に広まってきました。

しかし、中にはこの戦略がうまくいっていないベンダーがあります。

営利企業である以上、すべての事業は自社の収益に結びつけられるべきなのですが、オープンソース戦略はいかに大きい目・長い目で見て、業界全体が育っていくのを見守れるかにかかっていると思います。
一気にシェアを取りに行ったり、ライバルを意識して業界内での存在感をアピールしようとしたり、短期的な収支を考えたりという理由で焦ってもいいこと無いですね。

April 30, 2008

Google App Engine で Web アプリケーション ~ その2

Google App Engine は、Django というフレームワークがデフォルトで利用できます。この Django には強力なテンプレートエンジンが含まれています。

前回までのような方法で画面を出力するのは少々骨が折れますが、Django のテンプレートエンジンを使うと HTML ベースの画面を作りやすくなります。

Javaで言うところの、Velocity や FreeMarker のようなモノですね。


というわけで、今回はこれを利用してみました。


テンプレートとなるファイルを作成する

拡張子は .html で OK です。


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ようこそ</title>
</head>
<body>
  <center>
    <br />
    <h3>ようこそ!{{username}}さん!</h3>
    <br /><br />
    <a href="/index.html">戻る</a>
  </center>
</body>
</html>


Django テンプレートでは、動的に値を埋め込みたい箇所は、{{...}} で囲み、括弧の中に変数名を記述しておきます。オブジェクトの属性にアクセスするには、user.username のように、. (ドット) で区切ってネストを指定します。


テンプレート出力処理を行うには

こんな風に書きます。

# テンプレートを取得
templatefile = os.path.join(os.path.dirname(__file__), 'テンプレートファイル名')
# パース・コンパイル・出力処理
self.response.out.write(
  template.render(templatefile, {'変数名':オブジェクト}))

template.render() メソッドの引数には、出力したいオブジェクトと、そのオブジェクトの変数名を連想配列の形式で記述します。複数指定したい場合は

template.render(templatefile, {'変数名1':オブジェクト1, '変数名2':オブジェクト2, '変数名3':オブジェクト3}))


のように書きます。



というわけで、前回のアプリケーションを、Django テンプレートを使ったものに書き換えてみると、こうなります。


[index.html]

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ようこそ!</title>
</head>
<body>
  <form action="welcome" method="post">
    <center>
      <br />
      <h3>お名前は?</h3>
      <input type="text" name="username" size="30" />
      <br /><br />
      <input type="submit" value="送信" />
    </center>
  </form>
</body>
</html>


前回と同一です。


[WelcomeRequestHandler.py]

# coding: UTF-8

import os
import wsgiref.handlers

from google.appengine.ext import webapp
from google.appengine.ext.webapp import template

# webappのインポート
from google.appengine.ext import webapp

class WelcomeRequestHandler(webapp.RequestHandler):

  # HTTP post リクエスト処理
  def post(self):
      # リクエストパラメータ "username" の取得
      userName = self.request.get("username")

      # テンプレートファイルを取得
      templatefile = os.path.join(os.path.dirname(__file__), 'welcome.html')
      # パース・コンパイル・出力処理
      self.response.out.write(
        template.render(templatefile, {'username':userName.encode('UTF-8')}))

def main():
  # リクエスト URL パターンと、実行するクラスの関連づけ
  application = webapp.WSGIApplication([('/welcome', WelcomeRequestHandler)],
           debug=True)
  wsgiref.handlers.CGIHandler().run(application)

# アプリケーション起動時に main() 関数が実行されるようにする
if __name__ == "__main__":
  main()


前回は、HTML タグなどを直接出力していましたが、今回はテンプレートを利用してレスポンス出力を行っています。


[welcome.html]

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ようこそ</title>
</head>
<body>
  <center>
    <br />
    <h3>ようこそ!{{username}}さん!</h3>
    <br /><br />
    <a href="/index.html">戻る</a>
  </center>
</body>
</html>


「ようこそ!{{username}}さん!」の箇所に注目です。WelcomeRequestHandler.py で、リクエストパラメータから取得した値を "username" という名前でテンプレートオブジェクトとして指定しました。この welcome.html では、その "username" という名前の変数の値を出力しています。


[app.yaml]

application: liebejudith-helloworld
version: 1
runtime: python
api_version: 1

handlers:
- url: /welcome
  script: WelcomeRequestHandler.py
- url: /index\.html
  static_files: index.html
  upload: index.html
- url: /
  static_files: index.html
  upload: index.html


前回と同一です。


実行結果




実行結果も前回と同一です。


HTML センシティブな文字・記号のエスケープについて

Webアプリケーションでは、正しい表示やクロスサイトスクリプティング対策のために、< や、> など、HTML や JavaScript コードとして認識されてしまう文字をエスケープする必要があります。
現在のバージョンの Django では、デフォルトでエスケープが有効になっています。もし何らかの理由でエスケープ処理を無効にしたい場合は、


こんにちは {{ username|safe }} さん


のように、safeフィルタを利用します。
あるいは、


{% autoescape off %}
    こんにちは {{ username }} さん
{% endautoescape %}


のように、autoescape タグを使って、off オプションを指定します。Django テンプレートでは、タグの表記に {% ... %} を使います。


ループ処理を行うには

for タグを使います。Velocity や FreeMarker を使ったことのある方なら直感的におわかりでしょう。


{% for 要素 in リスト %}
    ・・・・
{% endfor %}


ループの中では、次の変数を利用できます。

forloop.counterループカウンタ(1から開始)
forloop.counter0ループカウンタ(0から開始)
forloop.revcounterループの終わりからのインデックス(1から開始)
forloop.revcounter0ループの終わりからのインデックス(0から開始)
forloop.firstループの最初の繰り返しの場合、True になる
forloop.lastループの最後の繰り返しの場合、True になる



条件分岐を行うには

if タグあるいは ifequal/ifnotequal タグを使います。

if タグを使った評価

指定した変数が存在するか・空ではないか(リストの場合)・Trueかを評価します。


{% if name_list %}
    ・・・・
{% else %}
    ・・・・
{% endif %}


or not and を使って複合的な評価も可能です。


{% if name_list or order_list %}
    ・・・・
{% endif %}



{% if not name_list %}
    ・・・・
{% else %}
    ・・・・
{% endif %}



{% if name_list and order_list %}
    ・・・・
{% endif %}



{% if name_list and not order_list %}
    ・・・・
{% endif %}



ifequal/ifnotequal タグを使った評価

2つの値が同一かどうかを比較します。
ifnotequal は同一でないかどうかを比較します。
2つの値はスペース区切りで指定します。


{% ifequal user.id comment.user_id %}
    ...
{% endifequal %}



{% ifnotequal user.username "liebejudith" %}
    ...
{% endifequal %}




画面部品をインクルードするには

include タグを使います。
ファイル名は、文字列リテラルで直接指定することもできますし、変数を使っての動的指定も可能です。


{% include "foo/bar.html" %}



{% include template_name %}




コメントを記述するには

{# ... #} で囲みます。


{# comment #}




テンプレートの継承

Django では、テンプレートを継承することができます。この機能は、同一レイアウト、同一部品を使った似たデザインの画面が多数存在する場合に非常に便利です。
子テンプレートでオーバーライドする部分は、{% block ブロック名 %} ~ {% endblock %} で囲んで記述しておきます。ブロック名はユニークな任意の名前です。


<html>
<head>
    <title>{% block title %}タイトル{% endblock %}</title>
</head>

<body>
    <div id="content">
        {% block content %}{% endblock %}
    </div>
</body>
</html>


あるテンプレートを継承したテンプレートを作成するには、{% extends "親テンプレート名" %} を記述します。そして、親で定義された {% block ブロック名 %} ~ {% endblock %} を任意にオーバーライドできます。


{% extends "base.html" %}

{% block title %}子ページ{% endblock %}

{% block content %}
content 部分のオーバーライド
{% endblock %}




変数値の出力、条件分岐、ループ処理、インクルード、テンプレートの継承と見てきました。これでたいていの画面は作成できるのではないでしょうか?


Django の翻訳ドキュメントも見つけました。Yasushi Masuda さん、Takanao Endoh さんという方が翻訳されています。

Django
http://ymasuda.jp/python/django/index.html

Django オンラインドキュメント和訳
http://michilu.com/django/doc-ja/index/

Django は、テンプレートエンジンだけでなくアプリケーション全体をカバーするフルスタックのフレームワークです。今回取り上げたテンプレートのリファレンスはこちらです。

テンプレート作者のための Django テンプレート言語ガイド
http://michilu.com/django/doc-ja/templates/

Django のユーザコミュニティも存在するようですが、残念ながら現在はサーバが止まっているようです・・・
http://djangoproject.jp/


私は Python 初心者のため、定石もお作法も知りません。バリバリの Python 使いの方から見たらとんでもないコードを書いているかもしれませんがご容赦下さい。間違いや「こうするもんだ」を指摘していただけるととても嬉しいです。

環境: Python 2.5