2011年2月28日月曜日

「Apache Chemistry」

 Apache Software Foundation(ASF)は2月23日(米国時間)、「Apache Chemistry」をトップレベル
プロジェクト(TLP)に昇格することを発表した。Apache Chemistryは企業向けCMSの相互運用仕様
「CMIS(Content Management Interoperability Services)」をオープンソースで実装するプロジェクト。



CMISは標準化団体OASIS(Organization for the Advancement of Structured Information Standards)が策定する企業向けコンテンツ管理システムの相互運用に向けた仕様。
CMISに準拠した製品としてはAlfrescoやEMC Documentum、IBM FileNet、Microsoft SharePoint、Nexeoなどがあり、Apache Chemistryはこれらのレポジトリと相互運用できるAPI
やCMIS準拠のレポジトリコネクタを構築するライブラリを提供する。CMISクライアントおよびサーバー向けのJavaライブラリやテストツールを含むOpenCMISを中心に、合計4つのサブジェクトで
構成されている。
 OpenCMISは米Adobe Systems、独SAPなど多数の商用ソリューションやオープンソースのソフトウェアで実装されているという。
 Apache Chemistryは2009年5月にASFのインキュベータプロジェクトとなり、約1年半でTLPに昇格することになる。ASFでは、「CMISの普及を促進することに成功している」とこれまでの成果を評価している。
Apache Chemistry

2011年2月27日日曜日

Open Library


Open Library(Open Library 公式デモサイト (英語))

Open Library(オープンライブラリー)は全世界の書籍情報へのアクセスを目標にするオープンソースプロジェクト。
元々は Open Content Alliance がスキャンした書籍を公開している同名の電子図書館から派生したプロジェクト
である。

概要 [編集]

Open Library の利用において、ユーザーはアカウントを明示的に取得しなくても自動的にアカウントが与えられる。
個々の書籍情報には Google などの外部の検索エンジンからのトラフィックが見込まれるほか、内部にも強力な
検索エンジンを有する。ユーザーによるタグの追加や、ユーザーによって定義された書籍リストをサポートする。
書籍の著者、出版社、読者など多くのユーザーによる使用のシナリオが想定されている。
Open Library はスキャンされOCRによってテキスト化された書籍のデータを表示するための書籍ビューワ機能を
持っており、ユーザーはこのテキストデータを校正することもできる。また、テキストデータにマークアップを適用
することにより異なったテキスト間の脚注や引用などができるほか、ブックマーク機能も有する。印刷のための
フォーマットへの変換機能も予定されている。すべての人がカタログを編集したり、書籍に評価を与えたりコメント
を加えたりすることができる。著作権が切れた書籍のアップロードができるほか、寄付によってそのような書籍の
スキャン活動をサポートすることができる。
新しいデータの追加やテンプレートへの変更には Wiki 言語(Infogami)が利用されている。

2011年2月26日土曜日

見えないChromeアプリを実現する機能

GoogleはこれまでChrome開発版においてウィンドウを開くことなくChromeアプリケーションを実行できるようにするバックグラウンド機能の実装に取り組んでいたた。今回、この機能が利用できるようになったことを広く開発者に伝える呼びかけが開始された。Googleはこうした機能を提供することでChromeアプリケーションやエクステンションの利便性を引き上げ、より多くのアプリケーションがChrome経由で動作するようにすることを狙っているとみられる。
インスタントメッセージのやりとりであったり、カレンダーイベントの通知であったり、即時性を求められるアプリケーションをChromeで実行するには、基本的にChromeウィンドウが開いている必要がある。今回、ウィンドウを開くことなくこうした振る舞いを実現する「バックグラウンド」と呼ばれる機能がChrome開発版に追加された。
Chromeを終了してもバックグラウンド機能を使っているアプリケーションやエクステンションは背後で動作を継続する。これはメッセンジャーやイベント通知などに使えるほか、コンテンツやデータの事前読み込みといった処理にも活用できる。バックグラウンドで動作しているアプリやエクステンションは簡単に停止することもでき、Chromeを再度起動したタイミングですべて再起動がかかる仕組みになっている。
セキュリティを実現する目的で、この機能が提供されるのはChromeアプリケーションとエクステンションに限定されている。通常のWebサイトはこの機能を利用することができない。Chrome Web StoreからインストールするChromeアプリケーションで実現できる範囲を広げ、より多くのChrome需要を喚起する狙いがあるものとみられる。

