Sunday, April 6, 2014

第5回 #渋谷java でトークしてきた

今日はこんなイベントに参加してきました。

第五.五回 #渋谷java - connpass

javaに関することなら何でもありのゆるふわjava LTイベントです。

参加される方はSIerの方や自社プロダクト開発の方やフリーランスの方など様々です。 LTの内容は初心者向け〜ガチ勢向けまで幅広く実施して頂いておりますので初心者の方もモヒカンの方お気軽にどうぞ!

2月にやるはずだったのが大雪のため4月に延期になったやつです。 私はセッション枠で20分ほどしゃべらせていただきました。資料がこちら。

その場でJenkinsを「ポチっとな」してMixer2のビルドとセントラルリポジトリへのデプロイ作業を生実演でお見せするという試みがけっこうウケたようで、うれしかったです。 ついでなのでプレゼンで語りきれなかったことを少し書きます。

perlならcpan, PHPならPEARやPECL, rubyならrubygems そしてJavaならmavenセントラルリポジトリのように、近代的なプログラミング言語のほとんどが、 パッケージリポジトリ=コンパイル済みで即利用可能な状態のライブラリの集積所=と、それをうまく使いこなすためのコマンド機構を持っています。

mavenはビルドツールではありますが、そのキモはmavenセントラルリポジトリとの自動的な連携にあります。これはGradleでもAnt+Ivyでも同じことが言えます。 java以外の言語でも似たようなものです。 だからこそ、現代のプログラマーはパッケージリポジトリのことをもっと意識しそこに貢献すべきです。今日のトークの動機はそこにあります。 ソーシャルコーディングに必要なのはGitHubだけではないのです。

mavenセントラルリポジトリにライブラリをupする権限を得るには審査が必要だという話をしましたが、 それはあくまで形式的なものです。 たとえばgroupIdが他とバッテイングしてないかとか、pomの書き方ちゃんとわかっていそうかとか、 MITかGPLかApache2かライセンスをちゃんと表示しているかとか、 なにかの商標にひっかかってなさそうかとか。。。 逆に言うと「おまえの作ったjavaライブラリはmavenセントラルに入れてもいいほどすっげえ便利かどうか」ということは考慮されません。 それはsonatype.orgの中の人が決めることではなく、全世界のjavaユーザーが決めることだからです。

門戸は開かれています。さあ、あなたもこれで、javaのOSSライブラリ開発者!

なお、他の方のトークで個人的に面白かったのがこちら。

@テスト
public void 文字列マッチャーのテスト() {
    文字列("テストなんとか", は("テスト".で始まる()));
}

っておいなんだこれw

最後になりましたが、運営の@seri_kさんほか会場設営などやってくださっているビズリーチ社の関係者の方々に感謝します。私も結構ガチで転職を考えております。w

参考リンク: 第五.五回 #渋谷java - Togetterまとめ

Tuesday, January 28, 2014

Mixer2でページのヘッダとフッタを挿入する方法

「Mixer2でビューを作るとき、いろんなページで共通のヘッダやフッタ部分を挿入するのってどうやるのだろう?」 よくあるケースです。JSPで言えば <jsp:include page="header.jsp"> にしておきつつ、 header.jspファイル内には <div id="header">ヘッダーのなか</div> のように書いておくやつ。

しかし、JSP的なやり方だと、ヘッダはヘッダ、フッタはフッタ、のようにバラバラになってしまい、 webデザイナーの立場からするとメンテが面倒なうえに実際の見栄えの確認がしづらくなってしまいます。 Mixer2ではいろいろなやり方がありますが、わかりやすくかつ手っ取り早いのが、パーツ取り用htmlテンプレート作戦です。

まず、通常の画面表示用テンプレートの他に、 parts.html のような名前でパーツ取り専用テンプレートを用意し、そこにヘッダとフッタのブロックを自由に書きます。

 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
    <meta charset="utf-8" />
 </head>
 <body>
 <div id="header">
  実際にヘッダにしたい内容
 </div>
 これはパーツ取り専用htmlなので実際には出力しませんよ
 <div id="footer">
  フッタにしたい内容
 </div>
 </body>
 </html>

