Mavenの使い方と、スキルとしての発展

ビルドツールとしての『Maven』。
そしてMavenをスキルとして昇華していく私なりのルートを
紹介したいと思います。


まずは『インストール』。
私は以下サイトさんをよく拝見させてもらってます。
他の記事も基本的なところから深いところまで記述されていてすごいです。
[ひしだまさんの技術メモ]
http://www.ne.jp/asahi/hishidama/home/tech/apache/maven/install.html

使い方
以下サイトで勉強しました。
[TECHSCORE]
http://www.techscore.com/tech/Java/ApacheJakarta/Maven/index/
Mavenのバージョン2を扱っていますが、基本的には同じなのでかなり勉強になります。

ここでだいたい理解したら、本家Mavenの"Learning about Maven"を眺めたり、
http://maven.apache.org/

プラグインについて知りたければ、本家Mavenのpluginページを眺めて、
「こんなGoalあるのね」とか「こんな設定もできたのか」とか面白くなってきます。
http://maven.apache.org/plugins/index.html


そして『発展』。

Mavenの恩恵を理解してきたところでもっとMavenの力を感じられる概念を学ぶと良いです。
それは「継続的インテグレーション(Continuous Integration:CI)」です。
Mavenは基本概念としてプロジェクトの「ライフサイクル」を管理するものですが、
ライフサイクルを利用して様々な恩恵を受けることができます。
その一部が"継続的インテグレーション"です。

継続的インテグレーションについてはいろいろなサイトで読むことができたり、
[オブラブ]さん
http://objectclub.jp/community/XP-jp/xp_relate/cont-j

私も購入して読みました。
継続的インテグレーション入門」という本があります。良書です。
[プログラマの思索]さんで紹介されてます。
http://forza.cocolog-nifty.com/blog/2011/09/post-b1d4.html


CIをするならCIツールである、Jenkinsを推します。Jenkins推しです。
日本人の川口さんが作ったものです。
[Jenkinsの生みの親が語る、継続的インテグレーションの未来]
http://www.atmarkit.co.jp/news/201106/06/jenkins.html

最近オライリーからもJenkins本が出ました。通称カエル本。
http://www.oreilly.co.jp/books/9784873115344/


ここまで来るとmojoも使うようなります。
mojoとはApacheプロジェクト外のpluginを扱う場所です。
http://mojo.codehaus.org/plugins.html
まぁカエル本読む前に既に使ってるかもしれませんが、
よく使われるのは、
・cobertura(コード・カバレッジ測定)
findbugs(静的ソース解析)
とかですか。


ここまで来ると社内でも固有のスキルを持つ人物として扱われだすように思います。
あとはMaven含め、継続的インテグレーションの『伝道師』(エヴァンジェリスト)として
積極的に活動していってください。

まだまだ開発やテスト、品質を軽視する現場は多いです。
そんな現場を変える力をMaven、CI、Jenkinsは持っているはずです。
それには仲間を増やさねばいけません。

ここを読んであなたも仲間になり、モダンな現場が増えればいいなと思います。

plyframework テンプレートに@inputHiddenってないの?

便利なplay framworkのタグ テンプレート。
http://www.playframework.org/documentation/2.0/ScalaTemplates

@inputTextでテキストボックスを作れる。
しかしtype hiddenのinputほしいなーとテンプレート探してみてもないみたい。

ぐぐってみたらやっぱり無くて、普通に

<input type="hidden" value="@hoge.id" name="id">

みたいにしろ、だとさ。

[Google-group] - play-framework
https://groups.google.com/forum/#!topic/play-framework/t4aeUiy1YpU
※見るにはgoogleアカウントが必要(グループには入らなくても見れる)


ちなみに、@inputTextとかはviews.html.helperパッケージ以下に存在してる。

anormでNULLを許容するテーブルをSelectする

scala初心者、playframeworkも初心者な私が触ってみてはまったことを解説していく。

playframeworkのチュートリアルをやってみて、ちょっと変更しようと思ったら「Null列がSelectできないでござる」とか言われてしまった。
チュートリアルhttp://www.playframework.org/documentation/2.0/ScalaTodoList

例えば、タスクの情報に"登録日"(createdate)と"締切日"(deadline)を追加したい

チュートリアルで作成した1.sqlを改良して、列を追加する。

