Monday, December 21, 2015

「mavenと書いて達人と読む」という勉強会を4日連続でやった話

このエントリはJava アドベントカレンダー 2015の20日目となります。 ただし今日は12月21日です。21日目のエントリがもう公開されているというレベルです。ごめんなさいごめんなさいごめんなさい。

さて、年末年始を前にして何か大きな機能追加とかリリースとかやって「やらかして」しまうとクリスマスも正月もドナドナになってしまうのを避けるために、 この時期はあまり大きな仕事はしないことになっております。そういうスキマ時間にしかできないことを少しやってみようと思いまして、 職場のエンジニアを集めてmavenの勉強会をやってみました。題して「mavenと書いて達人と読む」。

夕方に30分 x 4日連続。講師は全部自分。はい。2日目で力つきそうになって、4日シリーズにしたことを後悔しましたw。 そもそも自分自身だって達人にはほど遠いのですが、 プロジェクトの中でpom.xmlのメンテをやる人が限られてしまうとこうなるみたいなことがあったので、 やっぱり経験の浅い若手相手に座学っぽくやるのも時には必要なんだなーと思いました。 なお、いまどきgradleでしょ!とか言う話はスルーです。セントラルリポジトリのお世話になったことがないという者だけがmavenに石を投げなさい。

そんなわけで、以下、メモです。

1日目 maven標準ディレクトリ構造と基本コマンド

  1. ソースコードを動作可能な状態にまで変換することをビルドという。これはスクリプト言語でもコンパイル言語でも変わらない。コンパイル言語の場合にはビルドにはコンパイルという工程が含まれる。ビルドを支援するのがビルドツール。かつてはant、いまはmavenかgradle.
  2. IDE使わずにエディタだけでsrc/main/java/HelloWorld.javaとpom.xmlをつくる
  3. compile, exec:java, package, install など一通りたたいてみる
  4. 教科書にあるようなjavac HelloWorld.javaもやってみて、なにがどこにどう生成されるのか、比較してみる
  5. src/main/java, src/main/resources, src/test/java, src/test/resources というシンプルかつ機能的なディレクトリ構造と、依存関係の自動解決というのがmavenの最大の功績。
  6. 他のビルドツールを使っていても、結局 src/main/java みたいな構造は一緒であることが多い。
  7. ls ~/.m2/repository してみる。このディレクトリは何なのだろう?は次回以降のお楽しみ。

2日目 依存関係の自動解決、リポジトリという概念

  1. System.out.println("Hello World") のところをlog.info("...")に書き換える。当然まだコンパイルはできない。
  2. このときpomのdependencyにcommons-loggingを追加。mvn compileができるようになる。
  3. HelloWorldというクラスはorg.apache.commons.logging.Logというクラスに「依存している」同様にhelloというartifact(プロジェクト)はcommons-loggingというartifactに「依存している」依存関係をdependencyタグで表す。
  4. ちなみにjavacでやろうとすると javac -claspath "~/.m2/repository/commons-logging/commons-logging/1.1.1/commons-loggin-1.1.1.jar" src/main/java/HelloWorld.java みたいにすればコンパイルできる
  5. コンパイルのときや実行のときにクラスパスをいい感じにやっておいてくれるのがmavenのいいところ。それが依存関係の自動解決。
  6. リポジトリにはローカルとリモートの2種類がある。~/.m2/repositoryがローカル。リモートリポジトリのキャッシュみたいな役割になる(それだけじゃないけど)
  7. mvn help:effective-pom ってやるとセントラルリポジトリのurlがわかるよ。そのurlをブラウザで見てみると。。。
  8. mvn dependency:tree
  9. リモートリポジトリは誰でも立てられる。公開してもいいし、非公開ならインハウスリポジトリってことになる。ex. http://repository.apache.org

3日目 推移的な依存関係とビルドライフサイクル

※この日は疲れていたので内容が薄いw

  1. spring-boot-starterとか使って簡単なpom.xmlを作っただけなのにWebアプリがいきなりできあがるマジック
  2. mvn dependency:tree するとすごい数のjar(artifact)がツリー上に見える。これが「推移的」な依存関係。
  3. ビルドライフサイクルというものがある

