2008年12月19日金曜日

Surf Dev. Guide [2.10 テンプレートのレンダラ ]

2.9 テンプレートの種類
本文なし

------------------------------------------------------------------------------
2.10 テンプレートのレンダラ
下記の例は「share」の「search.ftl」である。


<#import "import/alfresco-template.ftl" as template />
<@template.header>
<link rel="stylesheet" type="text/css" href="${url.context}/templates/wiki/wiki.css" />
</@>

<@template.body>
<div id="hd">
<@region id="header" scope="global" protected=true />
<@region id="title" scope="template" protected=true />
</div>
<div id="bd">
<div class="yui-t1">
<div id="yui-main">
<@region id="search" scope="template" protected=true />
</div>
</div>
</div>
</@>

<@template.footer>
<div id="ft">
<@region id="footer" scope="global" protected=true />
</div>
</@>




------------------------------------------------------------------------------
2.11 テーマ
本文なし

Surf Dev. Guide [2.8 テンプレートのインスタンス ]

2.8 テンプレートのインスタンス
このサンプルは「share」の「site-data/template-instances/search.xml」である。
指定されているFreeMarkerレンダラは、「classes/alfresco/templates/org/alfresco/search.ftl」である。


<?xml version='1.0' encoding='UTF-8'?>
<template-instance>
<template-type>org/alfresco/search</template-type>
<properties>
</properties>
</template-instance>



上記のサンプルがうまくいく理由は、「テンプレート型」がSurfにとって未知である
(すなわち、webscript,fremarker,などでない)場合には、それをfreemarkerと仮定して
指定のURLから見つけてくるからである。

この他、より明示的に指定する方法としては:



<template-instance>
<template-type>freemarker</template-type>
<url>org/alfresco/search</url>
<properties>
</properties>
<template-instance>

2008年12月18日木曜日

Surf Dev. Guide [2.7 ページ関連]

2.7 ページ関連
ページ関連オブジェクトによって、2つのページを一緒にリンクすることができます。
最も一般的なのな、このリンクは型において子であり、意味するのは
ナビゲーションツリーのような確定した構造を表現することです。
しかし、別の型も可能であり、「ページ関連」が単一の確定木構造だけを
サポートする手段として使用すべきという要件はありません。

関連を使用しての、複数の木構造も可能です。この関連の性質は、
子を超えて拡張した場合、分類子、カテゴリ、タグに非常に類似しています。
言い換えれば、ページが他のページに関連付けられているとしても、
同時に他の要素にも側面からの関連付けを持たせてもよいのです。
これは、ファセットナビゲーションやタグクラウドの実装を考慮しています。

保管場所

/WEB-INF/classes/alfresco/site-data/page-associations


プロパティ

  • id => オブジェクトのid (オプション)

  • title => ページ関連のタイトル (オプション)

  • description => ページ関連の説明 (オプション)

  • source-id => 親要素のid、たいていはページid

  • dest-id => リンクした要素のid、たいていはページid

  • assoc-type => 関連の型



2.7.1 サンプルのページ関連

<page-association>
<title>Products</title>
<source-id>page.home</source-id>
<dest-id>page.products</dest-id>
<assoc-type>child</assoc-type>
</page-association>



注:ホームページと製品ページのリンクは、子の関係を使用している
現在のところ、子の関係のみがSurfプラットホームで認識されます。

Surf Dev. Guide [2.6 ページ]

2.6 ページ
「ページ(page)」とはWebアプリケーションで到達できるページです。
複数の他ページやそのページをキーとしてテンプレートと繋がる複数のフォーマット
と関連することもあります。ページは、トップレベルのオブジェクトであり、
そこを元にして追加的なナビゲーションやレンダリングのパスをたどることができます。

保管場所

/WEB-INF/classes/alfresco/site-data/pages


プロパティ

  • id => オブジェクトのid (オプション)

  • title => コンポーネントのタイトル(オプション)

  • description => コンポーネントの説明(オプション)

  • template-instance => このページを表示するためのテンプレートインスタンスのid

  • authentication => このページを見るために要求される認証(none,user,adminなど)



2.6.1 サンプルのホームページ

<page>
<title>My Home Page</title>
<template-instance>home-main</template-instance>
<authentication>none</authentication>
</page>



注記:シンプルな認証されていないのホームページ
レンダリング時に、ページのマークアップ表示は、ページから
「home-main」テンプレートへ移譲される。

2.6.2 サンプルのホームページ( 2つのフォーマット、ユーザー認証が必要)

<page>
<title>My Home Page</title>
<template-instance>home-main</template-instance>
<template-instance format="print">home-print</template-instance>
<authentication>user</authentication>
</page>



注:アクセスするにはユーザー認証が必要です。
印刷フォーマットが要求された場合、結果表示のために別テンプレート
(home-print)が活躍する。

1つのJVMで異なるライブラリを使用する環境を使う

JBOSSのアプリケーション内から、GlassFishのクライアントコンテナを使用するようなこと。
J2EE関連のライブラリ(JAR)などが競合しそうで、そのままでは使用できそうもない。

アイデア1) GlassFish環境でRMIサーバを立ち上げてRMIベースで連携
そもそも、GlassFishを使用するのはEJBを使うためなので、
RMI->EJB では、ごてごてしすぎだしパフォーマンスも悪くなる
EJB(RMI/IIOP)は単なる接続だけなら製品間のInteroperabilityがあるようだが、
  LoadBalanceやFailOverがからむと、専用のクライアントコンテナが必要になったりする

アイデア2) JavaModeleSystemを使用する:まだドラフト状態

アイデア3)OSGi を利用する:バンドル毎に異なるライブラリを定義できる
 JBOssなどのAppContainerから使用できるかが問題(要調査)

用語:
・Java Module System : 使用するライブラリの集合をモジュールとして定義できる
JSR 277  JAM形式のファイルにパッケージしてモジュールを分離
       リポジトリを持ち、動作時に使用するものを判断してロード
 RubyGemやPerlCPAMに似たしくみ

・OSGi Open Services Gateway initiative
JSR 291: Dynamic Component Support for Java SE
  バンドル毎に異なるライブラリを指定してインストールを動的に行える
  現状ではMinifestベース
 使用している製品 Apache Felix、Knopflerfish、Eclipse Equinox

2008年12月15日月曜日

Surf Dev. Guide [2.5 コンテンツ関連]

2.5 コンテンツ関連

「コンテンツ関連」オブジェクトが意図しているのは、Surfプラットホームが
入力されたコンテンツ部品に対するビュー表示をいかにして処理すべきかという
ことである。

別の言い方をするなら、エンドユーザが指定されたドキュメントに対する
詳細情報を表示するためにリンクをクリックしたとする。目的とするのは
そのドキュメントを開くことではなく、メタデータやプロパティを表示することである。

Surfプラットフォームを使用すると、「document-details-viewer」と呼ぶ
汎用ページを定義することができます。エンドユーザーがシステム内の任意の
文書についての詳細を表示したい時には、このページを使用してもらいたいでしょう。

「コンテンツ関連」を作成し、そのドキュメントとそのページを関連づける
ことでそれが可能になります。特定の文書(オブジェクトidによる)だけでなく、
特定のタイプのドキュメント(オブジェクト型idによる)を関連付けることができます。
ページインスタンスだけでなく、ページ型に対しても関連させられるんのです。

Surfプラットホームで実現していることは、エンドユーザーがドキュメントを
クリックして、「コンテンツ関連」のインスタンスに目を向けられるように、
このコンテンツを表示するためにどこに行くべきかを識別することである。
表示されるページとドキュメントコンポーネントは、利用可能なすべての
コンテンツを有しており、再読み込みが不要である。

保管場所

/WEB-INF/classes/alfresco/site-data/content-associations


プロパティ

  • id => オブジェクトのid (オプション)

  • title => コンテンツ関連のタイトル

  • description => コンテンツ関連の説明

  • source-id => 関連させるコンテンツ型

  • dest-id => コンテンツ型を表示するページまたはコンポーネント

  • assoc-type => 関連の型, 例) page, etc.



2.5.1 サンプルの構成