次に実際に画面に出すテンプレートファイル(fooTemplate.htmlだとします)には次のように書いておきます。

 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
    <meta charset="utf-8" />
 </head>
 <body>
 <div id="header">
  ここにヘッダがはいる予定です
 </div>
  実際に出力したいコンテンツ...
 <div id="footer">
  ここにフッターがはいる予定
 </div>
 </body>
 </html>

画面出力のviewクラスはこんな感じ。(あくまでも模式的な例です)

Html partsHtml = mixer2Engine.loadHtmlTemplate("parts.html");
Div headerDiv = partsHtml.getById("header",Div.class).copy(Div.class);
Div footerDiv = partsHtml.getById("footer",Div.class).copy(Div.class);
Html fooHtml = mixer2Engine.loadHtmlTemplate("fooTemplate.html");
fooHtml.getBody().replaceById("header", headerDiv);
fooHtml.getBody().replaceById("footer", footerDiv);

実際には、テンプレートのロードを何度もやるのはやや非効率です。 共通クラスを切り出して、そこでparts.htmlのロードを一回だけ行ってheader/footer用Divインスタンスの copy()の結果を返させて、それを使うような感じがよいでしょう。

「fooTemplate.html上に <div id="header">ここにヘッダが入る</div> みたいなことを書く手間すら省きたい」という要求も実現可能です。

Html partsHtml = mixer2Engine.loadHtmlTemplate("parts.html");
Div headerDiv = partsHtml.getById("header",Div.class).copy(Div.class);
Div footerDiv = partsHtml.getById("footer",Div.class).copy(Div.class);
Html fooHtml = mixer2Engine.loadHtmlTemplate("fooTemplate.html");
// bodyタグの先頭にヘッダdivを差し込む
fooHtml.getBody().getContent().add(0, headerDiv);
// bodyタグの最後にフッタ用divを差し込む
fooHtml.getBody().getContent().add(footerDiv);

こんな感じ。

いかがでしょう。Mixer2でのビュー実装の書き方は様々です。 jspのカスタムタグではなく通常のjavaで書くので柔軟性とテストの書きやすさは段違い、というのがポイントです。 要件に合わせてご自由にどうぞ。

Thursday, January 9, 2014

Java5で動くMixer2をリリースしました(あくまで実験的)

Java5がリリースされたのは2004年10月。そして今はもう2014年です。もうすぐJava8も出ます。 そんな時期にMixer2をjava5でも動かせるようにするってそれ誰得?ww というツッコミもけっこうありました。(※Mixer2は本来はJava6以上が動作条件です)

しかし、世の中にはレガシーなシステムなんていくらでもあるようです。詳しくは言えませんが、 Java1.4(5ですらない!)で現役で稼働しているシステムが存在し今もチビチビ改修していると言う話を、つい先日まのあたりにしました。 Javaから離れてしまいますが、全日空の国内線旅客システムが実はつい最近まで Fortran(COBOLですらない!)で動いていたというニュースもありましたね。

さて、話をMixer2に戻しましょう。 Mixer2はJavaのJAXB-APIを使ってXHTMLを入出力しています。JAXBはJava6以降でJDK/JREに標準搭載となったため、 本来、Java5では動きません。

ただ、jaxbはもともと独立したライブラリとしてSunの社内で開発が続き、のちにJava6で初めて実行環境に標準搭載されたという経緯があります。 これはjaxbに限ったことではなく他のapiでも似たような流れをたどることがあります。

ということは、jaxbやその関連の、既に公開されているライブラリを、 Mixer2が依存ライブラリとして使用するようにすればJava5でも動くということになります。 そう、実はそれほど遠い道のりではないのです。実際1日2日でできちゃったし。

そんなこんなでとにかく、mixer2-java5 version 0.1.2 をリリースしました。

使い方は本家Mixer2とまったく変わりありません。ただし、以下の点にご注意ください。

  • あくまで実験的なものですので、サポートやバージョンアップはそれほど期待しないでください。
  • SpringMVC関連機能は削り落としてあります。純粋にテンプレートエンジン機能のみです。

Saturday, December 28, 2013

Mixer2の最近のリリースでのエンハンス(特にSpringMVC関連)