# Tasks schema
# --- !Ups
CREATE SEQUENCE task_id_seq;
CREATE TABLE task (
  id integer NOT NULL DEFAULT nextval('task_id_seq'),
  label varchar(255),
  deadline date,
  createdate date DEFAULT sysdate
);
# --- !Downs
DROP TABLE task;
DROP SEQUENCE task_id_seq;

登録日はinsertした日でいいのでDEFAULT sysdate。

次にmodels/Task.scalaを修正。
case classの部分と、

case class Task(
    id: Long,
    label: String,
    deadline: Date,
    createdate: Date
)

val taskを変更。

val task ={
  get[Long]("id") ~
  get[String]("label") ~
  get[Date]("deadline") ~
  get[Date]("createdate") map {
    case id~label~deadline~createdate =>
      Task(id,label,deadline,createdate)
  }
}

val taskってのはSQLの結果をパースするParserを変数にしている。
チュートリアルでは、SQL("select * from task").as(task *) と書いている。


そしてviewも変更する。
チュートリアルをちょっと変更してtableでタスク一覧を表示する。
index.scala.html

@(tasks: List[Task], taskForm: Form[String])

@import helper._

@main("Todo List") {

  <h1>@tasks.size task(s)</h1>

  <table border="1">
      <tr>
        <td>ID</td>
        <td>タスク</td>
        <td>締切日</td>
        <td>登録日</td>
      </tr>
      @tasks.map { task =>
        <tr>
          <td>@task.id</td>
          <td>@task.label</td>
          <td>@task.deadline</td>
          <td>@task.createdate</td>
          <td>
          @form(routes.Application.deleteTask(task.id)) {
            <input type="submit" value="Delete">
          }
          </td>
        </tr>
      }
    </table>
  <h2>Add a new task</h2>
  @form(routes.Application.newTask) {
    @inputText(taskForm("label"))
    <input type="submit" value="Create">
  }
}

これでタスクを登録してみると・・・

insertは成功して、再表示のTask.all()メソッドでエラーです。
[RuntimeException: UnexpectedNullableFound(TASK.DEADLINE)]
deadlineがNULLなので型が解析できないようです。

Optionを使ってNULLを許容できるようにしてあげます。

case class Task(
    id: Long,
    label: String,
    deadline: Option[Date],
    createdate: Date
)

object Task {
  val task ={
    get[Long]("id") ~
    get[String]("label") ~
    get[Option[Date]]("deadline") ~
    get[Date]("createdate") map {
      case id~label~deadline~createdate =>
        Task(id,label,deadline,createdate)
    }
  }
〜〜〜

これでおっけー!

こう見ると単純で簡単なんだけど、scala初心者には
SQLParserってなにこれどう動くのとか、case classにもOption必要なの?とか
ハマりどころだったわけです。


まずはScalaをじっくり学んだほうが良さそうですな。

おわり!

怒らないこと

もう1年以上前に、「怒りを押さえる or 阻止するにはどうしたらいいんだろうか」ということを真剣に考えたことがあった。
つまり、どうでもいいことで怒って気分を悪くしてしまうことをそろそろ避けたいと考えた訳だ。
例えば、満員電車でいらいらするとか、ちょっとした言葉のニュアンスで不満を持つだとか、昔あった嫌なことを思い出しては壁パンするとか、そういうことがもう嫌になったな、と考えた。

とりあえず、これは哲学の世界に近そうだ、と考えた。*1
しかし感情を扱う哲学はそう多くは無いような気がしたし、哲学は膨大なので探すのが大変だと感じた。

そこで思いついたのは儒教、仏教などの「教え」はヒントにならないか、ということだった。
私は以前からwikipediaで宗教に関する由来や考え方を読むことはたまにあったし仏教の「他力本願」という言葉が好きだったりもした。

とりあえず駅の本屋へ向かった。
私は「日本人の考え方は儒教に似ている」とどこかで読んで鵜呑みにしていたため、儒教の本を探した。
しかしあまりたいした本は見つからず(研究結果のような本はいくつかあったが)その場で見つけた仏教の本をターゲットにした。
最初に開いたのは電車の広告でみた本だったが、ほかの本も開いてみた。
その中でこれだ!と思ったのが、まんまタイトル怒らないこと著:スリランカ初期仏教長老 アルボムッレ・スマナサーラ700円)だった。
書いた人は全然しらないが、目次にあった「他人が吐いたゴミを食べる必要はない」というところが気に入った。
その頃何度も感じていた言葉だったからだ。

