Kuchitama Tech Note

はてな記法がいつまでたっても覚えられないので、はてなダイアリーからマークダウンが使えるこっちに引っ越してきました。

AWS LambdaでScalaを使ってみたんだが

こんな記事を書きました

qiita.com

とても気になっている問題があります。

それが、AWS Lambda Deployment Limits です。

docs.aws.amazon.com

項目 デフォルトの制限
Lambda 関数デプロイパッケージのサイズ(.zip/.jar ファイル) 50 MB
リージョンあたりの、アップロードできるすべてのデプロイパッケージの合計サイズ 75 GB
デプロイパッケージ(非圧縮 zip/jar サイズ)に圧縮できるコード/依存関係のサイズ 250 MB

こういう制限があるけど、Scalaコードは、Scalaの標準ライブラリとかjarに含まれるはずなので、Javaで書くよりもjarのサイズは大きくなるはず。 この影響がどれぐらいかというのを調べてみました。

実験

とりあえず、シンプルなサンプルとして、Serverless Frameworkで create しただけのjarのサイズを見てみます。 Serverless Frameworkについては、Web+DB PRESS vol.95 で取り上げられてたので、読むといいと思います。

WEB+DB PRESS Vol.95

WEB+DB PRESS Vol.95

$ sls create -t aws-scala-sbt
$ sbt assembly
$ ll target/scala-2.11/hello.jar
-rw-rw-r-- 1 k2 k2 15M 10月 29 00:58 target/scala-2.11/hello.jar

ということで、 15MB のjarができました。 この時点で既に 50MBの 30% を消費しています。

ちなみに、冒頭の記事で最終的に作成した、依存関係に skinny-json を追加したバージョンのjarのサイズを見てみます。

qiita.com

$ sbt assembly
$ ll target/scala-2.11/hello.jar
-rw-rw-r-- 1 k2 k2 37M 10月 31 12:48 target/scala-2.11/hello.jar

なんと、 37MB まで増えました。

実に上限の 74% です。

もう少し調べます。

AWS Lamdaでは、zip/jarの展開後の容量も制限があって、250MBに収まっている必要があります。

$ mv hello.jar hello.zip
$ unzip hello.zip

$ du -hcd 2    
15M     ./models
24K     ./hello
108K    ./com/thoughtworks
17M     ./com/amazonaws
5.2M    ./com/fasterxml
22M     ./com
60K     ./skinny/util
64K     ./skinny
184K    ./mozilla
2.0M    ./software/amazon
2.0M    ./software
16K     ./META-INF/services
188K    ./META-INF/native
344K    ./META-INF
12K     ./scala/compat
20M     ./scala/reflect
720K    ./scala/sys
68K     ./scala/ref
52M     ./scala/tools
128K    ./scala/annotation
868K    ./scala/math
15M     ./scala/collection
2.3M    ./scala/xml
80K     ./scala/text
900K    ./scala/concurrent
44K     ./scala/beans
2.5M    ./scala/util
1.2M    ./scala/runtime
196K    ./scala/io
97M     ./scala
3.7M    ./org/joda
5.0M    ./org/apache
2.9M    ./org/json4s
12M     ./org
148M    .
148M    合計

skinny-jsonを追加した状態で、展開後のファイルサイズは合計148Mでした。 250MBの59.2%ですね。こちらも制限の半分を超えています。 やはり、./scalaが 97M と大変ボリュームがあります。

油断してライブラリを追加してしまうと、あっという間に上限に迫ってしまいそうです。 気持よく開発をつづけてたら、突然デプロイに失敗する危険があります。

依存関係の追加は計画的に行いましょう!!

ちなみに

aws-java-gradle テンプレートで build したzipのサイズ

$ sls create -t aws-java-gradle
$ gradle build
$ ll build/distributions/hello.zip 
-rw-rw-r-- 1 k2 k2 7.9M 10月 28 14:41 build/distributions/hello.zip

こちらは、 15.8% ですね。

Clojure+LeiningenでJavaFXプログラミング

JavaFX GUIプログラミング〈Vol.1〉をちょいちょい読み始めたので、 JavaFXアプリをClojure + Leiningenで開発する方法についてまとめる。

JavaFX GUIプログラミング〈Vol.1〉

JavaFX GUIプログラミング〈Vol.1〉

プロジェクトの作成