Mixer2-1.2.22をリリースしました。

実はここ数週間で何回かリリースしましたが、まともにアナウンスしていませんでした。最近のリリースではどこをどういじったか、ざっくりまとめておきます。

1. Spring MVCとの組み合わせ方をドキュメントに書きました

Mixer2とSpringMVCと組み合わせたサンプルアプリケーションはもともとあったのですが、 javadocはともかく、文章の形では基本的な説明をまとめて書いてはいなかったので、 Use Mixer2 with Spring MVCというページを公式サイトにつくりました。 なお、もともとほぼ同じことがjavadocにも書いてありましたが、それも少し手直ししました。

※誤解の無いように念のため書いておきますが、Mixer2それ自体は他のライブラリ等への依存性が非常に少ない、独立性の高いxhtmlテンプレートエンジンです。 Webアプリケーションフレームワークと組み合わせて使うのが便利なことは確かですが、 必ずSpringMVCやSAStrutsと組み合わせないと何もできないということは全くありません。

2. Spring MVCでMixer2もJSPも両方使いたくてもうまく動かないのを直しました

公式サイトの説明のように


    
        
        
        
        
        
    
    
        
        
        
    

と書けば、コントローラから返されたview名を使ってMixer2ViewResolverがhtmlテンプレートファイルを見つけられなかった場合には、 そのままInternalResourceViewResolverへ処理が移って、view名に該当するjspが使われる...はずだったのですが、 実際にはMixer2VeiwResolverがhtmlテンプレートを見つけられなかった段階でいきなりFileNotFoundExceptionになってしまっていました。

それではまずいので、ちゃんと次のリゾルバーに処理が移るように直しました。このへんは、SpringMVCのマニュアルにも書かれている通りにしてみた、という感じです。

17.5.2 Chaining ViewResolvers

"The contract of a view resolver specifies that a view resolver can return null to indicate the view could not be found. Not all view resolvers do this ..." (ビューリゾルバーの実装ルールとしては、ビューを見つけられない場合にはnullを返すことができますよ。ただ全部のビューリゾルバーがそうしてるわけじゃなくケースバイケース...)
Spring MVC reference 3.2.xより

ただし、従来の挙動(見つからなければ即座にFileNotFoundException)でよいという人のために、 この機能をオフにする設定方法も用意しておきました。細かいことはMixer2XhtmlViewResolverのjavadocに書いてあります。

3. headタグの中ではremoveById()等が動かないことがあるのを直しました

単純にバグです。

4. 恥ずかしいミススペルを直しました

PathAjusterクラスはクラス名自体の綴りが間違っていることが今頃発覚w。 機能はそのままでPathAdjusterクラスとして作り直しました。 古い方のクラスは@Deprecatedにしておきましたが、こういうので後方互換性を失うのはまずいのでたぶんずっと消さずに残しておくと思います。

5. HTML5でAタグの中のDIVタグ等が消えるのを直しました

Mixer2-jaメーリングリストのほうでもらったバグ報告の対応です。

htmlテンプレートとしてmixer2Engineがロードするとき、テンプレート上のaタグの中にインライン要素(spanとかimgとか)が入ってるのはokだが、 ブロック要素(divとかpとか)が入っているとそれが消えてしまうという現象です。

これはちょっと盲点でした。というのは、html4.xまでの規格では、aタグの中にブロック要素を入れるのはNGなのです。 Mixer2はJAXBを使ってhtml(xhtml)を読み込むので、そういったところも厳格にNG扱いで、該当要素を無かったことにします。 ところが、html5ではaタグの中にブロック要素も入れられるようになりました。 HTML5 の “ブロック・レベル“ リンクというやつです。 Mixer2のhtml5に対する対応の不足、というバグとして対応しました。

ここ数週間のMixer2のエンハンス、ざっくり解説してみました。安心して最新版をご利用ください。今後ともごひいきに!

Monday, December 23, 2013

JAX-RSのビューとしてMixer2を使ってみる