読んでみてわかったがこの本には、

  • 「怒り」とは何か
  • その定義は
  • 「怒るのは当たり前だ」への反証
  • 怒りによる自己の破壊
  • 怒らないとはどういうことか
  • 怒りの治め方
  • 怒りと幸福の関係

・・・など私が読みたかった事柄がほぼ書かれていた。

いろいろと書かれていることを紹介したいが、それに興味がある人には読んでもらった方が早いと思うので、先に書いた「他人が吐いたゴミを食べる必要はない」の部分だけ書き出そうと思う。

怒りは雪だるま式に大きくなるので、だいたい怒っている人は、怒って怒って、もうたまらない状態になっているのです。
怒りを自分でなくせない人間は、自分の心に怒りの毒が生まれたら、そのエネルギーを外に出さなくてはいけません。ですから、怒っている人は、そのためにしゃべっているだけなのです。こちらとしてはたいへん迷惑ですが、聞いている側に悪いところはありません。
能力のない上司が有能な部下をけなしているとします。そういう場合は、けなされているほうの部下が、心の中で「この人は歳も取っていて、能力もない。それで自分のことが心配で悩んでいて、そのストレスを発散しているんだ。だから、その状態から救い出してあげよう。」と思いながら、その人の話を聞けばいいのです。
話は聞いてあげても、相手の怒りを感情的に引き受けて気落ちする必要はまったくありません。その人は、自分のからだに溜まったゴミを外に出しているだけなのですから、わざわざ自分がゴミ箱になる必要はありません。
怒っている人の状態は、何かひどいものを食べておなかを壊して吐いているのと同じなのです。その人の言葉や行動は溜まっている毒を出しているだけですから、きれいになって落ち着くまで、思う存分出させてあげましょう。「あの人が吐いたものを食べて、私までおなかを壊す必要はない」という態度でよいのです。
たとえ、もとがどんなに美味しいものであっても、食べて吐いたものを拾ってまた食べるというのは無理でしょう?怒りもそういうものなのです。怒る人々というのは、自分がまず怒った上で、さらに人を怒らせようとしています。からだに悪いものを食べてそれを吐き、誰かに食べさせようとしているのと同じ状態なのです。
ですから、そんなものを拾って食べてはいけません。まわりの人が怒って話しているのにつられて自分も怒るということは、「腐ったものを食べた人が吐いたものを、拾って食べているようなものだ」と肝に銘じておきましょう。けっして受け入れてはならないのです。心をそういう状態にまで育てられれば、相手の怒りに対する怒りなど、なんのことはなく即座に消えてしまいます。

書いてみると意外に大変だった・・・読むと2ページにしかならないんだけどね。
この部分はだいぶ最後の方なのでここで、上司を救い出そう、としている部分は相手の怒りを見通した上での行動、ということになるんだと思っている。

ちなみにこれらのことを自分なりに少しづつ意識して考えるようになってきたと思う。
最近は満員電車で疲れることはあっても怒りを持つことはなくなってきたし、悪い思い出もすぐに吹き消すように努力している。
それなりにでも「気の持ちよう」というものは変わるもので、仕事上でも怒りを含めることは少なくなったと勝手に思っている。

最後に、この本が一番伝えたい言葉は、「怒る人ほど頭が悪いという真理」・「怒らない人ほど智慧を持つ」だとおもっている。

同じような悩みを持つ人は自分だけで考えないで、知識を拾ってから考えたら良いと思う。
この話はおしまい。

*1:精神科という方向もあったかもしれないが、自分の中で上記事柄は「願望」であったため、「治療」であると認識している精神医療への意識は消えていた。

Cygwin上でgemを使おうとすると、"No such file or directory"

久しぶりに投稿。

RubyにはRubyGems(コマンド名:gem)っていうrubyのアプリケーションやライブラリを管理できるツールがある。
それをCygwin上で利用した時に以下エラーになる場合がある。

$ gem --help
C:\Ruby193\bin\ruby.exe: No such file or directory -- /cygdrive/c/Ruby193/bin/gem (LoadError)