4日目 マルチプロジェクト構造

  1. packagingというところにはpom, jar, war みたいな種類を書く。Project Object Model, Java Application Archive, Web Application Archive...
  2. たまにearというやつもあってだな、Enterprise...と口に出した瞬間からjarを含んだwarを複数含んだのがearでWebLogicだかなんだかで動いて起動に15分とかかかってもうねアホか..トラウマに襲われて取り乱すもなんとか平静を取り戻す
  3. parentとmodulesというタグを使って親子関係を形作ることができる。普通のファイルシステムとディレクトリ構造と同じような感じになる。src/main/javaも含めて総合的にこれがmavenの標準ディレクトリ構造。
  4. なお、依存関係(dependency)と親子関係(parent,module)は似て非なる概念なのでご注意。
  5. parentタグにrelativePathを指定して強制的にフラットなディレクトリ構造にしてしまう手法がよく取られる。これはEclipseの制約という歴史的な事情がある。
  6. IntelliJなど、設計思想の段階でビルドツールの存在を前提にしたIDEが台頭してきたおかげで、本来のmaven標準ディレクトリ構造を生かせるようになった。
  7. だからIntelliJ IDEA Ultimateを買う予算をちゃんと引き当ててください。(※実際、買うことになってる)

そろそろ風呂に入って寝たいのでこのへんで。明日はn_slenderさんによるPlayFramework 2.4 Java Ebeanでのアプリ開発です!お楽しみに!

Saturday, December 12, 2015

乾杯から始まるSpringFramework入門に顔出してきた

自分とこではSpringは長く使っているので入門ということではないのですが、 「乾杯から始まる」という何気ないその一言にいたく感動しw、行ってきました。 横浜みなとみらいとか久しぶりだったなー。

乾杯からはじまるSpringFramework入門 (connpass.com)

タグバンガーズさんのことは存じませんでしたが、 Java/Springでゴリゴリと仕事する若々しいエンジニア集団(しかもWeb系)って、 いるところにはちゃんといるんだなと再認識しました。 小川さんという方と名刺を交換させていただいたときはどちらの陶芸家の先生だろうなどと思っていたら社長さんでした。 その小川さんがろくろをまわし始めIntelliJ IDEAでSpringBootフレームワークからのHibernateのEntity作ってからDDL自動生成からので高速コーディングを見せてくれました。 その間私はハイネケン3本を飲み干しておりました。本当にごちそうさまでした。

繰り返しになりますが、RoRとかPHPとかが人気の昨今ですが Java/SpringでゴリゴリWeb系システムつくってる人たちってちゃんといるし、 そこそこ儲かっているんだなと思うとなんだかとても親近感を覚えました。

そのまま実家に帰る用事があったので懇親会のあとすぐおいとましました。 次の機会にはぜひ渋谷の自分ところの勉強会かピザパーティにでも顔出していただいて、 なんなら講師としてSpringをご教示いただけたらな、なんて他力本願なことを思いながらクリスマスの華やかなみなとみらいを後にしました。

タグバンガーズの皆様、ありがとうございました。小川さん、陶芸家とか書いちゃってすみません。今日も実家で昼酒飲んで酔っているので多めにみてください。 お会いしたSIerの戦士の方々、いろいろお話できてうれしかったです。 私も元SIerですが、Web系の事業会社のエンジニアも、楽しいですよ。

追記

名刺入れに小川さんの名刺が無いぞ、はて??と思ったら、勉強会の机の上に名刺を何枚か置いたままだったことを、たったいま思い出しました。 ぐぬぬ。社会人としてあるまじき失礼なことを!!ごめんなさいごめんなさいマジごめんなさい。

Sunday, November 29, 2015

JJUG CCC 2015 Fallに行ってきました

昨日、日本Javaユーザーズグループ クロスコミュニティカンファレンス 2015 Fallに行ってきました。 今回も記録更新の参加者数だったそうです。

自社のスポンサーセッションとして自分の後輩君が「Java8移行から始めた技術的負債との戦い」と題して登壇しましたので見届けてきました。

