Wednesday, December 14, 2011
タリーズ行ったら7000円くれた
普段、タリーズのプリペイドカードでコーヒーを買っているのですが、昨日、レジで僕のカードをバーコードリーダーでピってやったらレジのお姉さんの顔が変わって店長!とか言いだしたのです。
なに?オレおたずね者?イスにコーヒーこぼしたの見られてた?うわごめんなさいごめんなさい。
ということではなくて、この前来たときお釣り7000円をお姉さんが渡し忘れたらしいとのこと。
タリーズコーヒーで7000円て!?
思い出しました。確かにプリペイドカードが残高不足だったので3000円チャージしようとして1万円札を渡した気がします。 (ちなみに3000円チャージするとコーヒー一杯無料件がもらえる)
あとで気づいた店側が、僕のプリペイドカード情報にフラグつけて、レジ通した瞬間アラートが出るようにしてあったようです。店長さんが、いやあ、また来ていただけてホントよかったです、と言いつつ7000円くれました。1万円札出してお釣りもらうの忘れる自分も自分だなとあきれつつ、タリーズえらいなあ、と思いました。
Saturday, September 24, 2011
springの設定ファイルをWEB-INF直下に置くとテストが難しくなる
src/main/webapp/WEB-INF/applicationContext.xml
のような位置にspringのbean定義ファイルをつくる例が多いようです。実際、巷の書籍やIT系サイトの記事などでもそのようなサンプルがよく公開されています。
しかし、この配置方法には実は大きな問題があります。JUnitなどのテストケースを実行するとき、その設定ファイルをロードできません。なぜならWEB-INFの直下はクラスパスではないからです。
- @ContextConfiguration and loading contexts from /WEB-INF [Archive] - Spring Community Forums (2009年ごろのSpringの公式フォーラムでのスレッド)
eclipse上でsrc/main/resources/applicationContext.xml のようなビルドパスの通っている位置に移動させたうえで、web.xmlのほうには
のようにclasspath:記法で書いておけば、クラスパス配下の設定ファイルをロードしてくれる(実体はWEB-INF/classes/mainContextConfig.xmlのようになる)。。。 はずなのですが、そうはとんやかです。org.springframework.web.context.ContextLoaderListener contextConfigLocation classpath:mainContextConfig.xml
詳細は不明ですが、ContextLoaderListenerは強制的にWEB-INF/直下の設定ファイルを探しに行ってしまいます。 結果、FileNotFoundExceptionを吐いてWebアプリが起動しません。 これを防ぐため、たとえば
のように書いておき、applicationContext.xmlには<beans><!-- dummy! --></beans>のような無設定のダミーを仕込んで、本来の設定をすべてclasspath:mainContextConfig.xmlのほうに書いておくことで対応できます。contextConfigLocation WEB-INF/applicationContext.xml, classpath:mainContextConfig.xml
Sunday, August 28, 2011
Chrome+HTML5カンファレンスでライトニングトークしてきました。
先週、Chrome+HTML5 カンファレンス at Google Japan(六本木ヒルズ)で、ライトニングトークに参加してきました。お礼が遅れてしまいましたが、当日の運営の皆様に感謝します。
Thursday, August 4, 2011
mixer2がhtml5に対応しました
ここでの報告が遅れてしまいましたが、version 1.1.0 をリリースしました。 html5の全ての要素、属性に対応しています。下位互換性は保たれているので、従来のXHTML1.0 Transitionalでも大丈夫です。
詳しい使い方のサンプルなどはここで徐々に書いてゆこうかなと。ちょっと忙しいので時間とれてませんが。
Monday, July 11, 2011
xperia arc のOSアップデートで通話に不具合が出るようです
自分も使ってるxperia arcですが、7月初旬にAndroidOSの自動アップデートが配信された後、通話に不具合がでているようです。電話が繋がっても2分前後で切れちゃうとか、音声が全く聞こえないとか。
自分の場合は、電源きる&電池とSIMカードを抜く&再びSIMカードと電池入れる&電源入れる、で直りました。そんなこったろうと思った...
いまtwitterで xperia arc 不具合 みたいなキーワードで検索すると、ドコモショップ行かなきゃ、みたいな話をしている人が結構いますが、そもそもtwitterにそう書く前にTwitter上で検索してみてはいかがでしょう。私の投稿がヒットしますから。w
追加です
数十時間後、ほぼ同じ症状が再発しました。だめだこりゃ。ソニーエリクソンはもう少しテストしてから更新かけてほしいものです。
追加です。この件を解消するべく新たなアップデートが7月27日に出ているようです。 ドコモ、「Xperia arc」「Xperia acro」のソフトウェアアップデートを開始 - ITmedia +D モバイル
Thursday, May 5, 2011
mixer2 1.0.8リリース。TableBuilderでテーブルを組むのが楽になりました。
詳しくは公式サイトのほうをご覧ください。mixer2 - TableBuilder です。あとJavaDocも。→TableBuilder (mixer2 1.0.8 API)
table,tr,tdだけでなく、tbodyやthead,tfootタグにも対応していますので、ブラウザ側でも、たとえばjqueryのdatatables等のライブラリと組み合わせやすいでしょう。たとえば「ASCII.jp:JavaScriptだけで表<table>を並び替え!」とか。
Saturday, April 23, 2011
Tableタグを作るBuilderクラスをつくってます
mixer2で、table,tr,tdタグを組もうとすると、こうなります。
import static org.mixer2.xhtml.TagCreator.*; ... Table table = new Table(); // 一個目のtd Td td1 = td(); // td = new Td(); と同じ意味になります。 Tr tr = tr(); td1.getContent.add("a"); tr.getThOrTd().add(td1); // 2個目のtd td2 = td(); td2.getContent.add("b"); tr.getThOrTd().add(td2); // tableに収める table.getTr().add(tr); ...
面倒ですよね(笑)。他のタグならともかく、tableタグはデータ表示などの目的での利用頻度がものすごく高いタグですので、これじゃあちょっと、あんまりです。
そこで、こんな風に、わかりやすくtableを組めるTableBuilderクラスをつくっているところです。
... TableBuilder tb = new TableBuilder(); tb.tr(0).td(0).add("a"); // 1行目、1列目のtdにaがはいる tb.tr(0).td(1).add("b"); // 1行目、2列目のtdにbがはいる Table table = tb.build(); // これでtableタグ全体ができる ...
もちろんこれだけでなく、行、列のindexを指定しなくてもadd("a")とかするだけで最後尾に自動的にtrやtdを作るようなメソッドもつくろうかなとも思っています。いろいろと試しているところです。
mixer2の次期リリースに搭載できると思います。乞うご期待。
Wednesday, April 20, 2011
mixer2 version1.0.6リリース。FormUtilクラスを追加しました。
formタグ内部のinputやselect等に、JavaBeanクラスの内容を自動的に挿入するユーティリティが追加されました。詳しくは mixer2 - Form and JavaBean をご覧ください。
Strutsのアクションフォームクラスや、Spring MVCのcommandクラスでも使われている、一般的なJavaBeanをそのまま使うことができます。Webアプリにおいて、formタグを使ったCRUD的な画面を生成する際に、結構便利に使えると思われます。
Saturday, March 19, 2011
mixer2 version1.0.4で部分マーシャル機能が追加されました
従来のmixer2は、Webページの全体、つまり<html>から</html>までを一気に文字列化する必要がありました。
version1.0.4以降、任意のタグ、例えば<div>から</div>までなど、htmlの一部分だけを出力(マーシャル)することができるようになりました。
これによって、たとえばVelocityやJSPなど、他のテンプレートエンジンと組み合わせて使うために、Webページの一部だけをmixer2で出力したいという要求に答えられるようになりました。
Sunday, March 6, 2011
オープンソースカンファレンス2011 Tokyo/Springへの謝辞
オープンソースカンファレンス2011 Tokyo/Spring - オープンソースの文化祭!に参加してきました。(土曜日だけですが)
セミナーをいくつか見て回りましたが、その中でも[パネルディスカッション] オープンソース/クラウド時代のキャリアデザインとははなかなか興味深かったです。超満員。事前登録しといてよかったー。
そして(自分的には)本題のLT(ライトニングトーク)でmixer2についてしゃべらせていただきました。5分しかないというのにその半分は笑いを取りにいくための思い出話(?)をしてしまいましたww。 しかしだからといってmixer2をかいつまんででも紹介するのは5分ではおさまるわけもないので、「詳しくはWebで!」ってやつです。
LTでしゃべれるのは10人前後(先着順)ですが希望者はもっといたようです。 本当はああいうのは若い学生さんとかに譲るべきなんでしょうが、ほんと自分なんかがしゃべらせてもらっちゃってすいません。
そして、スタッフなど中の人に心から感謝を申し上げます。お疲れ様でした。 すごい人数でしたので、来年は大学施設とかではなく、東京ビッグサイト?ww
mixer2での繰り返しデータの埋め込み
先月のことですが、こんなツイートを見かけました。
mixer2おもしろそう。 http://goo.gl/W1pRO スクリプトや式といった処理と、テンプレートをキレイに分けられそう。繰り返しデータの埋め込みもサポートされているなら、Wicketのテンプレートだけ取り出したような、自分的には理想のテンプレートエンジンになりそう。
(とある方のつぶやきより)
mixer2に好感を持っていただけているようでうれしいです。
嬉しいよというついでに、「繰り返しデータの埋め込みもサポートされているなら」という点について、mixer2開発者としての説明をしてみたいと思います。
ツイート主さんの懸念、というよりは素朴な疑問と言うべきそれは、とても当然です。 Hello Worldには本当にHelloWorldを表示することしか書いてませんから。 どんなプログラマーでも、Javaでの開発でよく使われるJSPやVelocityのような従来のテンプレートエンジンとの比較を無意識に考えてしまうので、「じゃあ、ループしながら値を埋め込むようなときはどうすんだろ?」とふと思うのは当然です。
結論を言うと、
Q.たとえばDB検索の結果とかで複数の値があるとき、それを繰り返し処理しながら表示するのって、mixer2ではどうやんの?
A.普通にJavaでforやwhileなどを使ってください。
なのです。
具体的なサンプルソースは本家サイトのTIPSのページの下のほうに書いておきました。
さて、上のリンク先、見ていただけましたでしょうか?そう、コードが長いですww。 JSPだったら<c:foreach>のようなカスタムタグを含めた3,4行ですみそうなところが、 mixer2だと10行くらいになっちゃってます(コメント行いれると15,6行!)
もちろん、これがベストプラクティスだということではありません。 こうした繰り返し処理を簡略化する汎用ユーティリティのようなものをmixer2のほうで用意するべきなのかもしれません。
ともあれ、ひとまずはmixer2を使う側のコーディングでどうにでもなりますよ、ということはなんとなくわかっていただけると思います。なにしろ、VelocityのVTL言語でもなくJSPのカスタムタグでもなく、ただのJavaコーディングなのですから。
Wednesday, February 23, 2011
タグの中身の操作方法
XHTML/HTMLのタグの多くは内部に任意のタグまたは文字列を持つことができます(入れ子タグ)。 mixer2でのタグの中のタグ/文字列へのアクセスと操作方法の基本について解説します。
divやspanのように、中になんでも入れられるようなタグの場合は必ずプロパティとしてcontent(java.util.List型)を持っており、それに対するgetContent(), setContent(), unsetContent()で操作することができます。
例えば次のような形でテンプレートをloadしたと仮定します。
<html> <head> <title>タイトルです</title> </head> <body> <div id="foo">aaa<b>bbb</b>ccc</div> </body> </html>
Html html = mixer2Engine.loadHtmlTemplate(new File("テンプレファイル")); Div div = html.getById("foo",Div.class); java.util.List list1 = div.getContent();
このとき、list1の内部は次のような値が格納されています。
添え字 | 型 | 内容 |
0 | java.lang.String | aaa |
1 | org.mixer2.jaxb.xhtml.B | Bタグオブジェクト |
2 | java.lang.String | ccc |
list1はdivタグの中身の実体をList型で抱えていますので、あとは普通にList型を扱うように add(追加したいもの)、remove(消したいものの添え字)、set(添え字、置換物)等のメソッドで扱えます。
Html html = mixer2Engine.loadHtmlTemplate(new File("テンプレファイル")); Div div = html.getById("foo",Div.class); java.util.List list1 = div.getContent(); list1.add("ddd"); list1.set(1, new Br()); list1.remove(2); System.out.println(m2e.saveToString(html));
上記によって、divタグの中を次のように書き換えたものを得ることができます。
<html> <head> <title>タイトルです</title> </head> <body> <div id="foo">aaa<br />ddd</div> </body> </html>
Friday, February 18, 2011
モックhtmlの内容を操作する(アンカーリンク編)
通常のJava/JSPによるWeb開発では、htmlモックをJSPに書きなおす作業をします。この作業によって、Webデザイナーでは手が出せないような呪文が埋め込まれていきます。<form> が<html:form>になったり、<c:if test="${user.isLogin == true }" />こんにちは${user.name}さん!</c:if> と書き加えたりする、あの作業です。
JSPに書きなおす作業が発生し、さらにJSPに書き換えたが最後デザイナーはほとんど手が出せなくなる(うっかり修正してJSPの呪文を壊すとまずい)のですから、この工程に入った瞬間から開発現場の生産性はガタ落ちです。jspなのでアプリとして実行できる状態まで作業しないと、見栄えの確認も修正もできません。モックhtml作成のときのように「ちょっとブラウザで表示してみて見栄えを確認してまた修正する」といったことはできないのです。
そんな愚痴はさておき、ではmixer2ではそこをどう解決するのか?といったお話を少しずつ書いてゆきます。今日はアンカーリンク編です。aタグとformタグ(のaction属性等)についてお話しします。
たとえばテンプレート(htmlモック)に書いたaタグで
<a href="detail.html">
となっている箇所はすべて
<a href="/contextPath/foo/detail?id=99">
のような形に書き換えなければならない、と想定します。
この場合まず、テンプレートを作る段階で当該のaタグにid属性またはclass属性をつけておいてもらうのが早道です。
<a href="detail.html" id="detailLink" > ※このリンクがページ上に唯一ならid属性で
あるいは
<a href="detail.html" class="detailLink" > ※リンクがページ上に複数あるならclass
といった感じです。命名規則は特にありませんのでデザイナーとプログラマーの間で適当に取り決めておいてください。
テンプレート(htmlモック)をMixer2EngineでロードしてHtml型のオブジェクトに変換したら、次のようにします。
File file = ResourceUtil.getResourceAsFile("detail.html"); Html html = mixer2Engine.loadHtmlTemplate(file); // id属性で走査して書き換え html.getById("detailLink", A.class).setHref( request.getContextPath() + "/foo/detail?id=" + 99); // class属性で走査してそれら全部を書き換え for (A a : html.getDescendants("detailLink", A.class)) { a.setHref(request.getContextPath() + "/foo/detail?id=" + 99); }
これで、該当のid属性またはclass属性を持つaタグのhref属性はすべて動的に書きかえられます。
formタグも同様です。htmlモック上では紙芝居のように画面遷移させるために
<form id="fooForm" method="get" action="thanks.html">
のようになっていたとすると、
html.getById("fooForm",Form.class).setAction(request.getContextPath() + "/foo/thanks"); html.getById("fooForm",Form.class).setMethod("post");
によって、
<form id="fooForm" method="post" action="/contextPath/foo/thanks">
に書き換えることができます。
Tuesday, February 15, 2011
coberturaのカバレッジ測定でignoreやexcludeがうまくできない
mixer2もちゃんとJUnitによる自動テストをやってます。テストケースの本数がまだ不足なのは否めませんが^^;)
カバレッジの測定もやっていまして、手元のeclipse上ではeclemmaプラグインで、mavenでのビルドとレポート生成時にはcoberturaを使っています。なんで違うソフトを使っているかと言うと、eclemmaにはmavenレポート用プラグインが無く、coberturaにはeclipse用プラグインが無いからです。どっちかに統一したいのはやまやまなんですが、そういうちぐはぐな状況なので仕方がありません。似たような事情を抱えているプログラマーさんも多いのではないでしょうか。
愚痴の本題なのですが、mavenのcoberturaプラグインには、特定の名称のパッケージ/クラスをカバレッジ測定対象にしない、という機能があるはずなのですが、うまく動かないようです。
バグレポートで言うとたぶん
[#MCOBERTURA-52] Ignores and Excludes do nothing - jira.codehaus.org
と同じ目に遭っているのだと思うのですが。
mixer2のとあるpackage配下は実はすべてJava6のJAXB-APIによる自動生成クラスなので、バグの混入の可能性がほとんどないクラスなので、カバレッジ測定対象から除外したいです。しかしそれがうまくいかなくて。
ちなみにいますべてのクラスがカバレッジゼロ%になっているのはこのバグだけでなく自分の単純ミスですww。 ほんとはもっとカバレッジ率あります。
Saturday, February 12, 2011
テンプレートhtmlをファイルじゃなくDBに保存できる
さらに、mixer2のテンプレートは、ファイルである必要すらありません。HelloWorldの例のようなjava.io.Fileオブジェクトだけでなく、Stringもテンプレートとして読み込めるからです。メソッドはloadHtmlTemplate(java.lang.String)です。
たとえばECサイト構築のASPサービスがあるとします。店舗ごとにまったく異なるデザインを見せるために、テンプレートは店舗ごとに異なるものを管理する必要があります。ブログサービスでも似たようなものですね。
店舗が10個くらいのうちはいいのですが、数百、数千となってくると、テンプレートをファイルで管理することが難しくなってきます。商品データ等と同様に、テンプレートもDB上で管理したくなってきます。
しかしJSPではテンプレートをDBで管理することは事実上困難です。Velocityも、DataSourceResourceLoaderによってテンプレートをDB管理することはできるものの、J2EEサポートを必要とするといった制約があり、使い勝手はあまりよくないようです。
しかしmixer2では単なるStringとして定義されたテンプレートhtmlを扱えます。
SAStrutsでのHelloWorldサンプルを、テンプレートをDBから読み込むとすると次のようになります。
// O/RマッパーとしてS2JDBCを使っていて、 // TEMPLATE_TABLEのTEMPLATEというカラムに // テンプレートが保存されていると仮定します。 public class IndexAction { @Resource protected Mixer2Engine mixer2Engine; @Resource protected JdbcManager jdbcManager; public String htmlString; @Execute(validator = false) public String index() throws IOException, TagTypeUnmatchException { TemplateTable tt = jdbcManager .from(TemplateTable.class) .where(eq(id(),999)) .getSingleResult(); String templateString = tt.template; Html html = mixer2Engine.loadHtmlTemplate(templateString); html.getById("hellomsg", Div.class).unsetContent(); html.getById("hellomsg", Div.class).getContent().add("Hello World!"); htmlString = mixer2Engine.saveToString(html); return "index.jsp"; } }
以上、TIPSでした。
Friday, February 11, 2011
mixer2のサンプルアプリをつくってみました
http://mixer2.org/etc/nullpon-sastruts/src/main/webapp/list.html
画像を押すと詳細ページへ飛び、さらに「買う」を押すと、買ってくれてありがとう的な画面に移る、という、3画面だけのごく単純なアプリになっています。
- http://mixer2.org/etc/nullpon-sastruts/src/main/webapp/list.html
- http://mixer2.org/etc/nullpon-sastruts/src/main/webapp/detail.html
- http://mixer2.org/etc/nullpon-sastruts/src/main/webapp/thanks.html
モックhtmlはWebデザインとしてはほぼ完成の状態であり、リンクやボタンを押せば次に想定される画面へ遷移できます。Webサーバ上にアップする必要も無く手元のPCのブラウザ上に読み込めば見れます。もちろんDBとの連携などありません。つまり「紙しばい」です。しかしそれはそれでOKです。モックhtmlはあくまでWebサイトとしての見た目、ユーザーインターフェースの確認の目的で作られるものだから、紙芝居でいいのです。
Webサイト開発の現場では、このモックhtmlをテンプレート言語(VelocityやJSP等)に書き直してWebアプリのView層にする、という作業の流れをよく見かけます。
しかし、mixer2を使うと「JSPに書き直す」という作業は不要です。モックHTMLのままでテンプレートとして使えるのがmixer2のメリットです。JSPのカスタムタグを書く必要はまったくありません。必要なのはXHTMLとCSSで書かれたモックHTMLファイルだけなのです。
http://mixer2.org/etc/nullpon-sastruts.tar.gzがこのWebアプリのアーカイブです。eclipse上にインポートすればすぐに稼動すると思いますのでお試しください。DBはsqliteを使っているのでDBの初期設定の手間もありません。
下記がこのサンプルアプリで想定している環境です。
- Tomcat6
- JDK1.6.0_22 (1.6.xなら何でも動くと思います)
- eclipse 3.6.1(helios) + WTP2.5 (sysdeo使ってる人のほうが多いかもしれないんですけどWTPです、すいません。でもsysdeoプラグインでも動くと思います)
- Seasar2/SAStruts/S2JDBCフレームワークをベースにしています。SAStrutsのビューはJSPやmayaaが使われることが多いようですが、それらの代わりにmixer2を使っている、と考えればいいでしょう。
わかりやすくするために、ほとんどの実質的な実装をIndexActionクラスに集約してあります。
syntax highlighterのテスト
import java.io.File; import org.mixer2.Mixer2Engine; import org.mixer2.jaxb.xhtml.Div; import org.mixer2.jaxb.xhtml.Html; public class HelloWorld { public static void main(String[] args) throws Exception { Mixer2Engine m2e = new Mixer2Engine(); Html html = m2e.loadHtmlTemplate(new File("HelloWorld.html")); html.getById("hellomsg",Div.class).unsetContent(); html.getById("hellomsg",Div.class).getContent().add("Hello World !"); System.out.println(m2e.saveToString(html)); } }
おお、なるほど。これは便利だな。
参考:クリボウの Blogger Tips: コードをハイライトする「Blogger Syntax Highlighter」ウィジェット