こんにちは。nabedgeこと渡辺です。 ひとつ前の記事はJava Advent Calendar2013のやつでしたが、 今日はJava EE Advent Calendar 2013の23日目なんです。 JavaじゃなくてJavaEEです。ここでSpringMVCがどうのとか言っちゃうといろんな人が(コンコン、おや誰かきたようだ

そんなわけで、JavaEE規格の中でもWeb系エンジニアにとって最も身近な、JAX-RSのお話です。

今年の3月頃、 JAX-RSはHTML Webアプリケーションを開発するのに充分なフレームワークであるか? - AOEの日記 というエントリが結構話題になりまして、そこではこんな話もありました。

テンプレート処理パートの実装について

(中略)
ただ、普通のJSPプログラミングであるため、エラー時にメッセージやハイライトをしたり、条件に応じた表示変更と言った処理もゴリゴリ実装する必要があります。これが地味にめんどかったりします。少し大きな規模の開発案件になった場合はある程度プレゼンテーションレイヤで必要となるライブラリを整備してあげる必要があると思います。

そのとおりです。javaのmvcフレームワークは、案外どれも「ビューはjsp(jsf)で」と一言書いてあるだけです。 しかし現実世界に置けるM,V,CのViewは、それほど単純ではありません。むしろ、ビューは十分に複雑です。

JAX-RSの設計思想として、httpレスポンスをhtmlではなくjsonやxmlで返すことに主眼を置いているように思えます。 素直に考えると、クライアントサイドはJavaScript等で実装しサーバーから受け取ったjsonやxmlを料理せよ、ということでしょうし、 実際そうしようとしている開発現場も増えてきているかもしれません。 しかしそのためにはBackbone.jsやAngular.jsといったクライアントサイドMVCフレームワークの使い方も覚えなければなりません。 Webデザイナーの仕事とうまく歩調を合わせることまで考えると、道のりは険しそうです。

話をサーバーサイドに戻しましょう。 Viewを実装するために、jsp、jsfあるいはVelocityやThymeleafのようなテンプレートエンジンの特殊文法を覚えたり、 それでも足りなくてカスタムタグやプラグインを書き、気がつけばWebデザイナーさんの仕事は置いてけぼりになっている。 そんなことになるくらいなら、はじめからViewをjavaで普通に書けばいいじゃない! テンプレートは普通のhtml/cssで!それがMixer2の存在理由です。

前置きが長くなりましたがとにかく、html主体のwebアプリケーションを、JAX-RSとMixer2で作る、簡単なサンプルを作ってみました。 ソースは https://github.com/nabedge/mixer2-sample/tree/master/mixer2-jaxrs-sample です。

jax-rs実装にはjersey、サーバはtomcatを想定しています。(あっ、なんでglassfishじゃねーんだって言われそう^^;)

ポイントは二つ。まず一つ目が、リソースクラスのメソッドの戻り値がorg.mixer2.jaxb.xhtml.Html型であることです。 IntexResource.javaをご覧ください。

    @GET
    @Produces(MediaType.TEXT_HTML)
    public Html index(@QueryParam(value = "message") String message)
            throws IOException, TagTypeUnmatchException {

        // loading template
        String template = "m2mockup/m2template/index.html";
        InputStream is = this.getClass().getClassLoader()
                .getResourceAsStream(template);
        Html html = mixer2Engine.loadHtmlTemplate(is);
        
        // replace content in <div id="message"> tag
        if (message != null) {
            Div div = html.getBody().getById("message", Div.class);
            div.unsetContent();
            div.getContent().add(message);
        }
        
        // replace static file path
        Pattern pattern = Pattern.compile("^\\.+/.*m2static/(.*)$");
        PathAjuster.replacePath(html, pattern, "m2static/$1");
        
        // return html object
        return html;
    }

Html型を返されたjerseyは、それを処理しうるMessageBodyWriterを探して引き継いでくれます。 それがMixer2Writer.java です。

@Provider
@Produces(MediaType.TEXT_HTML)
public class Mixer2Writer implements MessageBodyWriter {

    // -- snip --

    @Override
    public void writeTo(Html html, Class type, Type genericType, Annotation[] annotations,
            MediaType mediaType, MultivaluedMap multivaluedMap,
            OutputStream outputStream) throws IOException, WebApplicationException {
        // marshalling html object to string.
        String str = mixer2Engine.saveToString(html);
        OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8");
        writer.write(str);
        writer.flush();
    }
}

Html型のインスタンスをMixer2Engineに渡して文字列化し、そのまま出力しているだけです。

いろいろ急いでしまったので、突っ込みどころだらけです。リソースクラス内でビューの処理もやってしまっている点はイケてなくて、 本来ならViewable やViewableContext をうまく実装して切り分けるべきでしょう。そもそもJavaEEだっつってんのになんでGlassFishじゃなくtomcatで試しているんだとか。 Mixer2Engineの呼び出しもCDIを使うほうがJavaEEらしくなるでしょう。

このサンプル、どなたか試していただいて、もちょっとカッコよくしていただけませんか? マサカリも歓迎ですが、Pull Requestはもっと歓迎です。だってほら、クリスマスだし。

Sunday, December 8, 2013

Mixer2のSpringMVC連携機能がver 1.2.17でさらに進化!

こんばんは。nabedgeこと渡辺です。 この記事はJava Advent Calendar 2013の8日目です。

さて、私が作っているMixer2というテンプレートエンジンですが、 秋口に秀逸な pull request をいただいたので、ありがたくマージしてversion1.2.17をリリースしました。

本当は先週リリースした1.2.14で既にマージ済みだったのですが、 JavaDocに書いたサンプルコードのとおりに書くと動かない(笑)というヤバいのがあったのでリリースしなおしました。 そのJavaDocを書いたのはプルリクをくれた人ではなく私です。 さらに言うと、リリース作業で凡ミスして1.2.15と1.2.16を欠番にしてしまったのも私です。 ^^;)