<content-association>
<title>details: cm_content</title>
<source-id>{http://www.alfresco.org/model/content/1.0}content</source-id>
<dest-id>page.content.details</dest-id>
<assoc-type>page</assoc-type>
</content-association>



注:「http://www.alfresco.org/model/content/1.0 コンテンツ」という型のコンテンツと
表示の時に使用される「page.content.details」というidを持つページとの関連:
This is an example of how you might use the Surf platform to render Alfresco content into a page.
これが例示するのは、Alfrescoコンテンツをページとして表示させるには、
Surfプラットフォームをどう使用すればいいかということ。

Surf Dev. Guide [2.4 構成]

2.4 構成
構成オブジェクトはXMLの集合体であり、その目的は、自然であり妥当なものです。
構造化され永続化されたXML(プロパティとメンバーが分かっている)を持つモデルオブジェクトとは裏腹に、
1つの「構成」が要件としてもつのは、たった1つのこと --- 1つの「id」 --- である。
このidは、XMLから特定されるかファイル名から決定されます。

一般的に、高度なカスタマイズを要する以外は、「構成」オブジェクトを
扱う要はありません。 それらは、主にシステムによって内部的に使用されています。

保管場所

/WEB-INF/classes/alfresco/site-data/configurations


プロパティ

  • id => オブジェクトのid (オプション)

  • title => コンポーネントのタイトル

  • description => コンポーネントの説明



2.4.1 サンプルの構成
「構成」オブジェクトが使用されている場所の1つは、
「global site」に関連する情報を格納するためのです。
現在、 「web site」オブジェクトという概念は、存在しません。
代わりに、「web site」の構成は「構成XMLファイル」として格納されます。
一例はこちら(注意 「root-page」要素は最初に呼び出されるもの):


<configuration>
<title>Surf Platform 3.0 Sample Site</title>
<description>Surf Platform 3.0 Sample Site</description>
<source-id>site</source-id>
<properties>
<root-page>welcome</root-page>
</properties>
</configuration>



注:このXMLは、任意にどんな構造でも持たせることが可能です。
この意味では、構成オブジェクトのことを汎用モデルオブジェクトとして考えることができます。

Surf Dev. Guide [2.3 コンポーネント]

2.3 コンポーネント

コンポーネントは、 コンポーネント型のインスタンスであり、領域またはスロットに属します。
コンポーネントと結合することで、インスタンスはその固有状態を表明することになります。
保管場所

/WEB-INF/classes/alfresco/site-data/components


プロパティ

  • id => オブジェクトのid (オプション)

  • title => コンポーネントのタイトル

  • description => コンポーネントの説明

  • component-type => コンポーネント型id (optional)

  • scope => 結合のスコープ (「global」, 「template」または「page」のどれか).

  • region-id => コンポーネントを領有する領域(またはスロット)のid

  • source-id => コンポーネントが結合する「global」か「page」id か「template」

  • url => レンダラによって実行されるファイルへのパス



2.3.1 サンプルWebScriptコンポーネント

<component>
<scope>page</scope>
<region-id>content</region-id>
<source-id>welcome</source-id>
<url>/test/configtest</url>
</component>


注記: 「pageスコープ」のコンポーネントが、「welcome page」の「content領域」に入ります。
コンポーネント型が指定されていないため、URLプロパティが検査され、WebScriptであると判断されます。
したがって、このコンポーネントでは、 urlが「/test/configtest」であるWebScriptが実行されます 。

2.3.2 サンプルのJSPコンポーネント

<component>
<component-type>jsp-sample-component-type</component-type>
<scope>template</scope>
<region-id>news</region-id>
<source-id>product</source-id>
</component>


注:「templateスコープ」のコンポーネントが、「productテンプレート」の「new領域」に所属します。
コンポーネント型は「jsp-sample-component-type」であり、これは前にサンプルとしてあげています。
これは、JSPレンダラであり、すべてのレンダリング情報はコンポーネント型の上に含まれています。

2008年12月10日水曜日

Surf Dev. Guide [2.2 コンポーネント型]

2.2 コンポーネント型

コンポーネント型とは、Webサイトビルダーが把握し生成する物であり、
Webアプリケーションの多くの箇所で使用されます。新規インスタンスは領域
(またはスロット)にはめ込むことでページと結合します。他のフレームワーク
では、時として「ウィジェット」、「ガジェット」、「ポートレット」、または
「dashlet」と呼ばれています。

保管場所

/WEB-INF/classes/alfresco/site-data/component-types


プロパティ

  • id => オブジェクトのid (オプション)

  • title => コンポーネント型のタイトル

  • description => コンポーネント型の説明

  • renderer-type => レンダラのid (設定で定義、典型例:webscript, jsp, java)

  • renderer => レンダラによって実行されるファイルへのパス




2.2.1 サンプルのWebScriptコンポーネント型

<component-type>
<title>Alfresco RSS Newsfeed Component</title>
<description>Displays a configurable number of Alfresco news items</description>
<renderer-type>webscript</renderer-type>
<renderer>/sample/alfresco-newsfeed</renderer>
</component-type>


注記: レンダラは、WebScriptのXML説明文書内で定義されているWebScriptへのURL

2.2.2 サンプルのJSPコンポーネント型

<component-type>
<id>jsp-sample-component-type</id>
<title>Alfresco RSS Newsfeed Component</title>
<description>Displays a configurable number of Alfresco news items</description>
<renderer-type>jsp</renderer-type>
<renderer>/app/components/alfresco-newsfeed</renderer>
</component-type>


注記: レンダラは、 JSPファイルへのパス(web-application相対的)

2.2.3 サンプルのJava Beanコンポーネント型

<component-type>
<title>Alfresco RSS Newsfeed Component</title>
<description>Displays a configurable number of Alfresco news items</description>
<renderer-type>java</renderer-type>
<renderer>org.alfresco.web.site.ui.AlfrescoRSSNewsFeed</renderer>
</component-type>


注記: レンダラは、インスタンス化される Java Beanのクラス名。
このJavaクラスは、「Renderable」インターフェイスを実装する必要があります。
これに関しては別のセクションでより詳細に扱います。

Surf Dev. Guide [2 オブジェクトモデル]

2 オブジェクトモデル

Webアプリケーションの基本セクションでは、Surfプラットホームのデータモデル
に関して高次の概要を説明していた。本セクションで、各オブジェクトタイプの詳細に入る。

------------------------------------------------------------------------------
2.1 クロム

クロムは、コンポーネントの周辺を取囲む境界要素を意味するものである。
これら境界要素とは、「影付け」のようなスタイル要素を含んだり、
ページにドラッグアンドドロップ機能を付加するものだったりする。
また、ポップアップコンポーネントを設定するボタンのような
「ユーザ機能」を付加させることもある。(しばしばポータルで見かけるもの)

デフォルトでは、クロムはSurfプラットホーム内では最小限に留められています。
新しいコンポーネントが、ページに追加されると、Webアプリケーションのための
デフォルトchromeを受け取ることになります。(当初は空の既製品)

保管場所

/WEB-INF/classes/alfresco/site-data/chrome


プロパティ

  • id => オブジェクトのid (オプション)

  • title => クロムのタイトル

  • description => クロムの説明

  • renderer-type => レンダラのid (設定で定義)

  • renderer => レンダラによって実行されるファイルへのパス



2.1.1 サンプルのJSPクロム

<chrome>
<title>Sample Chrome 1</title>
<renderer>/app/sample-chrome-1.jsp</renderer>
<renderer-type>jsp</renderer-type>
</chrome>


注記: レンダラは、 JSPファイルへのパス(web-application相対的)

2.1.2 サンプルWebScriptクロム

<chrome>
<title>Sample Chrome 2</title>
<renderer>/sample/chrome-2</renderer>
<renderer-type>webscript</renderer-type>
</chrome>


注記: レンダラは、WebScriptのXML説明文書内で定義されているWebScriptへのURL

2.1.3 領域用サンプルクロムテンプレート
@コンポーネントを使用して、領域内のコンポーネントを含めることができます。


<div id="${htmlid}">
<@component/>
</div>



2.1.4 コンポーネント用サンプルクロムテンプレート
@componentIncludeを使用して、コンポーネントが表示される場所を指定できます。


<!-- Start Debug Component Chrome -->
<div style="border: 2px black solid">
<div style="background-color: #aaaaaa; border-bottom: 1px black solid; color: white; padding: 2px"><B>${htmlid}</B></div>
<div style="background-color: #dddddd; padding: 2px">
<@componentInclude/>
</div>
</div>
<!-- End Debug Component Chrome -->

2008年12月9日火曜日

Surf Dev. Guide [1.4 レンダラ]

1.4 レンダラ

新規テンプレートや新規コンポーネントとして定義するために行うのは、
Surfプラットホーム用のモデルオブジェクトを記述するXMLを書くことである。
モデルオブジェクトの役割は、Surfプラットホームに、コンポーネントの存在と
コンポーネントを処理する方法についての情報を与えることである。
とはいっても、後からテンプレートやコンポーネントがどう表示されるかの
情報は開発者が与える必要があります。そのために、「renderer」が必要になります。

少数の「renderer」が既製品として提供されていますが、自分用に追加してもかまいません。
サポートされる既製品の「renderer」は、以下のものである。

  • WebScript

  • Freemarker

  • JSP

  • HTML


1.4.1 WebScriptレンダラ

WebScriptレンダラは、最先端のレンダラであり、これを利用することで
(pre-render処理で)JavaScriptの、(presentation処理で)Freemarkerの、
という2つの利点を活用できることである。

もし以前に、Alfrescoの「web script engine」を利用してWebScriptを構築
したことがある方々は、既に知っていることと思います。
それ以外の場合は、 WebScriptガイドを見てください 。

Surfプラットホーム内では、WebScriptがコンポーネントを表示するためには
最も一般的に使用されます。自分のWebScriptを構築したならば、
/ WEB-INF/classes/alfresco/site-webscriptsのディレクトリに配置します。
少し経つと、コンテナがそれを拾い上げ、自分のモデルオブジェクトから
使用できるようになります。

WebScriptを使用することをコンポーネント側に指示するには、
WebScriptのURLプロパティに適切なurlを設定すること。

1.4.2 FreeMarkerレンダラー

Freemarkerレンダラは、テンプレートを表示する場合に最もよく使用されます。
また、WebScriptレンダラとの組み合わとして自動的に使用されますが、
それはコンポーネントに適用される場合だけです。テンプレートを作成すると、
Freemarkerを直接使用することができます。

Freemarkerテンプレートを作成していて、Alfrescoで使用している方々は
何ができるかについてはすでに熟知していることでしょう。そうでない場合は、
「Alfresco Freemarkerテンプレートガイド」を参照してください。

Surfプラットホーム内では、Freemarkerの「.ftl」テンプレートファイルは、
/ WEB-INF/classes/alfresco/templates ディレクトリに配置することができます 。
少し経つと、テンプレートプレセサがそれを拾い上げ、自分のモデルオブジェクトから
アクセスできるようになります。

テンプレート側にFreemarkerの「.ftl」ファイルを使用することを指示するために
「template-type」パラメータにファイルパス(/templatesからの相対)を
設定すること。

1.4.3 JSPレンダラー

JSPレンダラは、 コンポーネントまたはテンプレートのどちらかを表示するために
使用されており、Java言語の全てとSurfプラットホームのJavaAPIへのアクセスを提供
しています。使用するには、Javaプログラミングの知識が必要です。

JSPレンダラを使用するには、「.jsp」ファイルを作成して、web-applicationの
任意の場所に配置する必要があります。ただし、慣例として /app/components
ディレクトリの下に配置することをお勧めします。

一旦配置した後で、JSPのパス(web-application相対)に対してのレンダラプロパティ
を設定します。後の方で詳しく説明します。

Surf Dev. Guide [1.3 モデルオブジェクト]

1.3 モデルオブジェクト

Surfプラットホームには、それが管理し参照する必要があるオブジェクトのデータモデルが含まれ、
それによって、Webアプリケーションを正しく表示できます。
これらのモデルオブジェクトはメモリに標準的POJO(Plain Old Java Object)として管理されています。
ディスクに書き込むときには、 XMLとしてシリアル化されます。

XMLが格納されるのは、次の場所にあるサブディレクトリです:

/WEB-INF/classes/alfresco/site-data


このディレクトリ内には、次のようなサブディレクトリがモデルオブジェクトの
タイプ毎に1つ存在し、Surfプラットホームによって管理されています:

/site-data/chrome
/site-data/component-types
/site-data/components
/site-data/configurations
/site-data/content-associations
/site-data/page-associations
/site-data/page-types
/site-data/pages
/site-data/template-instances
/site-data/template-types
/site-data/themes


各サブディレクトリ内には、シリアル化されたモデルオブジェクトを表すXMLがあるはずです。
たとえば、デフォルトのalfwf.warファイル内では、welcome.xml というファイルがあります 。
これは、「welcome」というidを持つページであり、内容は次のXMLとなっています:

<?xml version='1.0' encoding='UTF-8'?>
<page>
<title>The test welcome page</title>
<template-instance>welcome-main</template-instance>
<authentication>none</authentication>
</page>


各オブジェクトタイプの正確な意味は、オブジェクトモデルのセクションで
扱われるので、ここでは一般的な感じを示すにとどめます。
XMLを調べて分かることは、これがページであり、
そのタイトルは「The test welcome page」。
テンプレートは「welcome-main」というidで示されること。
アクセスには 認証を必要としないこと。

新規ページまたは新規コンポーネントまたは何らかのモデルオブジェクトを作成するには、
これらのディレクトリに新しいXMLを配置すればよい。
すなわち、データベースにアクセスする必要も、Webクライアントをカスタマイズする必要もないのです。

2008年12月8日月曜日

Surf Dev. Guide [1.2 振分サーブレット]

1.2 振分サーブレット

振分サーブレットの責務は、ユーザーにページを表示することです。
着信要求コンテキストを考慮して、何をどのように表示するかを明確化する
必要があります。
振分が受信可能な要求は、以下のものです:

特定のページ
ページIDが、振分に対して直に送付されることがあります。
ページタイプ
例として、ユーザーがログインページを要求するとします。
アプリケーションが実際には複数のログインページを持っており、
(顧客向けに1つ、 パートナー向けに1つ、従業員向けに、、、など)
そこから1つ選択し、表示して返す必要があります。
オブジェクト
An object id may be given to the dispatcher.
オブジェクトIDが、振分に送付されることがあります。
The dispatcher must then figure out which page to use to render this object.
その場合、振分はこのオブジェクトを表示するためにどのページを使用すべきかを
明確化する必要があります。
他にも組み合わせや、順序の違いが数多くあり得ます。
よって、振分サーブレットは、最小限の工数で動作をカスタマイズできるように
実装されています。
これら拡張機能の正確な性質は、上級編で扱います。

2008年12月5日金曜日

Surf Dev. Guide [1.ウェブアプリの基本]

1 ウェブアプリケーション基礎
このセクションはSurfプラットホームウェブアプリケーションについて説明します。
一般に、SurfプラットホームウェブアプリケーションはWARとしてパッケージされます。
デフォルトで作成されるalfwf.warファイルは、そのようなWARファイルの一例です。

1.1 構成
 WARファイルを展開すると、ここで示すような構成になっています:
 

/core
/css
/images
/WEB-INF
/WEB-INF/classes/alfresco
index.jsp



いくつかのディレクトリが追加されることもありますが、これらが基本構成です。
それはまさに純然たるウェブアプリケーションです。

初めに注目するファイルは「web.xml」であり、WEB-INFの下に位置します。
サーブレットコンテナは、始動時にこのファイルを読み込みます。
「web.xml」の中に、サーブレットとSpringオブジェクトのための設定があります。
それは軽量に保たれますが、いくつかのセクションに注意するべきです。

以下のセクションは「Spring Framework コンテキスト」にロード方法を示します。
Springは、Surfプラットホームに含まれていて、その責務はBeanの管理と生成になります。
このセクションで「webscript-framework-application-context.xml 」が導入されます。
(WebScript Engine構成をロードする)
それから、「web-framework-application-context.xml」を導入します。
(Surfプラット設定をロードする)

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:alfresco/webscript-framework-application-context.xml
classpath:alfresco/web-framework-application-context.xml
</param-value>
<description>Spring config file locations</description>
</context-param>



一度 Webアプリケーションを起動すると、いくつかのサーブレットが利用可能になる。
DispatcherServletもその一つであり、要求をSurfプラットフォームへと導く
主要なハンドラとなっている:

<servlet>
<servlet-name>pageRendererServlet</servlet-name>
<servlet-class>org.alfresco.web.site.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>pageRendererServlet</servlet-name>
<url-pattern>/page/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>pageRendererServlet</servlet-name>
<url-pattern>/p/*</url-pattern>
</servlet-mapping>



リクエストがWebアプリケーションに到着してindex.jspをたたくと、
ディスパッチャサーブレットに転送されます。(/pageへのフォワード)

Alfresco3.0/Suf

SurfPlatformはAlfrescoが持っている、WebApplicationFrameWorkであり、
AlfrescoECMへのAPIを有するCMSといった感じ。基本的にはDashletという
構成部品をならべることでページを作成する。

Surf Platform - Developers Guide

概要を調査

Contents 内容

1 Web Application Basics ウェブアプリの基本
1.1 Structure 構成
1.2 Dispatcher Servlet 振り分けサーブレット
1.3 Model Objects モデル
1.4 Renderers レンダラー
1.4.1 Web Script Renderers WebScriptレンダラー
1.4.2 Freemarker Renderers FreeMarkerレンダラー
1.4.3 JSP Renderers JSPレンダラー

2 The Object Model オブジェクトモデル
2.1 Chrome クロム
2.1.1 Sample JSP Chrome 例:JSPクロム
2.1.2 Sample Web Script Chrome 例:WebScriptクロム
2.1.3 Sample Chrome Template for Region 例:領域に対するクロムテンプレート
2.1.4 Sample Chrome Template for Component 例:コンポーネントに対するクロムテンプレート
2.2 Component Type コンポーネント種別
2.2.1 Sample Web Script Component Type 例:WebScriptコンポーネント
2.2.2 Sample JSP Component Type 例:JSPコンポーネント
2.2.3 Sample Java Bean Component Type 例:JavaBeansコンポーネント
2.3 Component コンポーネント
2.3.1 Sample Web Script Component 例:WebScriptコンポーネント
2.3.2 Sample JSP Component 例:JSPコンポーネント
2.4 Configuration 設定
2.4.1 Sample Configuration 例:設定
2.5 Content Association コンテンツ関連
2.5.1 Sample Configuration 例:設定
2.6 Page ページ
2.6.1 Sample Home Page 例:ホームページ
2.6.2 Sample Home Page (two formats, user authentication required) 例:ホームページ(2形式、認証が必要)
2.7 Page Association ページ関連
2.7.1 Sample Page Association 例:ページ関連
2.8 Template Instance テンプレート
2.9 Template Type テンプレート種別
2.10 Template Renderer テンプレートレンダラー
2.11 Theme テーマ

3 Creating a New Template 新規テンプレートの作成
3.1 Freemarker Example FreeMarkerの例
3.2 JSP Example JSPの例
4 Creating a New Component 新規コンポーネントの作成
4.1 Web Script Example WebScriptの実例
4.2 JSP Example JSPの実例
4.3 Java Bean Example JavaBeansの実例
5 Advanced Surf Platform Configuration SurfPlatformの応用設定
5.1 Request Context 要求コンテクスト
5.2 Page Mapper ページマッパー
5.3 Users ユーザ
5.4 Link Builder リンクビルダ
5.5 File Systems ファイルシステム
5.6 Formats フォーマット
5.7 Model Types モデル種別
5.8 Tag Libraries タグライブラリ
5.9 Renderers レンダラー
5.10 Content Loaders コンテンツローダ
5.11 Error Handlers エラーハンドラ
5.12 System Pages システムページ
5.13 Dispatcher Defaults 振り分けの省略時設定
5.14 Application Defaults アプリケーションの省略時設定
5.15 Debug Settings デバッグ設定
5.16 Advanced Remote Configuration リモートの応用設定

GetProcess.cmd

状況によっては、内部で作成している WShell.exec("xx") の部分が非同期にならず、
PIDを取得しようとした時に当該プロセスが存在しないというエラーになる場合があった。
んで、改良版がこれ。呼び出すプロセスとしてcscript.exeの代わりにcmd.exeを
使用し、pauseにて入力を待つようにした。これだと非同期に実行でき、不要に
なったらさっと片づけられる。


@if(0)==(0) ECHO OFF
:: GetProcessId.cmd ver 1.2
:: PolymorphicScript(CMD/JSCRIPT)
:: http://scripting.cocolog-nifty.com/blog/2007/01/index.html
:: V1.1 20081127 ST(KRB)
:: V1.2 20081202 ST(KRB) replace vbs with self script cause file permission
:: V1.3 20081205 ST(KRB) use cmd.exe for inspect pid instead of cscript.exe
CScript.exe //NoLogo //E:JScript "%~f0" %*
GOTO :EOF
@end
//
var error_level = 0;
try
{
var pGene = 0;
if(WScript.Arguments.Named.Exists("P")) {
pGene = WScript.Arguments.Named.Item("P");
}
if(WScript.Arguments.UnNamed.Length==0) {
PrintPPid(GetPID(), pGene);
//WScript.Echo(GetPPID(GetPID()));
error_level = 0;
} else if(WScript.Arguments.UnNamed.Length==1) {
PrintPPid(WScript.Arguments.Item(0), pGene);
// WScript.Echo(GetPPID(WScript.Arguments.UnNamed.Item(0)));
error_level = 0;
} else {
WScript.StdErr.WriteLine("Usage: GetProcessID.CMD [/P:n | PID]");
error_level = 2;
}
}
catch(e)
{
WScript.StdErr.WriteLine("error:" + e.message);
error_level = 1;
}
finally
{
WScript.Quit(error_level);
}

function PrintPPid(ipid, igen){
var result = ipid;
for (var i=0;i <= igen;i++){
result = GetPPID(result);
}
WScript.Echo(result);
}

function GetPID(){
var Path=WScript.ScriptFullName;
var wShell=new ActiveXObject("WScript.Shell");
// if use cscript.exe ,cannot run as async mode
var oExec=wShell.Exec('cmd.exe /C pause');
var PID=GetPPID(oExec.ProcessID);
try{
// Terminate() may needs waite time for several seconds
// so input as enter to 'pause' cmd
oExec.StdIn.WriteLine("");
oExec.Terminate();
}
catch(e)
{
// none
}
return PID;
}

function GetPPID(PID){
var SWbemObjectSet=GetObject("winmgmts:root/CIMV2").ExecQuery("SELECT * FROM Win32_Process WHERE ProcessID=" + PID);
if(SWbemObjectSet.Count!=1){
WScript.StdErr.WriteLine("ID " + PID + " Not Found.");
WScript.Quit(1);
}
var Processes=new Enumerator(SWbemObjectSet);
for(;!Processes.atEnd();Processes.moveNext()){
var Process=Processes.item();
return Process.ParentProcessID;
}
}

2008年12月4日木曜日

Alfresco

プロジェクトでワークフローを伴ったWebAppの開発をしそうなので、JavaベースのOSSを調査中。
他の候補としては、magnolia, openCms などがある。

1)Aflresco: ECM 中程度の重さ、ドキュメント管理から出発:
政府機関などで使用実績あり、単純な機能はScriptとFreeMarker
2)Magnolia: ECM 軽くてきびきび、ドキュメント管理、Webページも作成しやすい
ワークフローのカスタマイズに難あり
3)OpenCMS: CMS とにかく重い、Memoryが2G以上必要

----------------------------------------------------
1)概要
ドキュメントの生成、更新、削除などの履歴と権限管理
指定の権限者の承認でフォルダーを移動するなどのワークフロー
CMSやWebAppの機能は、比較的最近「Surf Platform」を使用
2)SurfPlatformでのDashletの作成手順
参考:Writing a Hello World Dashlet for Alfresco Share

xxxxId に対する GET で使用するページなら、以下のようなものを作成する
xxxxId.get.xml WebScript 概要など
xxxxId.get.ftl FreeMarker のテンプレート、UI(HTML系)定義
xxxxId.get.js サーバサイド機能
xxxxId.get.config.xml
xxxxId.get.desc.xml
xxxxId.get.properties ラベルの文字などのプロパティ

ftl で使用できるスクリプトの一例
${msg("hello.world")} プロパティファイルから指定エントリを読み込んで出力

3)ボタンなどを追加
参考:Learning Surf 4 - Modifying Share documentLibrary with Create content button

2008年12月2日火曜日

Win32でのPID取得スクリプト改良版

参考にしたものは、VBSのファイルを作成する部分があり、権限によって動作しない
場合があったので、改良してみた。オプションによりN世代親のPIDを取得できる。


@if(0)==(0) ECHO OFF
:: GetProcessId.cmd ver 1.2
:: PolymorphicScript(CMD/JSCRIPT)
:: http://scripting.cocolog-nifty.com/blog/2007/01/index.html
:: V1.1 20081127 ST(KRB)
:: V1.2 20081202 ST(KRB) replace vbs with self script cause file permission
CScript.exe //NoLogo //E:JScript "%~f0" %*
GOTO :EOF
@end
// check if sleep
if(WScript.Arguments.Named.Exists("S")) {
var wait_period;
wait_period = WScript.Arguments.Named.Item("S");
// dummy mode for make process
try{
WScript.sleep(wait_period * 1000 + 10);
}
catch(e)
{
// none
}
finally
{
WScript.Quit(0);
}
}
//
var error_level = 0;
try
{
var pGene = 0;
if(WScript.Arguments.Named.Exists("P")) {
pGene = WScript.Arguments.Named.Item("P");
}
if(WScript.Arguments.UnNamed.Length==0) {
PrintPPid(GetPID(), pGene);
//WScript.Echo(GetPPID(GetPID()));
error_level = 0;
} else if(WScript.Arguments.UnNamed.Length==1) {
PrintPPid(WScript.Arguments.Item(0), pGene);
// WScript.Echo(GetPPID(WScript.Arguments.UnNamed.Item(0)));
error_level = 0;
} else {
WScript.StdErr.WriteLine("Usage: GetProcessID.CMD [/P:n | PID]");
error_level = 2;
}
}
catch(e)
{
WScript.StdErr.WriteLine("error:" + e.message);
error_level = 1;
}
finally
{
WScript.Quit(error_level);
}

function PrintPPid(ipid, igen){
var result = ipid;
for (var i=0;i <= igen;i++){
result = GetPPID(result);
}
WScript.Echo(result);
}

function GetPID(){
var Path=WScript.ScriptFullName;
var wShell=new ActiveXObject("WScript.Shell");
var oExec=wShell.Exec('CScript.exe //B //E:Jscript "' + Path + '" /S:0');
var PID=GetPPID(oExec.ProcessID);
try{
oExec.Terminate();
}
catch(e)
{
// none
}
return PID;
}

function GetPPID(PID){
var SWbemObjectSet=GetObject("winmgmts:root/CIMV2").ExecQuery("SELECT * FROM Win32_Process WHERE ProcessID=" + PID);
if(SWbemObjectSet.Count!=1){
WScript.StdErr.WriteLine("ID " + PID + " Not Found.");
WScript.Quit(1);
}
var Processes=new Enumerator(SWbemObjectSet);
for(;!Processes.atEnd();Processes.moveNext()){
var Process=Processes.item();
return Process.ParentProcessID;
}
}

Win32でのRuntime.getRuntime().exec() のexitCode

Cscript.exe などを実行すると、エラーがでてもexitCodeは「0」のまま?
どうも、明示的に指定しておかないといけないらしい。つまり、WScript.Quit(n)
を入れておかないと、CScript.exe は正常終了と考えてしまうようだ。

■例

var error_level = 0;
try
{
// varius processes
if (ok){
error_level = 0;
}else{
error_level = 2;
}
}
catch(e)
{
WScript.StdErr.WriteLine("error:" + e.message);
error_level = 1;
}
finally
{
WScript.Quit(error_level);
}

2008年11月27日木曜日

WindowsでのPID取得

一覧を取得するScript類はいろいろ見たが、自分のを調べるのは少ないようだ。


一覧を取得するコマンド:
コマンド類の説明:Managing Processes in Windows NT 4 / 2000 / XP

C#によるコード:知識のゴミ箱:プロセスIDを取得する(.NET) CommentsAdd Star

自分のを調べるPolymorphicScript:Windows Script Programming:バッチファイルで現在や親のプロセスIDを調べる。

Bashの一文字コマンド

さっきのPolymorphicScriptの参考リンク中に「bash の : コマンド」が
出てくる。これはbashの組込コマンドであり、意味は、

: [arguments]
何もしません。このコマンドは arguments を展開し、指定されたリダイレクトを実行する以外には何も行いません。終了コード 0 を返します。

ということだ。他に有名な1文字コマンドは、

. filename [arguments]
source filename [arguments]
filename からコマンドを読み込み、現在のシェル環境のもとで実行します。

がある。

PolymorphicScript

1つのスクリプトに複数の言語を混在させているものをこう名付ける。

例)Windows CMDファイルにJscriptを内包する
 両者で文法エラーにならず、片方は読み飛ばせる文を使用する。

1)CMD:変数の設定文 JScript:環境変数の設定+ブロックコメントの開始
@set @_=1/*
CScript.exe //NoLogo //E:JScript "&~f0" %*
GOTO :EOF
*/

2)CMD:1行IF文 JScript:ifマクロで、@endまでスキップ
@if(0)==(0) ECHO oFF
CScript.exe //NoLogo //E:JScript "&~f0" %*
GOTO :EOF
@end