2011年2月23日水曜日

企業・雇用の国際化

本日(2011/02/23)の日経BPのニュースでタイトル『"生え抜き外国人"社長の勝算』の記事がありました。

オリンバスの次期社長が英国人が就任されます。まぁ、オリンバスに限らず、ソニーや日産自動車や日本板硝子などの大企業も外国人のトップは珍しくなくなった。その背景は海外の収益がますます増加になるに違いないでしょう。社員レベルも役員クラスも就職に当たっては今後グローバルの視点で考えなければいけなくなりつつです。

2011年2月21日月曜日

Struts 2 XML不要のZero Configuration

Zero Configurationとは

 じつは、この「Zero Configuration」機能こそが、Struts 2の目玉とも言える機能です。Struts 1では、アプリケーションの規模に比例して、XMLファイルに記述するActionクラスや画面遷移の定義が膨れ上がり、俗に「XML地獄」と呼ばれるような開発効率の低下を招いていました。Struts 2では、このような状況を打破するべく、XMLファイルへの定義を不要にする機能が盛り込まれました。当初は、前述したようにCodebehindプラグインによってサポートされていました。

 XMLファイルの定義をなくす仕組みは、決められたルールに従ってActionクラスやJSPファイルを命名することと、アノテーション機能との合わせ技です。

Zero ConfigurationHello World

 まずは、例によって「Hello Worldアプリケーション」を作成していきましょう。次の図のように、ごくシンプルに、リンクをクリックすれば、Actionクラスが処理されて、文字列を表示するというものです。

Hello World」アプリケーションの画面遷移

「Hello World」アプリケーションの画面遷移

ファイル構成

§            /WEB-INF/lib/commons-fileupload-1.2.1.jar

§            /WEB-INF/lib/commons-io-1.3.2.jar

§            /WEB-INF/lib/commons-logging-1.1.jar

§            /WEB-INF/lib/freemarker-2.3.13.jar

§            /WEB-INF/lib/junit-3.8.1.jar

§            /WEB-INF/lib/ognl-2.6.11.jar

§            /WEB-INF/lib/spring-test-2.5.6.jar

§            /WEB-INF/lib/struts2-core-2.1.6.jar

§            /WEB-INF/lib/xwork-2.1.2.jar

§            /WEB-INF/lib/struts2-convention-plugin-2.1.6.jar

 全体のファイル構成は、次のようになります。

 <ContextRoot>
 ├ /WEB-INF
 │ ├ /classes
 │ │ ├ /zero.action
 │ │ │ └ ZeroAction.class
 │ │ └ struts.xml
 │ ├ /content
 │ │ └ zero.jsp
 │ ├ /lib
 │ │ └ 参照ライブラリー
 │ └ web.xml
 └ index.jsp

web.xml

 web.xmlの記述も新しいバージョンでは、若干変更があります。