そんなことはさておき、何が新しくなったのかというとSpringMVCとMixer2を連携させるためのViewとViewResolverです。 とりあえずフルーツショップサンプルアプリケーションの商品配送先住所の入力画面用のコントローラで説明してみます。

@RequestMapping(value = "/shipping")
public String shipping(Model model,
    @RequestParam(value = "redirected", required = false) boolean redirected,
    @Valid Shipping shipping, Errors errors) {

    model.addAttribute("shipping", shipping);
    model.addAttribute("redirected", redirected);
    model.addAttribute("errors", errors);
    return "checkout/shipping";
    // 以前のMixer2ではここで return "shippingView" のように、
    // springコンテナ上にDI済みのviewクラスの名称を
    // 与える必要があったが、新しいMixer2では
    // テンプレートファイルのパスでよい。
    // そしてテンプレートファイルのパスは
    // Viewクラスのパッケージ名/クラス名とそのまま紐づくルール。
}

コントローラの戻り値はテンプレートファイルのパスそのものです。 つまり戻り値の書き方はInternalResourceViewResolver + JSPを使う場合と同じでいいところがポイントです。

次に、配送先住所の入力画面のViewクラスを見てみましょう。

// Viewクラスに@ComponentのようなDIアノテーションは不要。
// 新しいViewResolverが代わりにやってくれる。
public class ItemView extends AbstractMixer2XhtmlView {

    @Autowired
    protected FooBar fooBar; 
    // もちろんSpringコンテナから任意の
    // オブジェクトをDIで受け取れる