*JScriptでは、このように解釈され、if(0)はfalseなので文法チェックされない
@if(0)
==(0) ECHO OFF
...
@end

* "%~f0" は実行したファイルパスそのものを指す

参考:
それはそれ。これはこれ。:[CMD]WSHスクリプトのBATスクリプトへの組み込み(前編)

Windows Script Programming:バッチファイルで現在や親のプロセスIDを調べる。

2008年11月26日水曜日

Swing BeanBinding DateをJTextFieldにBindするには

NetBeans6.5にてDBアプリの自動生成を使用して、テーブルデータを表示する画面を作成した。
ところが、リストを選択した時にすべての項目が「詳細部分」に表示されるテーブルと、されない
テーブルがある。ログをみると、表示されない場合は、以下のようなExceptionがあった。

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException
at java.lang.Class.cast(Class.java:2951)
at org.jdesktop.beansbinding.Binding.convertForward(Binding.java:1312)
at org.jdesktop.beansbinding.Binding.getSourceValueForTarget(Binding.java:844)
at org.jdesktop.beansbinding.Binding.refreshUnmanaged(Binding.java:1222)


いろいろ調査してみた結果、問題はDateオブジェクトをJTextFieldのtextプロパティにCast
して設定しようとしているところらしいと判明。
 こんな感じ: jTextField1.setText((String)dateObj);