なにはともあれプロジェクトが無くては始まらないのでプロジェクトを作成

lein new javafx

で、とりあえずJavaFXを実行するにはjfxrt.jarが必要。 jfxrt.jarはMacOSXだと /Library/Java/JavaVirtualMachines/jdk1.7.0_09.jdk/Contents/Home/jre/lib/jfxrt.jar にあるっぽいので、そこからコピって来た。 ここのディレクトリにパスが通っていれば問題ないと思うのだけど、デフォでは通ってないっぽい。 作成したプロジェクトディレクトリ直下にlibディレクトリを作成して、その中にjfxrt.jarをコピー。

ただ、手動でjarを追加すると、基本的にLeiningenさんはjarを認識してくれないので、project.cljにjarのパスを追加してやる必要がある。 パスを通すには、:resource-pathsというプロパティを追加してやる。

これでコンパイル時のクラスパスにlib/jfxrt.jarが追加される。 ついでに、:mainを追加して、lein runしたときにちゃんと実行されるように設定しておく。

JavaFX Applicationの作成

準備が完了したので、早速プログラムの作成に入る。 Leiningenのデフォルトだと、src/javafx/core.cljが作成されているのだけど、今回は、自分でsrc/kuchitama/javafx.cljを作成し、そこに実装した。 わざわざ自分でパッケージを切った経緯については、@t_nodaさんと@bouzuyaさんのやり取りを元にしている。詳しくはこちらを参照

で、肝心のプログラムだけどこんな感じ

これで、JavaFX GUIプログラミングのP.8あたりのサンプル相当の実装になる。 こいつをベースにいじって行けば、Clojureでいろいろ出来るハズ

課題

このサンプルだと、lein uberjarを実行したときに、生成されるスタンドアローンなjarの中にjfxrt.jarが含まれないので、実はスタンドアローンで動作しない。 これを解決するには、そもそも手動でのライブラリ追加をやめてちゃんとLeiningenさんに依存関係を解決してもらえばいいのだけど、oracleはjfxrt.jarをmavenで公開していないため、それは不可能になっている。 その対応として自分でローカルのmavenリポジトリを作成して、そこにjfxrt.jarを追加するという方法がある。(参考) 確かに、これが一番オーソドックスな方法だと思うのだけど、僕はわざわざjfxrt.jarだけを管理するためにローカル環境にmavenリポジトリを作りたくはなかったので、今回手動追加という方法をとった。 でも、スタンドアローンなjarがスタンドアローンに動作しないのは詐欺もいいところなのでなんとかしたい。 どなたか、方法をご存知の方がいらっしゃればご教授ください。

勉強会デビュー in 関西Javaエンジニアの会

先週,ついに勉強会デビューしました

デビューと言っても,聴講側なのですが,

関西Javaエンジニアの会に参加させていただきました
http://atnd.org/events/15245

Javaニュース

谷本 心さん ( @cero_t )による,Javaの最新情報だったみたいです.

だったみたいというのは,実は遅刻したためほとんど聞けませんでした.

聞けた部分だけを抜き出すと,

2.0 - 1.0 = ? 何になるのか?

じつは,ちゃんと0.9にはならないということ.

1.1は2進数で表現できないそうです.

しかし,これはこのこの界隈では有名なネタ.

では,次はどうなのか

BigDecimal a = new BigDecimal(2.0);
BigDecimal b = new BigDecimal(1.1);

a = a.subtract(b);
System.out.println(a);

これも正しい回は表示されないそうです.
なぜなら,コンストラクタの引数が浮動小数点になってしまっているから.

なので,正しくは,

BigDecimal a = new BigDecimal("2.0");
BigDecimal b = new BigDecimal("1.1");

a = a.subtract(b);
System.out.println(a);

と,コンストラクタの引数を文字列で渡さなくてはならないそうです.

仕事で使うCGM 〜 Click + Guice + Mirage

連続して,谷本 心さん ( @cero_t )の発表です

Apache ClickとGoogle Guice,Amateras Mirageを組み合わせて,
業務システムを構築した実践報告です.

いろいろと訳あって自由に決定できたので,世にも珍しい組み合わせを試してみたそうです.

けっか,Apache Clickは,ライフサイクルの理解が大変だったり,
HTMLを自分で表現するのがこんなんだったりと,
あまりお気に召さなかったそうですが,
GuiceとMirageは,Seaserの代替として検討の価値ありだそうです.