    @Override
    protected Html renderHtml(Html html, 
            Map<String, Object> model, 
            HttpServletRequest request,
            HttpServletResponse response) 
            throws TagTypeUnmatchException {

        // Html html = mixer2Engine.loadHtmlTemplate(filePath);
        // のようなコードは不要。
        // 新しくなったAbstractMixer2XhtmlViewが、
        // コントローラのメソッドの戻り値で指定された
        // パスを使ってあらかじめテンプレートをロードして
        // Htmlオブジェクトに格納済み。

        @SuppressWarnings("unchecked")
        List<Category> categoryList = (List<Category>) model.get("categoryList");
        Item item = (Item) model.get("item");

        // embed item box
        replaceItemBox(html, item);

        // 途中は省略

        return html;
    }

ここでSpringの設定のほうを見てみます。



    
    
    
    
    

Mixer2XhtmlViewResolverのprefix,suffix,basePackageのプロパティがポイントです。 つまり、コントローラのメソッドの戻り値が "foo" の場合、
org.mixer2.sample.web.view.FooView がビュークラスで、
クラスパス上の m2mockup/m2template/foo.html がテンプレートファイルです。

コントローラのメソッドの戻り値が "foo/bar" の場合、
org.mixer2.sample.web.view.foo.BarView がビュークラスで、
m2mockup/m2template/foo/bar.html がテンプレートファイルということになります。

もちろんビュークラスはAbstractMixer2XhtmlViewを継承していなければなりません。 なお、複数のテンプレートを組み合わせてhtmlを生成したい場合は、ビュークラス内で getMixer2Engine()でいつでもエンジンを使えますので、好きなテンプレートをいくらでもロード可能です。

クレバーなプルリクをくださったkazuki43zooさんに感謝!

Java Advent Calendar 2013、 次はJavaFXの大御所、skrbさんです。

Wednesday, November 27, 2013

メールアドレスとRFCの話

確かに定期的に繰り返される話題ですね。

「メールアドレスのルール」なんて使ってはいけない3つの理由

問題点1. メールアドレスに関して、RFCなんてそもそも守られていない

2009年以前に登録されたDoCoMo携帯のメールアドレスなど、quoted-stringじゃないのにピリオド連続するものが実在している以上、彼らを許容するべきです。

今そこにある実装 >> (越えられない壁) >> RFC です。

※2009年以前に登録されたDoCoMo携帯のメールアドレスっていうのはつまり、 foo....bar@docomo.ne.jp みたいにドットが連続してたりするアドレス(RFC的にはNG)のことを指します。

んで、「今そこにある実装」を重視すべきなのであれば、以下も重視したうえで、 「やはり彼らを許容すべきではない」という結論も得られてしまいます。

ケースバイケースでしょう。

合わせて読みたい:Internet Explorer はIE特化アプリから一時的に日本を救ってくれたけど次回はもう助けてくれないよという 警告

Sunday, November 24, 2013

DevLove現場甲子園でしゃべってきました

もう先々週のことなんですが、DevLOVE現場甲子園2013というイベントでしゃべってきました。

webデザイナとエンジニアのチームワークを加速させるテンプレートエンジンmixer2 devlove現場甲子園

Mixer2ネタであることはともかく、プレゼン資料自体の使い回し感は否めません。すいませんすいませんすいません。

ほかの方もプレゼンもなかなか面白かったです。 webデザイナーの秋葉さんのプレゼンとか→ 「【DevLOVE甲子園2013】UIと画面遷移を設計するときに 破綻しないようにするための、 ひと手間」

あと、「バラバラの同僚を社内勉強会でつなげよう」っていうやつもなかなか。

最後になりましたが、devloveスタッフの方、本当にご苦労様でした。ありがとうございました。

Saturday, October 26, 2013

log4j2にログを集める

log4j, slf4j, logback, commons-logging... こんがらがりませんか?僕はこんがらがりました。

ある実験的なWebアプリの開発の過程では、ログを最終的に何に集約するか?logbackか?それとも...?と、迷い、 結局log4j2に集約しました。これはそのメモみたいなものです。

なお、「slf4j+logbackのほうがナウでヤングだろ」といったご意見はスルーです。好みとかポリシーの問題です。 また、いにしえより伝わるlog4j1.xではなく、log4j2.xっていうところもポイントです。 java.util.logging?えーっ?!却下。

1. 前提とか方針とか

  • 新規のJava-Webアプリを開発する。そのコード上で使うLoggerにはlog4j2を使う。
  • ベースはSpringMVCフレームワーク。spring自身は内部でcommons-loggingを使っているので、それもlog4j2に集められるように設定する。
  • Spring以外にもいろいろOSSライブラリを使うが、それが吐くログもできる限りlog4j2に集める。例えば、内部でslf4j-apiを使ってるOSSが最近はとても多い。
  • 設定はlog4j2.xmlに集める。とりあえずWebアプリ内部に同梱する。
  • ビルドツールはmavenを使う

2. mavenのpom.xml

dependenciesタグ内で先に書いてあるほうが優先されるので、ログ出力ライブラリは上のほうに書いておくのが無難です。log4j-coreがもちろんlog4j2の本体。 log4j-jclがcommons-loggingによる出力をlog4j2に中継させるやつ。log4j-slf4j-implはslf4jによる出力を(以下略)

    
        