JFormattedTextFieldで日付を扱うものを用意し、そのValueにBindさせてみると、
無事にExceptionなしに表示された。

 教訓:IDEは便利だが、すべてをやってくれるわけではない。

Swing/EDT

 Swingはシングルスレッドモデルで、実際に動いているスレッドがEDT。
ここで長い処理をしたり、WaitやBlockをさせると画面描画関連が
すべて止まってしまうので、注意。
 Java6からは、Swingから非同期処理行うSwingWorkerが追加された。SwingWorkerのTutorial
Java5でもBackPortがある。SwingWorker-ackPort

SwingのDeBugなどに使用できるツール。Swingの処理速度の劣化原因を発見する。Detangler

 応用の一つで、ある一定の間隔が開くと処理を開始するWorkerの実装が紹介
されている。DelayedWorker
 たとえば、長いリストをスクロールしている時に早くスクロールすると
変化しないが、スクロールを止めたりゆっくりになると行の状態を表示
する機能などではこれがあると便利。

2008年11月19日水曜日

NetBeasn+TopLinkで作成されるEntity

対象がOracleだと、Entityに以下のようにスキーマ情報が入ってしまい、
スキーマを切り替えるとエラーになる

catalog = "", schema = "CQS01"

2008年11月18日火曜日

JPA:TopLinkEssential