[リスト1web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>ZeroProject</display-name>

    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

</web-app>

 <filter>タグで指定するクラスが、org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterクラスとなりました。以前のFilterDispatcherクラスは、非推奨に変更されています。ただし、このクラスには、前述した文字コードの変換漏れがあるため、リクエスト文字などで文字化けが発生してしまいます。応急的な解決策としては、文字コードの変換処理をActionクラスに追加するか、以前のFilterDispatcherクラスを使うかのどちらかです。

 それ以外は、2.0系列との違いはありません。

struts.xml

 次にstruts.xmlですが、これは以下の記述だけです。

[リスト2struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <constant name="struts.enable.DynamicMethodInvocation" value="false" />
    <constant name="struts.devMode" value="false" />
</struts>

 「Zero Configuration」でなければ、Actionクラスの定義など、いろいろ記述する必要があるところですが、これだけで大丈夫です。画面遷移もまったく記述不要です。

 Conventionプラグインの設定も、デフォルトでかまわないのであれば、特に指定する必要はありません(既定値などは後述します)。

Actonクラス

 Actonクラスは、次のように、連載第一回目のものとほぼ同じです。異なるのは、このクラスが、あるルールに従っているところだけです。

[リスト3ZeroAction.java

package zero.action;

public class ZeroAction {

    private static final long serialVersionUID = 1L;

    private String replyMsg;

    public String getReplyMsg() {
        return replyMsg;
    }

    public void setReplyMsg(String message) {
        this.replyMsg = message;
    }

    public String execute() throws Exception {
        this.setReplyMsg( "これがZero Configuration" );
        return "success";
    }
}

 あるルールとは、このクラスをActionクラスだと認識させるためのもので、struts.xmlでの定義の代わりになるものです。Conventionプラグインによって、デフォルトでは、以下のいずれかのルールに従っているクラスをActionクラスと認識します。

§            com.opensymphony.xwork2.Actionインターフェイスを実装してるクラス

§            クラス名が「Action」で終わっているクラス

 またConventionプラグインは、この条件に当てはまるActionクラスを、strutsstruts2actionactionsという名前のパッケージからサーチします。

 サンプルのZeroAction.javaでは、パッケージ名がzero.actionで、クラス名がZeroActionとなっていますので、このクラスはActionクラスとして認識されることになります。

 Actionクラスの名前が、デフォルトのAction名の生成に使用され、execute()メソッドが呼び出されます。ただし、クラス名の最後の「Action」は、Action名から除かれ、さらに大文字と小文字を組みあわせたCamel形式の名前は、小文字をハイフンで区切った名前に変換されます。ZeroActionクラスなら、「zero.action」になるということです。

 また、ここで重要なポイントは、パッケージの階層とクラス名が、ActionURIと対応(マッピング)していることです。パッケージの階層を上位からサーチして、最初にActionクラスのパッケージだと認識したところがURIのルートになります。つまり、sample.actionパッケージにあるZeroActionクラスなら、sample.actionがルートとなり、「/zero.action」ということです。その他、クラス名とActionを示すURIのマッピング例は、次のとおりです。

クラス名とActionを示すURIの対応例

クラス名

URI

zero.action.ZeroAction

/zero.action

sample.action.test.ZeroAction

/test/zero.action

sample.struts.company.details.HelloWorldAction

/company/details/hello-world

 なお、URI.actionは省略可能ですので、「/zero」とするだけで、「/zero.action」と見なされます。

Result処理

 Resultに指定するViewテンプレートファイルにもルールがあります。サンプルコードでは、/WEB-INF/content/zero.jspとしていますが、デフォルトでは、/WEB-INF/content/以下からファイルがサーチされます。サーチされるファイル名は、Resultコードと対応しており、「Action-Resultコード.jsp」となります。つまり、zero.actionから呼ばれるメソッドが"success"を返すなら、「zero-success.jsp」となります。

 なお、Resultコードが"success"の場合は省略可能ですので、サンプルコードのように「Action.jsp」が対応します。また、Actionクラスがサブパッケージにあれば、対応するResultファイルも同じ階層にあるものが対応することになります。

 実際のマッピング例は、次のとおりです。

Actionを示すURIとサーチされるResultファイルの対応例

ActionURI

サーチされるデフォルトのViewファイル

/zero.action

/zero.jsp

/test/zero.action

/test/zero-success.jsp

/company/details/hello-world

/company/details/hello-world.jsp

 なお、デフォルトのResultタイプが「Dispatcher」ですので、まずjspファイルがサーチされ、それがなければ、HTMLファイル(.html)、velocity.vm)、freemarker.ftl)の順に探していきます。

 従ってサンプルコードでは、「/zero」を指定すると、「/WEB-INF/content/zero.jsp」がViewテンプレートファイルとして用いられることになります。

注意点

 Conventionプラグインの動作で、注意が必要なものがあります。それは、Actionクラスが見つからない場合、Actionクラスの処理がスキップされて、Viewテンプレートのみを処理してしまうことです。例えば、/WEB-INF/content/zero2.jspというファイルだけがあり、対応するActionクラスがない状態でも、「/zero2.action」とすると、そのjspファイルが表示されてしまいます。

 使い方によっては便利な機能ですが、危険な機能とも言えます。あやまって、Actionクラスと認識されないActionクラスを作ってしまうと、そのクラスの実行がスルーされることになってしまうのです。

カスタマイズ方法

 ここまで説明してきたルールは、すべてデフォルトの仕様です。Zero Configurationとはいえ、ある程度は既定値を変更するカスタマイズが可能です。カスタマイズには、アノテーションを用いた指定と、XMLの設定ファイルで既定値を上書きする方法があります。

Actionアノテーション

 Actionアノテーションは、Actionメソッドと、それを呼び出すURIのマッピングを指定するものです。Actionアノテーションを用いると、一つのメソッドに複数のURIを設定できたり、executeメソッド以外のメソッドを、Actionメソッドとして設定することができます。

 例えば次のようにすると、ZeroAnnクラスのActionメソッドは、「/ann/zero-ann.action」というURIにマッピングされます。デフォルトの「/zero-ann.action」ではアクセスすることができません。

[リスト4ZeroAnn1.javaの一部

package zero.action;

import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.Action;

public class ZeroAnn1 extends ActionSupport {

    ...中略...

    @Action("/ann/zero1")
    public String execute() throws Exception {
        setReplyMsg("ann/zero1");
        return "success";
    }
}

 この場合URIが「/ann/zero1.action」ですので、対応するResult処理のViewテンプレートファイルは、「/WEB-INF/content/ann/zero1.jsp」ということになります。

 一つのメソッドに、複数のURIをマッピングすることもできます。例えば、次のようにすると、「/ann/zero2.action」でも、「/ann/zero3.action」でも、同じメソッド(execute2)が呼び出されます。

[リスト5ZeroAnn1.javaの一部

import com.opensymphony.xwork2.ActionSupport;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Actions;

public class ZeroAnn1 extends ActionSupport {

    ...中略...

    @Actions({
        @Action("/ann/zero2"),
        @Action("/ann/zero3")
    })
    public String execute2() throws Exception {
        setReplyMsg("ann/zero2,ann/zero3");
        return "success";
    }
}

 Actionアノテーションのもう一つの用途は、一つのActionクラスに、複数のActionメソッドを定義することです。次の例では、ふたつのActionメソッドを定義しています。

[リスト6ZeroAnn1.javaの一部

public class ZeroAnn1 extends ActionSupport {

    ...中略...

    @Action("/ann/zero1")
    public String execute() throws Exception {
        setReplyMsg("ann/zero1");
        return "success";
    }

    @Actions( { @Action("/ann/zero2"), @Action("/ann/zero3") })
    public String execute2() throws Exception {
        setReplyMsg("ann/zero2,ann/zero3");
        return "success";
    }
}

InterceptorRefアノテーション

 InterceptorRefアノテーションを指定することで、インターセプターの設定をすることができます。このアノテーションは、クラス定義の前に記述し、クラスレベルで指定します。クラスレベルで指定すると、クラスで定義されたすべてのActionメソッドに、このアノテーションが適用されます(ドキュメントでは、メソッド単位で指定可能なようですが、確認できませんでした)。

 例えば次のように、「timer」インターセプターと、「defaultStack」を指定すると、ログにメソッドの実行時間が出力されます(Eclipseのコンソールでも確認できます)。

[リスト7ZeroAnn.javaの一部

import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.InterceptorRef;
import org.apache.struts2.convention.annotation.InterceptorRefs;

    ...中略...

@InterceptorRefs( { @InterceptorRef("timer"),
    @InterceptorRef("defaultStack") })
public class ZeroAnn extends ActionSupport {

    ...中略...

    @Action("/ann/zero")
    public String execute() throws Exception {
        return "success";
    }
}

 ログの出力は、次のようになります。

情報: Executed action [/ann/zero!execute] took 197 ms.

 

Resultアノテーション

 Resultアノテーションは、Result処理をカスタマイズする際に使用します。このアノテーションでは、クラスレベルでの指定と、Actionメソッド単位での指定が可能です。

 例えば次のように指定すれば、このActionクラスのすべてのActionメソッドで、"failure"というResultコードのときには、fail.jspを用いるようになります。現在時刻の秒数が偶数なら、"failure"を返すようにしていますので、そのときだけ「fail.jsp」が表示に用いられます。

[リスト8ZeroAnn2.javaの一部

import java.text.SimpleDateFormat;
import java.util.Calendar;
import com.opensymphony.xwork2.ActionSupport;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;

@Results({
  @Result(name="failure", location="fail.jsp")
})
public class ZeroAnn2 extends ActionSupport {

    ...中略...

    public String execute() throws Exception {

        Calendar cal = Calendar.getInstance();
        SimpleDateFormat d = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        this.replyMsg = d.format(cal.getTime());

        // 現在時刻の秒が偶数なら、failureを返す。
        if ((cal.get(Calendar.SECOND) % 2) == 0) {
            return "failure";
        }
        return "success";
    }
}

 Actionメソッド単位に指定するには、次のようになります。type属性を使って、Result処理の種別を指定することもできます。

[リスト9ZeroAnn2.javaの一部

public String execute() throws Exception {

 ...中略...

@Action(value = "/ann/zero5",
    results = { @Result(name = "success",
        location = "http://codezine.jp/", type = "redirect") })
public String execute2() {
    return "success";
}

ResultPathアノテーション

 ResultPathアノテーションは、Result処理で指定するViewテンプレートファイルの場所を指定するアノテーションです。この場所は、デフォルトでは「WEB-INF/content」になっています。

 また、ResultPathアノテーションは、メソッドレベルでは指定できません。クラスレベルで指定するか、または、パッケージに対するコメントやアノテーションを記述するpackage-info.javaに記述する必要があります。

 例えば次のようにすると、このActionクラスでは、「WEB-INF/jsp」からViewテンプレートファイルがサーチされることになります。

[リスト10ZeroAnn3.javaの一部

import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.ResultPath;

@ResultPath("/WEB-INF/jsp")
public class ZeroAnn3 extends ActionSupport {

    ...中略...

    @Action("/ann/zero6")
    public String execute() {
        return "success";
    }
}

 パッケージ内に、次のような「package-info.java」があると、今度は、パッケージに含まれるActionクラスすべてに指定したことになります。「package-info.java」は、JDK1.5以降の機能で、パッケージの宣言と、アノテーション、コメントだけのファイルです。

[リスト11package-info.java

@org.apache.struts2.convention.annotation.ResultPath("/WEB-INF/jsp")
package zero.action.ResultPath;

その他のアノテーション

 上記以外には、パッケージ単位で任意のURIの起点を指定するNamespaceアノテーションや、例外がスローされたときの遷移先を指定する、ExceptionMappingアノテーションなどがあります。

 詳しくは、「Convention Plugin」のドキュメントを参照してください。

XMLファイルによる既定値のカスタマイズ

 struts.xmlファイルに<constant>タグで設定を記述することによって、既定値を変更することが可能です。

 例えば、struts.xmlに次のような記述を追加すれば、ResultPathの既定値を変更することができます。

<constant name="struts.convention.result.path" value="/WEB-INF/jsp/"/>

主な既定値

 次の表に、主な既定値をまとめました。

主な変更可能設定項目

設定項目

既定値

概要

struts.convention.result.path

/WEB-INF/content/

Viewテンプレートのデフォルトディレクトリ

struts.convention.action.suffix

Action

Actionクラスと認識するためのサフィックス文字列

struts.convention.action.
disableScanning

FALSE

Actionクラスを探すために、パッケージをサーチするか否か

struts.convention.action.
mapAllMatches

FALSE

@Actionアノテーション」なしで、メソッドをActionメソッドとして扱うか否か

struts.convention.action.
name.lowercase

TRUE

アクション名を小文字に変換するかどうか

struts.convention.action.
name.separator

-

アクション名や、Viewテンプレートの区切り文字

struts.convention.package.
locators

action,actions,struts,struts2

Actionクラスを探すパッケージ名

struts.convention.package.
locators.disable

FALSE

上記で指定したパッケージからのサーチを行うか否か

struts.convention.exclude.
packages

org.apache.struts.*,
org.apache.struts2.*,
org.springframework.web.struts.*,
org.springframework.web.struts2.*,
org.hibernate.*

Actionクラスのサーチから除外するパッケージ名

struts.convention.package.
locators.basePackage

 

ここで指定したパッケージを起点としてActionクラスをサーチする

文字化け防止措置

 前述した文字化けの対処として、文字コードを変換する方法を紹介します。文字化けは、パラメータの受け渡しで発生しますので、パラメータのセッターのところで、変換処理を行います。

 引数の文字列を、getCharacterEncodingメソッドで取得したリクエストデータの文字コードで変換しています。

[リスト12ZeroAnn.javaの一部

public class ZeroAnn extends ActionSupport {

    ...中略...

    public void setReplyMsg(String message) {
        try {
            HttpServletRequest request = ServletActionContext.getRequest();
                this.replyMsg = new String(message.getBytes("iso-8859-1"),
                        request.getCharacterEncoding());
        } catch (UnsupportedEncodingException e) {
        }
    }

 このようにすると、次のように、パラメータに日本語を指定しても、正しく文字がセットされます。

[リスト13index.jspの一部

<s:url id ="link" action="ann/zero">
<s:param name="replyMsg">ゼロコンフィギュレーション</s:param>
</s:url>
<s:a href="%{link}">文字化け応急措置</s:a><br />