恐らくrubyからはwinパスでアクセスしたいけどcygwinunixパスでやろうとするから変だーって感じなんじゃね。

手っ取り早く解決するならば、aliasを設定しちゃうと上手くいく。

alias gem='C:/Ruby193/bin/gem'

まぁgemでいろいろアプリ入れるたびにalias設定してやらないといけないから結構面倒なんだけどね。

antでZipExceptionが起きる

antを作っていたらなぜかZipExceptionが発生してしまった。

Unable to obtain resource from XXXXX.properties:
java.util.zip.ZipException: error in opening zip file
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.(ZipFile.java:214)
at java.util.zip.ZipFile.(ZipFile.java:144)
at java.util.jar.JarFile.(JarFile.java:152)

調べてみたらにpropertiesファイルが直接設定されているのが問題だった。
antはに設定されたJarファイルをZipで操作するようで、その際にpropertiesファイルがあるとエラーになってしまう。

具体的に言うと、もともとこう書いていた。

<path id="run.classes">
    <path path="${classes}"/>
    <fileset dir="${lib.dir}">
        <include name="**/*.jar"/>
    </fileset>
</path>

<path id="conf">
    <fileset dir="${resource.dir}">
        <include name="**/*.properties"/>
    </fileset>
</path>

これではconfを参照した際にZipExceptionが起きてしまう。
これをこう書くとうまくいった。

<path id="run.classes">
    <path path="${classes}"/>
    <fileset dir="${lib.dir}">
        <include name="**/*.jar"/>
    </fileset>
</path>

<path id="conf">
    <pathelement location="${resource.dir}"/>
</path>

POIを使ってExcelの不要な名前定義を削除する

以前vbaを使った参照できなくなった名前定義の削除を作ったが、
お粗末なものだったのと、JavaExcelを操作する練習も兼ねて
Apache POIを利用したものを作成してみた。

JavaのライブラリでExcelを扱うものはJExcelApiApache POIがある。

今回はApache POIを使って作成した。
# というか最初はJExcelApiで作っていたのだが不要な(参照できない)名前定義を読み込めないようなので断念した。

実装した仕様としては下記。
・エクセルの名前定義を読込み、参照できないもの(#REF)を削除して、ファイルを保存する。
・名前定義を削除しない場合はファイルの保存を行わない。
・ディレクトリ指定をすると、xls拡張子のファイルを探し出し、処理を行う。(サブディレクトリを含む)
・削除した名前定義を標準出力してログとする。


で、結局簡単にできた。
vbaで作成した時と違うのはどうもPOIでは別ファイルへの参照はnullになってしまうようだ。
# vbaで"Document ant Setting"のパスを意識して削除していたが、そこがnull。
# なので特に名前定義の参照先を意識せずに"参照できなかったら削除"というロジックになっている。


まぁ使いたいだけの人には不要な説明はソースを配布することで置いておいて、
実行の仕方について説明する。

1. 名前定義削除JarファイルをDL。ここからDLできます。
2. Apache POIをDL。最新は3.8だが、3.7を使用。
3. ファイル操作で使用するApache Commons IOライブラリ。ver.2.0.1。
# また、このプログラムは現時点で最新のJava7で作成されているため、JREのVersionUpも必要かもしれない。


上記3つのJarファイルをクラスパスに入れて
excel.poi.ExcelRmRefNamesPoiを実行する。
その際に引数として、処理させたいディレクトリパスを指定する。
# 注意点:Windowsの場合はパス区切り文字を円マーク"\"ではなく、スラッシュ"/"へ変換してください。

java -cp "ExcelRmRefNames.jar;poi-3.7-20101029.jar;commons-io-2.0.1.jar" excel.poi.ExcelRmRefNamesPoi [TargetDir]

また、読み込み専用ファイルやPOIで読み込めないファイルであった場合は失敗し、エラーログを吐いたのち、そのまま次のファイルを続けて処理する。
使用にあるとおりサブディレクトリも全て走査し.xlsファイルを処理する。
注意:必ずバックアップを取った後に実行することをお勧めします。

ライセンスは、GPLとします。
# ライセンスについて触れたのは初めてのことなのでなにか不備があるかもしれません。
# コメントで指摘してもらえると助かります。