NetBeans6.5にてJPAとSwingのサンプルを作成中、SQLでOrder By をかけると奇妙なエラーが発生。

select b from XXX ORDER BY b.JOB_INSTANCE_ID
token null
select b from XXX ORDER BY b.JOB_INSTANCE_ID
illegal
select b from XXX ORDER BY b.JobInstanceId
illegal

どうやら、使用できるカラムは、Entityとして使用しているクラスのフィールド名であり、大小文字もクラス定義に合わせて先頭が小文字でないとだめだったお。

select b from XXX ORDER BY b.jobInstanceId

2008年11月17日月曜日

AppServerからの自Servletアクセス

先週末は、RmtWebプロジェクトのバグをほぼつぶした。しかし、実行してみるとAppServerにRenderをさせる場合も、Proxyをさせる場合もTimeoutが発生したりして思うように動作しない。(初回はまず間違いなく失敗するが、数回やると成功する、、、とか安定しない)
■Servlet仕様
RenderServlet JEditoPane を利用して他サイトのURLをRenderし画像として返すもの
例) xxx/scrn.render?url=http://xxx.example.com/yyy/zzpage.html

DelegateServlet Proxy的に動作し、指定のURLの出力をそのまま返すもの
例) xxx/scrn.wget?url=http://xxx.example.com/yyy/scrn.capt?Size=25

そこで、さらに切り替えを増やして直接画面キャプチャを指定できるようにした。
外部ネットからだとアクセス不可になってしまうが、安定した。

■不安定な理由の推定
1)Render:
SwingのイベントモデルはSingleのため、HTTP接続で待ちが発生するとすべてが待ちになってしまう。
これは、通常のJEditoPaneがHTMLの解釈と要素のDonwloadが非同期であり、終了したことを検知しにくいことから、同期式の取得に変更した場合に発生した。
 もともとのJEditorPaneでは非同期でHTMLを解釈するために、上記のような詰まりは発生しないと思われるが、今度は画像リンクの解釈がうまくいかなかった。たとえば、xxx/scrn.capt で、「PNG画像」が来るのだが、これを画像と認識してくれず変な表示となる。同期式に変えた場合にはきちんと表示できるので、JEditorPaneのバグっぽい。

2)Proxy:
AppServerのServletから自分自身へHTTP接続することになるのだが、これが問題のようで、頻繁にConnectionTimeoutする。リトライするようにコードを追加したが、ちょっとましになった程度で安定せず。Servletのスレッドから自AppServerの他ServletへのNetアクセスに制限があるのかもしれない。

2008年11月13日木曜日

SwingはSingleThraedなので、、、

JEditoPaneのHtml表示のスレッドからSwingを使用するような
コードを呼び出してそこが invokeLater() などとしていると
デッドロックになってしまう!!!
 ところで、robot ってSwingスレッドを使用するの?
Maven2でPON.XMLで使用しているVersionをJavaのソースやリソースの中と同期させたいのだが、やり方がわからない。

たとえば、Java側で 特別なクラスを作成し、そこに
static final String VERSION = "0.2-SNAPSHOT";
などど定義しておいて、これをPOM.XMLから
$XXX.YYY#VERSION
などのように、使用することなのだが、未だやり方が可能なのかも含めて見つからず。
Pluginを自作するしかないのか?

2008年11月12日水曜日

世界のとらえ方

オブジェクト指向に限らず、システム分析の重大な関心事項の1つは対象とする世界(ドメインということが多い)をどうとらえ、どう表現するかということだ。分析の主眼が現状認識であることから、認識したものをシステム的な表現に落とし込むことが主たる作業となる。