驚いたことに160人の部屋が満室で立ち見続出。席の間の通路に座り見までしてもらって、それでも入りきらないという状況でした。 Java8移行とか技術的負債とか、どこの現場のエンジニアも一様に悩んでいるがゆえの切実な需要があったということなのでしょう。

個人的には 「GH-5 サーバサイドのビュー処理エンジンForneusの開発秘話」というセッションが興味深かったです。 Mixer2というテンプレートエンジンを作っている自分としては、 登壇者の井上さんが語るJavaのテンプレートエンジンに関する問題意識には非常に納得というか 「ああみんな同じようなこと考えているんだなあ」という意味においてなんだか不思議な安心感と親近感を覚えました。

最後に聴講したのは「GH-7 てらだよしおの赤裸々タイム」。 日本におけるJava言語の啓蒙者というかスポークスマン的な存在のてらだよしおさんが サンマイクロシステムズからオラクル(買収)、そして驚きのマイクロソフトへの転職から数ヶ月たったいま、 なかなか楽しいセキララトークを聞くことができました。

転職サイトの開発に携わるエンジニアとしてこれは質問のひとつもしておかねばなるまいと、最後にマイクをお借りしました。

「寺田さんがオラクルからMSに転職するために転職サイトを使ったということはないでしょうが、 しかしこの会場の大多数の人は寺田さんほどの知名度はありません。 それでもなお新天地を求めて動くべきときが誰にでも来る可能性があります。 採用する側もエンジニアが欲しいから採用しています。 採用する側、採用される側、それぞれは、なにを考え、なにを問いかけ、なにを準備するべきなのでしょうか?」

そんなぼんやりとした私からの問いかけにも、寺田さんは的確に返してくれました。

なんでもできるオールマイティな人よりも、(採用される側は)何か一つだけでも強いもの尖ったものを持つことが大事で、(採用する側は)そうした人間のヨコの繋がりを強化していくような形がいいんじゃないか。

たしかそんな趣旨のことをこたえてくださいました。

と言ってくれる聴講者の方もいらっしゃったようで、お役に立ててなによりです。

なお、じつは質問の手を挙げたときは

という趣旨の質問をしようとしてマイクをもらってからオトナのブレーキがかかって1.5秒のアドリブでこの質問をひねり出した自分をあらためてほめてあげたい日曜日の昼下がりです。

Monday, November 23, 2015

マイナンバーのチェックデジットを検証するJavaライブラリ"jpn-mynumber"

ソースはgithubに。バイナリとjavadocはmavenセントラルリポジトリに登録済みです。 個人番号と法人番号の両方に対応。 詳しくは https://github.com/nabedge/jpn-mynumber からどうぞ。

Tuesday, November 17, 2015

Mixer2 1.3.1をリリース TagTypeUnmatchExceptionは非チェック例外になりました

うっかり薄着で夜更かししてコード書いてたら見事に風邪引いたのか、強烈な頭痛に襲われまくりの秋の朝。 どうにか落ち着いたので、ブログでも更新します。そういえば半年も放置してしまってた。

Mixer2の1.2.41と1.3.1 をリリースしました。これにて1.2系統は打ち止めとします。

まず、html5の<main></main>タグのサポートを追加しました。これは1.2.41と1.3.1の両方です。 今頃mainタグ?って感じですが、Mixer2にHTML5対応実装を最初に追加したのが2012年ごろで、このころはmainタグはまだ勧告候補にすらなっていない、拡張仕様扱いだったのです。今となっては若干記憶があやふやですが、その後もちょこちょこ属性の追加の対応などには追随していたものの、mainタグだけすっぽり抜けて忘れていました(笑)

あと、1.3系統ではTagTypeUnmatchException を非チェック例外(extends RuntimeException)にすることにしました。 この例外はたとえばulタグの中にliではなくdivを直接つっこもうとすると発生するやつです。 Java8の時代になって、Lambda式の中での例外の取り回しがかえって難しくなるケースがあることから、思い切って非チェック例外に切り替えることにしました。 だからマイナーバージョン番号も1.3にup。

さて、天気がいいので散歩して飯食って仕事しますかね。

Monday, May 4, 2015

Mixer2 1.2.36 リリース。replaceInner()でタグの中身を一発で置換