            org.apache.logging.log4j
            log4j-core
            2.0-beta8
        
        
            org.apache.logging.log4j
            log4j-jcl
            2.0-beta8
        
        
            org.apache.logging.log4j
            log4j-slf4j-impl
            2.0-beta8
        

        ... other dependency...
    

maven使いじゃない人のために、これで実際どんなjarがビルドパスに入ってくれるのか、書いておきます。こんだけ。

log4j-core-2.0-beta8.jar
log4j-api-2.0-beta8.jar
log4j-jcl-2.0-beta8.jar
commons-logging-1.1.1.jar
log4j-slf4j-impl-2.0-beta8.jar
slf4j-api-1.7.5.jar
slf4j-ext-1.7.5.jar
cal10n-api-0.7.4.jar

3. log4j2.xml

log4j2.xmlをsrc/main/resourcesに置く。root(要するにデフォルト値)を設定するほか、 ログ出力を制御したいクラス名、パッケージ名に対して出力レベルや出力先(appender)を設定します。

4. コードを書く

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Foo {
    private static Logger logger = LogManager.getLogger();
    public void bar(String a, String b) {
        logger.debug("a={},b={}", a, b);
    }
}

ログに変数をいれたいときに、logger.debug("a=" + a + ",b=" + b ) などとやってしまいがちですが、 実はこれ、ログ出力メソッドよりも先に+演算子による文字列連結の方が先に実行されますので、性能影響が出ます。 logger.debug()なんて本番環境ではオフにすると思いますが、それでも文字列連結は無駄に実行されてしまうのです。 どの程度の性能差が出るかは Performance - Apache Log4j 2 に詳しく解説されています。 せっかくlog4j2を使うのですから、{}記号によるプレースホルダ機能を使うようにしましょう。

また、log4j1.xのときは、
provate static Logger logger = Logger.getLogger(Foo.class);
のように、ロガー名として自クラスを明示的に与えてloggerを作る必要がありましたが、 log4j2のLogManagerでは省略できます。 log4j2のほうが好みな理由はこれが地味に便利だからかも。

Tuesday, October 1, 2013

Mixer2 as XHTML snippet generator

Mixer2 is the xhtml dedicated template engine. Because Mixer2 use JAXB (Java Architecture for XML Binding) internally, the usage is not only as a template engine, but also, Mixer2 can be used in another way.

Mixer2 has some different functionality.

  1. as a alternative to JSP, Velocity, and other template engine technology
  2. as a XHTML parser
  3. as as XHTML tag snippet generator

In thie post, I introduce "XHTML snippet generator" functionality of Mixer2.

You must fix up your html template as "full html" like "<html>...</html>" in order to use mixer2Engine.loadHtmlTemplate() .

But if you need to output xhtml tag using mixer2Engine.saveToString(), you can get any tag snippet as string. So, you can create some helper class like custom tag of JSP.

For example, If you must use jsp as the base template but also you want to use Mixer2, You can use them combine them.

If you create the new tag instance, use "new" the tag classes. Also you can use TagCreator.

Div div = TagCreator.div();
Span span = TagCreator.span();
span.getContent().add("Hello World !");
span.setStyle("color:red;");
div.getContent().add(span);
String result = mixer2Engine.saveToString(div);
System.out.println(result);

output:

Hello World !

If you create table tag, you can use TableBuilder.

String[][] data = new String[][]{
    // id, name, price
    {"1", "cookie", "2.50"},
    {"2", "candy",  "3.75"}
};

TableBuilder tBuilder = new TableBuilder();
for (String[] row : data) {
    tBuilder
        .addTr()
        .addTd(row[0])
        .addTd(row[1])
        .addTd(row[2]);
}
Table table = tBuilder.build();
String str = mixer2Engine.saveToString(table);
System.out.println(str);

output:

1 cookie 2.50
2 candy 3.75

For more detail of TableBuilder, see Mixer2 official site.

How about it ? Mixer2 and other template technology can exist together. Try Mixer2 !