対象とするものは複雑なものであったり、変動するものであったり、出来事や関係だったりする。よってそれを理解し管理しやすい塊へと分解してゆくことが求められる。そして、分解の仕方は、「それらをどう取り扱うのか」というシステム目的によって恣意的に変化し、大まかな捉え方から精密なものまで種々のくくり方ができる。

こうしてくくりだした事象をシステム的に表現する場合、塊(事象の枠組み)に対して名称を与え、その事象が持っている属性(プロフィール)を設定することになる。

プロフィールの記述には、「記述可能」特性を使用する。
「記述可能」とは、数値、文字、日付のような、何らかの文字や記号で記録し、他者とコミュニケーション可能なものという意味で用いる。また、記述可能特性には、「比較性」を持つものと持たないものがある。

「比較性」とは、~より大きい小さい、~より長い短い、~より広い狭い、など等号・不等号の関係でとらえることができるものである。言い換えれば数値に換算できるものと言ってもよい。比較可能でないものとしては、たとえば、「名前」や「国籍」などの同じだとか一部が似ているだとかの評価はできるが、不等式での評価ができないものをあげることが出来る。

「記述可能」でない特性としては、音楽や絵画などの時空間との関連でしか意味を持たないものなどがある。

たとえば、対象とする世界を乗り物と考え、子供が使う三輪車と、多くの乗客を乗せるジャンボジェット機を取り上げてみる。この2つのものは具体的なものとして存在し、触れることができるし、それぞれの機能性を持っている。

2008年11月4日火曜日

S2BatchでRestart

BatchがRestartableである時は、Execution_Contextに途中経過が保存され、再実行の時にそれを利用して続きから実行するようになる。
誰が何を書き込めばいいかを調査中。SampleではLOGN:2などの取得番号が保存されている。

2008年11月3日月曜日

大阪王将

また家族で行った。オーダーバイキングなので、できたてでおいしくて、満足度が高い。

2008年10月28日火曜日

クロージャー

Java7でクロージャーが取り入れる予定とのことで、クロージャーとは何かを調べてみた。
クロージャー とは、引数以外の変数を実行時の環境ではなく、自身が定義された環境(静的スコープ)において解決する関数のことである」とあるが、簡単に言うと関数をモジュールとして扱うことのようだ。
 UDS(Forte)での開発をしていた時、IDE上ではメソッドは独立した存在として扱うことができた。たとえば、あるメソッドを1つのクラスから別のクラスへDrag&Dropしたり、コピー・ペーストしたりなどである。ただし、コードの上ではこれを実現することはできず、メソッド(関数)をオブジェクト同様に引数として渡せれば、、と思う場面があったが不可能であった。
 関数型の言語では関数そのものを引数として渡したり、関数を戻り値にとるような「高階関数」という存在があるが、クロージャーはそれを限定的に使用したものということか。Javaで使用できるようになれば現在はAOPやCallBackとして実装している部分がかなりすっきすとしそうな感じがする。ただし、懸念として記事にもなっているが、Cの関数ポインタのように特に初心者にはわかりずらい、つまりコードを追いにく記述になってしまう場合が多いと思われる。

参考:
ついにJavaにもクロージャ? - James Gosling氏らJDK7へ導入提案

親子クラスで同じフィールド定義があると、、、

トランザクション指定を変えてのテスト中、「CommitInterval」を2以上にしても動作に変化がなく、Debuggerで調べてみて発見。
 子クラス定義で親クラスと同じフィールドを宣言していた。こうした場合、実際のInstanceには同名の2つのフィールドが存在することになり、それぞれ別のデータを保有する。実際には呼び出されるコードが親のものか子のものかによってアクセスする対象が変わることになる。
 Javaでは、こうしたフィールドやアトリビュートの重複定義をハイディングといい、アクセスタイプ(private,public など)や型を含めて制限されていない。つまり、ついうっかり子クラスで親と同じフィールドとアクセッサを定義してしまうと、実行時には親クラスのフィールドは初期値のままということになる。もちろんコンパイルエラーも実行時エラーも出ない。
まさに、調査していたコードがそうであった。しかも子クラスで独自に使用する必然性が感じられないため、たんならミスか?と思われる

参考:
Hishidama's Java Memo
Java言語仕様 第3版
Javaの日々

2008年10月27日月曜日

WinXPなどでExploreのドライブ説明文を変更

StartupScriptなどでマウントさせた場合に、勝手にドライブの説明が作成されてしまう。これを変更したかったのだが、やっと方法が分かった。


VBSでnet useでマウントしたドライブレターの変更方法