先月、Mixer2 1.2.36 をリリースしてました。http://mixer2.org 目玉はreplaceInner()メソッドで、これはhtmlタグの中身を一発で置換します。

Before

Html html = m2e.loadHtmlTemplate(new File("HelloWorld.html"));
html.getById("hellomsg", Div.class).unsetContent();
html.getById("hellomsg", Div.class).getContent().add("Hello World !");

After

Html html = m2e.loadHtmlTemplate(new File("HelloWorld.html"));
html.getById("hellomsg",Div.class).replaceInner("Hello World !");

こんな基本的なことっぽいメソッドを今まで用意していなかった理由は語ると長くって、、まあ要するにJAXB-api周りの取り回しで結構面倒なワナがあったからなのですが、 どうにかねじふせました。リリース直後のバグとりを手伝ってくださった @fjut さんに感謝です!

Sunday, March 22, 2015

java.ext.dirsは廃止の方向だそうです

今月初めの 第10回#渋谷Javaで久しぶりに登壇してトークしたのですが、その内容が実は大嘘でしたという話です。

資料がこれ。

かいつまんで言うと

  1. JREには拡張機能機構というのがもともとあって、
  2. $JAVA_HOME/lib/ext (javaのシステムプロパティで言うとjava.ext.dirs)に自前のjarを置くと自動的にクラスパスに含まれるので
  3. そういう形でアプリもJREもセットでサーバにデプロイするようにすればいろいろ設計する手間が省けて何かと幸せになれるかもね

という趣旨でした。

ところがぎっちょん

2015/3/3つまり第10回#渋谷Javaのたった三日前。Java8u40 がリリースされていました。まったく気にしていなかったのですが、 そのリリースノートには衝撃の内容が。

推奨規格オーバーライド機構と拡張機能機構は非推奨であり、今後のリリースで削除される可能性があります。実行時の変更はありません。 「推奨規格オーバーライド」機構または「拡張機能」機構を使用している既存のアプリケーションは、 これらの機構を使用しないよう移行することをお薦めします。これらの機構を既存で使用しているかを識別するために、 -XX:+CheckEndorsedAndExtDirsコマンド行オプションを使用できます。次のいずれかの条件がtrueの場合、失敗します。
  • -Djava.endorsed.dirsまたは-Djava.ext.dirsシステム・プロパティがデフォルトの場所を変更するために設定されているか、
  • ${java.home}/lib/endorsedディレクトリが存在するか、
  • ${java.home}/lib/extにJDKに同梱されているファイル以外のJARファイルが含まれているか、
  • プラットフォーム固有のシステム全体の拡張ディレクトリにJARファイルが含まれている。
JDK 8u40以降のリリースで、-XX:+CheckEndorsedAndExtDirsコマンド行オプションがサポートされます。

#渋谷javaの会場で「java1.4,5,6,7,8まである機能がそんな簡単に消えやしませんから安心して使っちゃいましょう!」って高らかに宣言した私の立場ナッシング。

詳しくは追ってないのですがどうやらJavaアプリケーションのパッケージング機構に関してJCEで別の議論が進んでいるようで、それにからんで古いほうの機構は削除の方向らしいです。 それにしても少なくともJava1.4以降ずっとあった機能が削除されようとは!しかもこのタイミングでw

そんなわけですが、開発したJavaアプリをJREとセットでデプロイしちゃおうぜというアイデアが実現不可能になったわけではまったくないので、普通にJREとアプリとをそれぞれサーバ上に展開し、java -classpath "自作のjarと依存jarの展開先dir/*" com.example.MyMain みたいな感じでclasspathをワイルドカード指定しちゃえばいいと思います。

Sunday, January 18, 2015

去年の秋のJJUG-CCCで講演したら思ったより満足度高かったらしい

もう年も明けて鏡開きも成人式も終わった今日この頃ですが、思い出したかのように、去年の秋のJJUG-CCC Fallで講演したときの聴講者アンケート結果が届きました。実際、中の人が次の3月のJJUG-CCC Springのセッションの公募を始めたついでに思い出したんだろうけど(笑)。