ただし,実績のないフレームワークを使うときは,
最悪ソースを全部読んで自分で直すぐらいの気概は必要ということで,
私にはハードルがまだまだ高そうという印象でした.

Grails 〜InconsequentialなSpocでGeb〜

3本目は,奥清隆さん(@kiy0taka)の発表

Groovyという,JavaVM上で動作するScript言語を用いた,
Ruby on RailsライクなWebフレームワークであるGrails(グレイルズ)と,
テスト手法の紹介でした.

特に,Seleniumというテストツールは,クロスブラウザでのテストが可能で,
テストの記述に合わせて勝手にブラウザが動くのは見てて楽しかったです.

まとめ

本来は,最後に 染田 貴志 ( @tksmd )さんの発表があるはずだったのですが,残念ながらご都合が合わず中止に…

この後は懇親会になりました.

私は正直,DIコンテナってな〜にってレベルで,WebFramework祭って言われても正直ピンと来ず,
セッションを聞いてても全く分からなかったのですが,とりあえずJavaもいろいろと面白げなものがまだまだあるんだなと思いました.

内容がわからなくてもいい刺激にはなるし,懇親会も楽しいので次回も都合の許す限り参加しようと思います.
そして,しっかり自分も勉強して話す側に回りたい!

とりあえず,丁度今読んでるってこともあるので,
この勉強会にも参加されていた@irofさん(@irof) 主催の EffectiveJava読書会に参加します.
http://atnd.org/users/46692

WiiGeeの基本的な使い方

Wiiリモコンを用いて,ジェスチャ認識を行うライブラリ WiiGee をとりあえず動かしてみるサンプルです

サイトのBasicTrainingだけでは,使い方が分かりづらかったので,メモがてらソース貼っつけます.

import org.wiigee.control.WiimoteWiigee;
import org.wiigee.device.Wiimote;
import org.wiigee.event.GestureListener;
import org.wiigee.event.GestureEvent;
import java.io.IOException;

/**
 * ジェスチャを登録するクラス
 * @author Kuchitama
 */
public class WiiGeeSample implements GestureListener{
	public static WiimoteWiigee wiigee;
	public static Wiimote wiimote;
	
	public static void main(String args[]){
		wiigee = new WiimoteWiigee();
		
		try{
			wiimote = wiigee.getDevice();
		}catch(IOException e){
			e.printStackTrace();
			wiimote.disconnect();
			System.exit(1);
		}
		
		// 終了時に自動的にBluetoothを切断するように,シャットダウンフックを設定しておく
		final Wiimote wiimoteF = wiimote;
		Runtime.getRuntime().addShutdownHook(new Thread(new Runnable(){
    		public void run(){
    			wiimoteF.disconnect();
    		}
    	}));
		
		WiiGeeSample ins = new WiiGeeSample();
		
		// ジェスチャモデルの学習を行うボタンを設定する
		wiigee.setTrainButton(Wiimote.BUTTON_A);
		// ジェスチャモデルの生成を行うためのボタンを設定する
		wiigee.setCloseGestureButton(Wiimote.BUTTON_HOME);
		
		wiigee.addGestureListener(ins);
	}
	
	/**
	 * ジェスチャが認識されたときの処理
	 */
	public void gestureReceived(GestureEvent e){
		if(e.isValid()){
			System.out.println("Recognized Gesture ID is "+ e.getId());
		}else{
			System.out.println("Failed to Recognize!");
		}
	}
}

ジェスチャの登録

このプログラムを実行して,Wiiリモコンの?と?のボタンを同時押しします.
ペアリングが上手くいったら,認識させたいジェスチャをAボタンを押しながら行って下さい.
大体10〜15回ほど,「Aを押しながらジェスチャ→Aを離す」を繰り返します.

その後,Homeボタンを押すと先ほど行ったジェスチャのHMMが生成されます.

この流れを繰り返すことで複数のジェスチャを登録することが出来ます.
登録されたジェスチャは,登録順に0からIDが設定されます.

ジェスチャの認識

ジェスチャの登録が出来たら,認識を試してみてください.

Bボタンを押しながら登録したジェスチャを行います.
きちんと認識されれば,

>| Recognized Gesture ID is 0

の様に,そのジェスチャのIDが表示されます


とりあえず,ここまで
生成したモデルを保存する方法とか,読み込む方法は後日