Exploreのプロセスを作成しておいて、
exp = WScript.CreateObject("Shell.Application");
そのプロパティを変更する。
exp.NameSpace("Y:\").Items().Item().Name = "新しい説明";

ActionScriptからローカルマシンを調べる

HostNameがとりたかったのだが、かなり難しそう。
JavaよりもSandboxが固くてローカルへアクセスは制限を緩めるようなコード署名もないようだ。見つかった方法は、ActionScriptのFSCommand() => JavaScript => WSH の経路でActiveXObjectを駆使してHostの情報を集めるというもの。できそうだが毎回セキュリティのダイアログはいただけない。なんとかできないか調査は続く。

2008年10月24日金曜日

S2JTAがうまく働かない?

S2Batchでのトランザクション設定のテストに入ったが、Rollbackがうまくいかない。Debugログを出してみると、きちんと「トランザクションをロールバックしました」と出力されるし、開始とロールバックの間でINSERTを実施しているように見えるのだが、INSERTが確定してしまっている。Diconでの定義にトリッキーなことをしている影響だろうか?なぞだ、、、

2008年10月23日木曜日

液晶バックライト

 代替に使用できそうなインバータを手に入れて、再度調べてみると、(CCFLも古くて暗いようなのだが)インバータ自体も問題がありそうだと気づいた。手持ちの別のインバータ(1灯式)をつないで見ると、既存のインバータよりも明るく点灯したためだ。
 買ってきたインバータは、低価格なものが2種類あって非常に悩んで購入したのだが、ネットで調べてみると現在と同じコネクターのものが同じような価格で出ていた。交換してもらえるか頼んでみようと思う。それにしても、狭いところに入れることが多い部品だからか、電源供給側のコネクターはいろんな種類があって各社まちまち。CCFL側は数種類だが違いがある。4灯式の場合は2つを直列にするものが多いが、高級品は並列接続である。
 現在分かっている電源側のピンの概要を記しておく。
  VCC 12V程度が多いようだ:アナログ回路なので電圧の許容は15%くらいありそう
GND: 大電流が必要な場合はVCCとペアで数本をパラにしている
ENABLE: 点灯と消灯の制御用:これは、正論理負論理、3.3V/5V などまちまち
BLT:明るさ調節:ENABLE同様に各種方式がありそうで、単なる潮流電圧だけでなく、パルス変調もある
(PWM:方形波のDuty比率で明度を調節する方式らしい)

2008年10月21日火曜日

H2databaseでErrCode=50200

ロックをかけたトランザクションとは別のトランザクションが同じリソースのロックを取得に行った時に絶対に受け取ることができない組み合わせの場合に発生するようだ。(DeadLockのときもでるらしい)

S2で「RequiresNewTx」を指定したメソッドから特定のデータをInsertし、別の「RequiresNewTx」となるメソッドを呼び出して、その中で同じレコードのUpdateをしていることが原因だったようだ。再現テストしても発生しないため、どうもデバッガでデータを適当に書き換えた結果として発生していたようだ。


参考:http://www.h2database.com/javadoc/org/h2/constant/ErrorCode.html#c50200

LOCK_TIMEOUT_1 = 50200
The error with code 50200 is thrown when another connection locked an object longer than the lock timeout set for this connection, or when a deadlock occurred. Example:

参考2:http://lumber-mill.co.jp/gallery/view/tips/java/h2
ここは、SQLでのExport方法も載せてあった。

$ java -cp h2.jar org.h2.tools.Script -url jdbc:h2:foo -user sa

$ java -cp h2.jar org.h2.tools.RunScript -url jdbc:h2:foo -user sa

トレーニングの本質

トレーニングとは、「一定の基礎的な学習を反復練習しながら身に着けていくこと」(http://ja.wikipedia.org/wiki/トレーニング) であり、教育の1方法である。

教育は様々に定義されてきたが、その定義の仕方は大きく次の4種類に分けることができる。
 語源・語義からの定義 (例 「教育とは、能力を引き出すことを意味する」)
 目標・目的からの定義 (例 「教育とは、よりよく生きるためのものである」)
 方法・手段からの定義 (例 「教育とは、強制の一種である」)
 機能・効果からの定義 (例 「教育とは、社会の再生産である」)

 ここでは、「教育とは人の持つ諸能力が引き出されるよう導くことである」とする定義を採用して論議を進める。

 ほとんどの人には現時点において容易にまたは全く行うことが出来ない事柄がある。しかし、それを偶然ではない何らかの方法によって、行いうる事柄に変えることができたとする。この方法の適用や伝達が他者によってなされた場合に狭義の教育を受けたとみなすことが出来る。つまり、その他者によって能力が引き出されるように導きを受けたといえる。一方、自分自身での試行錯誤や文献などの資料から能力を高めた場合は、自己学習をした言える。
 ここで、「導き」に含まれるさまざまな意味の中から、現在の地点からある別の地点への物理的な移動を助けることに限定して考えてみる。すると、導くとは方向や距離、着地する足の高低や地面の柔らなさなどを示して、導きを受ける側の者が自らの力で当該地点にたどり着けるように援助をすることと捕らえることができる。もちろん、すでに持っている能力に応じて援助の範囲は変化することとなる。
 たとえば、目が全く見えない者に対しての導きは詳細なものになるべきであり、自分で再度同じ道を進むことが出来るようにするためには、視覚以外の方法で印となるものを用意する必要がある。逆に、当該箇所をよく見知っている者に対する導きは、「XXの交番から右へ15メートル」などのようにポイントとなるものを示すだけで十分となる。
 また、導きを与える側の物は導く事柄に対して充分な能力を持っている必要がある。そうでないと、盲人を手引きする盲人の喩えのようの状態に陥ってしまうであろう。

■まとめ
 トレーニングとは教育の一種であり、目的とする能力を獲得するために、
                        基礎となる事柄を反復練習しながら身につけていくこと

 トレーニングを施す人は、当該能力を充分に備えている必要がある

液晶の修理

前にもらっていたバックライトがすぐ消える液晶の修理を再開。
インバータを別のものにするときれいに点灯するし、時々うまく表示される場合もあるため、蛍光管(CCFL)は正常と判断した。インバータも正常かもしれないがよくわからず。電圧を測るとどうも直流ではなくPWM方式でDuty比率で輝度を変化させている模様。とりあえず、Enableらしき端子の電圧が、正常時は1.8V 程度で、異常時は0.5Vとか3.2Vであることがわかった。

2008年10月17日金曜日

GoogleChromeが中途半端インストール

インストールして起動しようとしたが、インストーラが途中で吹っ飛んだ感じ。ファイルも存在し、ショートカットやメニューなどもできている。話題になっている、GoogleUpdate.exeも動作しているのに、初期軌道のダイアログが一瞬で消えてしまう。
ネットで調べると、起動時のオプションとして以下の2つがいいらしいので、追加。
-no-sandbox -start-single
結果としてはこれでは解決せず。ちなみに使っているのはMcAfeeのウイルス防御。
ショートカットのプロパティから互換性タブを開いてWin2000モードでの起動を試みる
がまったく動作せず。試しに、
 □詳細なテキストサービスを無効にする
をチェックしてみると、普通に起動した。何なんだろう??

Runtime.getRuntime().exec()でエラーが、、、

Tomcatでテストしているときは発生しなかったRumtime#exec()のエラー
  IOException ... CreateProcess ... error=2
というもので、Googleして、太郎日記 から分かったのは対象のファイルがパスに入っていないと発生するらしい。カレントを移動してから実行させているのだがそれだではだめらしい。

 ちなみに、対象はCMDファイルですので、以下のように起動させることにして一件落着。

cmd.exe /Q /C xxx.cmd p1 p2

通常のWin32環境で cmd.exe がパスに入っていないことはあり得ないので、これでOKのはず。

2008年10月16日木曜日

S2Daoでの複数パラメータUpdate

規約上できないのね、、、

・DaoのInterfaceは次のようなもの、
int update(SomeEntity entity, Integer version);

・SQLはファイルで、以下のような感じ。
Update xxTable set version = /*version*/ where version = /*entity.version*/123

んで、実行すると以下のようにHashMapの操作中にNPE。

java.lang.NullPointerException
at java.util.concurrent.ConcurrentHashMap.hash(ConcurrentHashMap.java:157)
at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:730)
at org.seasar.framework.beans.factory.BeanDescFactory.getBeanDesc(BeanDescFactory.java:55)
at org.seasar.dao.node.BindVariableNode.accept(BindVariableNode.java:54)
at org.seasar.dao.node.ContainerNode.accept(ContainerNode.java:34)
at org.seasar.dao.impl.AbstractDynamicCommand.apply(AbstractDynamicCommand.java:66)
at org.seasar.dao.impl.UpdateDynamicCommand.execute(UpdateDynamicCommand.java:39)
at org.seasar.dao.interceptors.S2DaoInterceptor.invoke(S2DaoInterceptor.java:53)
at org.seasar.dao.pager.PagerS2DaoInterceptorWrapper.invoke(PagerS2DaoInterceptorWrapper.java:71)
at org.seasar.springframework.batch.dao.BatchStepExecutionDao$$EnhancedByS2AOP$$14eaec9$$MethodInvocation$$update5.proceed(MethodInvocationClassGenerator.java)

 調べてみるとS2Daoではメソッドのパラメータ名が分からないので、2つあるパラメータから適切なものを取得できずにエラーとなっている模様。
 では、@Argsを付けるとうまくいくのかは明日に回そう。

2008年10月15日水曜日

睡眠における対称性の破れ

睡眠の研究によると、人は眠っている間に「ノンレム睡眠」と「レム睡眠」を繰り返している。ちょうど、「体」と「頭」を時間差で休ませているようだ。この2種類の睡眠は約90分で1周期であるという。だからこの90分の倍数で睡眠をとるといいとのことである。
 しかし、自分の経験からすると、1周期の90分は同質ではない場合がありそうだ。90分で眠りが浅くなり、覚醒しやすくなる場合と、90分では全く覚醒せず、180分たってやっと覚醒しやすくなる場合がある。つまり、こんな感じ。
 1.周期1 ・・・ 90分
 2.覚醒しやすいインターバル ・・・ ??分
 3.周期2 ・・・ 90分
 4.覚醒しにくいインターバル ・・・ ??分
 5.周期3 ・・・ 90分
 6.覚醒しやすいインターバル ・・・ ??分

2008年10月14日火曜日

Tomcat5と6のはざまで

Tomcat5で動作しているWebApp(S2, teeda)をTomcat6にて起動しようとしていたら、、、
commons-el がないから起動できないとのエラーログ。POMを見てみると、見事にExcludeしてあった。

<dependency>
<groupId>org.seasar.teeda</groupId>
<artifactId>teeda-tiger</artifactId>
<version>1.0.12</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>org.seasar.container</groupId>
<artifactId>s2-extension</artifactId>
</exclusion>
<exclusion>
<groupId>org.seasar.container</groupId>
<artifactId>s2-framework</artifactId>
</exclusion>
<exclusion>
<groupId>commons-el</groupId>
<artifactId>commons-el</artifactId>
</exclusion>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>

調べてみると、Tomca6では「Unified EL」を使用するように仕様が変わった(JSP/Servletの仕様に連動していの変更)ため、commons-elは不要になったようで、クラスパスには存在しなくなったために上記のエラーとなっていた。

[[教訓]]他で動作していて自分のところでエラーとなる場合は環境を疑うこと

大阪王将のバイキング

オーダーバイキングなので、席で注文して作りたてを食べられるのがいい。ちょっと待つこともあるが、他のバイキングに比べると満足度が高いと思う。2回目の夕食も「あさパス」を利用して一人500円安くなった。
 よく間違ってしまうが、餃子の王将とはまったく違う店で、ある意味対極(ちょっと高い、時間かかる、うまい)

ServletのinitからContextPathを取得することは、

無理のようです。 いろいろ調べたりやったりしてみましたが、、、
実際には、LocalHostやLocalPortと共にContextPathも知りたがったのだが、Initで与えられたパラメータは、ServletConfigだけなので、そこから取得できるServletContextまでは分かっても、そのcontextのパスは調べようがないようだ。これがdoGetなどのServletRequestを与えられるメソッドなら、問題なくすべて求められるのだが、、、、残念。
ServietのinitからTimerTaskで自分のマシンからブラウザを開いて特定のページを表示させたかったのだが、やむなく断念し、別のページから当該パスなどを登録するように変更した。

2008年10月11日土曜日

RemoteWeb

さて、リモートウェブのほうだが、昨夜はダラダラと朝方まで作業してしまった。
はまっていたのは、MylinとTracの連携部分。ついでとばかりにTracOnSolaris
のPluginとして「AccountManager」を追加したのだが、Tracが起動しなくなるは、
認証が無効になるわで散々なことに。結局、以下のページの助けを借りて何とか復旧
して少し作業、、、って朝になってる。

蝸牛の宿(別館)
mahataの日記

Mylinの解説は、@ITさん。
Mylyn&Tracでリズムに乗ってタスクを大掃除♪

2008年10月10日金曜日

S2TestCaseでの初期化処理など

 通常のTestCaseであれば、setUp() tearDown() などのメソッドをOverRideすることで初期化および終了処理をかけるのだが、S2の場合はAutoBindingによりフィールドに値がセットされるタイミングが問題となる。setUp() の中でフィールドにDIされていることを期待した処理を書くと、NPEで落ちることになる。
 そこで、S2TestCaseの動作を調べてみると、以下のような順序でS2TestCaseは処理を進めていく。(org.seasar.framework.unit.S2FrameworkTestCase#runBare() より抜粋)

setUpContainer();
setUp();
setUpForEachTestMethod();
container.init();
setUpAfterContainerInit();
bindFields();
setUpAfterBindFields();
doRunTest();
tearDownBeforeUnbindFields();
unbindFields();
tearDownBeforeContainerDestroy();
container.destroy();
tearDownForEachTestMethod();
tearDown();
tearDownContainer();

つまり、フィールドにAutoBindingでDIされた後で初期処理を入れたい場合は、setUpAfterBindFields() をOverRideするといいということだ。

S2Dao ではまる

S2Daoで、Selectのパラメータに中途半端にMapが使えるため、はまってしまった。
問題となったDAOの定義は以下のようなもの(Interface, Foo はEntity)

Foo selectById(Object id);

使っている側はこれ、(key はHashMapで、"id":"1" のEntryあり)

Foo = fooDao.selectById((Map)key);

んで、出たエラーの概要がこれ、


org.seasar.framework.beans.IllegalPropertyRuntimeException:
[ESSR0059]クラス(org.seasar.springframework.batch.item.sample.Foo)のプロパティ(id)の設定に失敗しました。理由はjava.lang.IllegalArgumentException: object is not an instance of declaring class


うーーーむ、どうもObjectで指定するとEntityと同じTypeのオブジェクトが来たと思って処理するようで、Mapは考慮されていない。念のためにアノテーションを追加して以下のようにしてみると、

@Query("id = ?")
Foo selectById(Object q);

無理やりIDのカラムにあてはめようとしてエラーになっている模様。(@Arguments("id")も試したが結果は同じ)


org.seasar.framework.exception.SQLRuntimeException:
.....
Caused by: org.seasar.framework.exception.SSQLException:
[ESSR0072]SQLで例外(SQL=[SELECT T_FOOS.name, T_FOOS.value, T_FOOS.id FROM T_FOOS WHERE id = ?], Message=[17004], ErrorCode=null, SQLState={3})が発生しました
.....
Caused by: java.sql.SQLException: 列の型が無効です。


うーーーむ、どうやらMapからIDを拾ってはくれないようだ。S2Daoの仕様によると、argumentの型はPrimitiveかwrapperが基本で、DTOも使えるとのことで、Mapの記述はなし。S2JdbcがMapでQueryパラメータを指定できるので、同じようにできないかと思ったがやっぱり断絶があった模様。(もしかすると、最新のS2Daoならできるかも、、、、現在はS2Dao-1.0.47)

 続いて、最初からMapで指定したらどうなるか?

Foo selectById(Map q);

なんと!!! ちゃんととれてる。やればできるじゃないかS2DAOと思ったのも束の間、Mapとして与えるプロパティがどう変わっても取得できるものが同じでることが判明。つまり、

"id":"1" ==> Foo(id=1,...)
"id":"2" ==> Foo(id=1,...)

うーーん、これじゃ使えない、、、、試しに、@Arguments("id")としてみると。やっぱり「列の型が無効」とのこと。


Caused by: java.sql.SQLException: 列の型が無効です。


やっぱり、Mapはだめだ。

S2Jdbc と S2DAO の混在

混在環境での問題点など。
1)Entityのアノテーションが供用できない
S2Jdbc: @Entity @Table(name = "Table")
S2Dao: @Bean(table = "Table")

S2Jdbcでは、Entityを使わない方式もあるので、SQL文でTable名を与えてしまえばEntityは不要なのだが、、、ついつい同じEntityだしと思って使い始めると????な状況になることがあった。

2008年10月9日木曜日

S2Jdbcのテストではまる

S2JdbcをS2TestCaseを継承したクラスで、JUnit4にてテストしていたら、「oracleDialect」 のコンポーネントが見つからず、jdbcManager が生成できないエラーとなった。

あちこち調べたが有意な情報が見つからず、以下のを参考に oracleDialect を定義した。

<!-- need for S2Jdbc http://d.hatena.ne.jp/GARAPON/20071119 -->
<component class="org.seasar.framework.convention.impl.PersistenceConventionImpl"/>
<component name="oracleDialect"
class="org.seasar.extension.jdbc.dialect.OracleDialect" >
</component>


一応動いたが、なんか釈然としない。ほぼ同じ構成でhsqlDialectを使用するテストは何の問題もないのに、、、

2008年10月8日水曜日

タグをそのまま表示

POMのソースを貼り付けてあとから見たら、タグが吹っ飛んでいた。
少々調べると、
 <PRE>はスペースや改行はそのままだが、タグはだめ。
 <PLAINTEXT>は、すべて出してくれるが、
  Bolggerが追加した<BR />まで表示されてしまうことと、
  終了タグがないので、文末にしか使用できないことで却下

結局変換した・・・残念!
参考:お世話になったタグ変換ツール
 蓄々HTML実体参照変換
 タグ無効化変換

Maven2-surefire:test でエラー

JUnitが順調に「オールグリーン」となり、MavenにMakeさせてみたらところ、
見事に BUILD FAILURE となってしまった。調べてみると
Testで使用するEntity(単なるJavaBean的クラス)をTestしようとして起こって
いるようだ。Testメソッドが1つもないのだからそりゃ駄目だわな、、、
ということで、surefire プラグインの仕様を確認して以下の設定をpomに
追加、 (Testで始まるクラスを除外する)
-----------------------------------------------------------

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.2</version>
<configuration>
<excludes>
<exclude>**/Test*.java</exclude>
</excludes>
</configuration>
</plugin>

-----------------------------------------------------------
ところが、これでMavenするとTestが1件もなしになってしまう!
よく見ると、Testクラスの名称が XxxTests.java となっているでは
ないか~~~~~! ということで、以下のを追加して解決
-----------------------------------------------------------

<includes>
<include>**/*Tests.java</include>
</includes>

-----------------------------------------------------------
今日はここまで。
S2Batch JUnit 続き
 昨日の無限ループだが、原因はAOPのPointCutの指定にあった。
RepeatOperationsInterceptorをAOPするテストなのだが、その仕様を理解しないまま対象メソッドを「.*」としていた。
今回のInterceptorの仕様としては、
* メソッドのリターンがない場合(Voidメソッド)なら無限に繰り返し
* リターンがある場合は、NULLまたはFALSEになるまで繰り返すと
というもので、処理の途中でVoidのSetterを呼んでいる部分が無限ループとなっていた。
対象を絞り込んだところ正常終了となった。

[[教訓]] 仕様が不明な場合は異常となる可能性が低くなる方向から試行するべし。

2008年10月7日火曜日

S2Batch JUnit

SpringBatchをS2に移植している。テストも移植しているが、現在は以下のメソッドで
Testが終了しない。
RepeatOperationsInterceptorTests#testCompleteOnFirstInvocation()

TaskManagerを見ると、2つのjavaw.exe がCPUをほぼ100%占有していた。
調査は明日以降に持ち越し、、、

動的AOPをJUNITしたらエラー

JunitTestの最中にjava.lang.IllegalAccessErro
が発生。メッセージはAop(動的拡張)されたクラスと元のクラスの関係のようだ。
class Xxxx$$Enhance...$$ cannot access its superclass Xxxx
--- しばらく調査:
//http://tech.groups.yahoo.com/group/junit/message/6508
によれば、このエラーは、アクセスできないフィールドやメソッドを修正したり呼び出したりした場合に発生し、その原因としては実行時にクラス定義が互換性をなくすように変更されていた場合となっている、とのことだ。
public な Consutructorがないのが原因かなと思って入れてみたりしたがだめ。ほぼ同じ構成のテストが動作しているので比較してみると、Privateな要素に問題があるようだ。
結局、問題は以下の点だった。
* AOPの対象となるクラスが、Testクラスの内部Privateクラスであった
* AOP系のロジックはTestクラスにて書いていた
よって、コンパイルまでは問題ないのだが、実行してみるとAOPで作成されたクラスは、Privateな内部クラスの子供であるため、親クラスとしては参照できなくなり上記のエラーが発生してしまった。

[[ 教訓 ]]
cannot access => Scopeが何か(public, protected, package, private)に注目すること!

iPhone関連:
iPhone開発で使用するCocoaはObjective-Cであり、Java/Perl/Python/Rubyなどとブリッジ可能

ついでにメモ:
S2TestCase でトランザクションテスト:
setup() で、include("j2ee.dicon")をしておいて、テストメソッド名の最後にTxをつける
参考(http://cvs.sourceforge.jp/cgi-bin/viewcvs.cgi/seasar/s2-struts/doc/S2Unit.html?rev=1.1)