自分自身、あのあとすぐもう通常のお仕事に忙殺されていて、参加記とかそういうのをまったく書いていなかったことに気づいたので、超遅ればせながらなんか書きのこして置くことにします。

まず使った資料ですが、こちら。

見ての通り、それほど難しい内容ではなかったんです。JJUGで喋るのが初めてなわけじゃないとはいえ、しかしやっぱり他のセッションではすんごい人がすんごいエッジの効いたディープな話とかしてるわけで、正直どうなのかなー、教室一杯に人がいたけどツマンネーと思われてたらしゃくだなーとかちょっぴり弱気になってる自分もおりました。

ところが、数時間ほど前に届いた参加者アンケート結果の集計によると、満足度はそこそこ高いほうに入っていたようで、我ながらびっくり。考えてみればそうですね、誰もがディープな話を聞きたいわけじゃない、少し現実味を帯びたくらいの話がちょうどいいということもあるのでしょう。

きっちり自社CMも入れておいたことだし(笑)、通常業務も年明けで一区切りついたことだし、3月のCall For Paperにもなんかネタ考えて応募してみる気力も出てきたところで、 「R1-5 JavaでやってみるThe Twelve Factor App」に足を運んでくださった皆様にあつく御礼申し上げますとともに、遅ればせながら新年のご挨拶にかえさせていただきます。本年もよろしくお願い申し上げます。

Tuesday, September 23, 2014

Mixer2 1.2.34でのエンハンス(SpringMVC関連)

今月、Mixer2は実は2回リリースしてます。1.2.33と1.2.34。 1.2.33では一部のメソッドをprivateからprotectedにしたことで拡張、改造がしやすくなりました。 1.2.34ではSpringMVC用のAbstractなViewクラスを少し変更しています(下位互換性はありますのでご安心ください)。また、XMLStringUtilというユーティリティクラスを追加しています。

まずXMLStringUtil。これはXHTML(XML)として有効な文字列かどうかを判別したり、無効な文字列を任意の文字(デフォルトだと空白ひとつ)で置換することができます。 XMLで使用できる文字列はw3c.org上で厳密に決められています。簡単に言うと、いわゆるUTF-8の範囲内の文字と、あとは改行、空白、タブ等のごく限られた制御コードのみということです。 XHTMLはXMLのサブセットですから右に同じということになり、Mixer2が使用しているJavaのJAXB実装もこれに厳密に従っています。そのため、妙な制御コード、たとえば改ページ制御コードがxhtmlテンプレート上に含まれていたり、あるいはそれをorg.mixer2.jaxb.xhtml.*配下のタグ型の内部にうっかり仕込もうとすると、saveToStringする段階で例外が発生してしまうことがあります。 XMLStringUtilはその防波堤となるユーティリティです。

次に、SpringMVC用の抽象ビュークラスに新たにmodifyHtmlStringHookというメソッドを追加しました。 このメソッドは、Mixer2がhtmlオブジェクトをsaveToString()して文字列化したあとに呼ばれ、その後すぐhttp responseするようになっています。

デフォルトのままだとスルーパスするだけ(何もしない)ですが、Viewの実装クラス内でこのメソッドをオーバーライドすると、httpレスポンスされる直前のhtml文字列(Html型のインスタンスではなく)を直接操作できます。これによって、Mixer2ではできないこと、たとえばhtmlコメント等の埋め込みが可能です。 たとえば、HTML5未対応なIE8以下を擬似的にhtml5対応させるために、html5.jsを使うことがあると思います。 しかし、公式サイトを見ての通り、これは

<!--[if lt IE 9]><script src="dist/html5shiv.js"></script><![endif]-->
のように、IE特有のコンディショナルコメントとして埋め込む必要があります。Mixer2はhtmlコメントを埋め込むことができない(あっても無視してしまう)ので、Mixer2付属のSpringMVC用のビュー/ビューリゾルバでは使用できませんでした。1.2.34以降では、modifyHtmlStringHook() をオーバーライドして、例えば</head>タグのあたりをString#replace()メソッド等を使って狙い撃ちにすれば、上記のコンディショナルコメントを追加することができます。

まだ公式マニュアルには実はどちらもまともに書いていません。そのうちちゃんと書かねば。