Play framework + Scala でリクエストが返らずに嵌った

環境

  • Play framework 1.2.4
  • Scala Module 0.9.1 (Scala 2.8.1)

ある時を境にどのURLにリクエストを投げても、
ずっと読み込み中のままいつまでたってもレスポンスがかえってこなくなった。

ログを見ても以下で止ったままで何も出力されない。

...

Traversing /home/kiris/project/sample1/tmp/generated/views.defaults.html.welcome.scala
Traversing /home/kiris/project/sample1/tmp/generated/views.html.main.scala
API phase took : 1.759 s

原因がさっぱりわからないのでThread Dumpだしてみた。

% jps
19264 Jps
18730 Server

% jstac 18730
"Thread-3" prio=10 tid=0x00007fe8d87ff000 nid=0x6ba9 waiting for monitor entry [0x00007fe8dc3d7000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at sbt.BufferedLogger.doBufferableIf(BufferedLogger.scala:87)
	- waiting to lock <0x00000000f6ec6e78> (a sbt.Logger$$anon$1)
	at sbt.BufferedLogger.doBufferable(BufferedLogger.scala:85)
	at sbt.BufferedLogger.log(BufferedLogger.scala:75)
	at sbt.Logger$class.error(Logger.scala:74)
	at sbt.AbstractLogger.error(Logger.scala:8)
	at sbt.BasicIO$$anonfun$processErrFully$1.apply(ProcessImpl.scala:51)
	at sbt.BasicIO$$anonfun$processErrFully$1.apply(ProcessImpl.scala:51)
	at sbt.BasicIO$.readFully$1(ProcessImpl.scala:73)
    ...

どうもsbtからエラーログを出力する所で止ってしまっているっぽい。
出力しようとしている文字列がわかれば原因が特定できそうなので、
Eclipse PluginのMemory Analyzer(http://eclipse.org/mat/)を使ってヒープ解析。

f:id:kiris60:20120124131221p:plain
Thread-3で検索かけて調べてみると、どうもJPAとAnorm共存させていたせいか、
JPA側のアノテーションプロセッサの処理でコケてたっぽい。怪しい行を削除したら動いた。

まとめ

  • PlayでEnsimeのデバッガーを動かせるようしておくべき
  • あけましておめでとう

Scala 2.9.1 + sbt 0.11.2 でpicture-showをインストール

picture-showについてはこちらを参照。

[error] {file:/home/iwanaga/repos/picture-show.git/}PictureShow Conscript/*:update: sbt.ResolveException: unresolved dependency: org.scala-tools.sbt#launcher-interface;0.7.4: not found
[error] Total time: 31 s, completed 2011/12/16 12:16:11

のように怒られて、picture-showがインストールできない人向け。
ローカルで依存関係を解決しても、conscriptでコケるのでforkしてしまった。

% git clone git://github.com/kiris/picture-show.git
% cd picture-show
% sbt publish-local
% cs kiris/picture-show

Javaでシングルトンの遅延初期化

もっとも簡単なシングルトンの例

@ThreadSafe
final class Singleton {
  public static final Singleton INSTANCE = new Singleton();
  private Singleton() {}; 
}

staticフィールドの初期化は、そのクラスに初めてアクセスされた(≠クラスがロードされた)時に行なわれる。

そこで次の例では、インスタンスが必要になる時まで生成を遅らせている。

@ThreadSafe
final class Singleton {
  private static Singleton instance;
  private Singleton() {}; 
  public static synchronized Singleton getInstance() {
    if(instance == null) { 
      instance = new Singleton();
    }
    return instance;
  } 
}

確かにインスタンスの生成は遅らせされたが、getInstanceを実行する度にスレッドの同期が行なわれるのはうれしくない。

そこで登場するのが悪名高きdouble-checked locking pattern。
アウトオブオーダー書き込みのせいで、不完全なインスタンスが別スレッドに公開されることがあるので使ってはいけない。

@NotThreadSafe
final class Singleton {
  private static Singleton instance;
  private Singleton() {}; 
  public static Singleton getInstance() {
    if(instance == null) { 
      synchronized(Singleton.class) {
        if (instance == null) {
          instance = new Singleton();
        }
      }
    }
    return instance;
  }
}

Java 5.0からは変数にvolatile修飾子を付けることでこれを防げる。
以下はJava 5.0以降でのみ安全なdouble-checked locking pattern。

@ThreadSafe
final class Singleton {
  private static volatile Singleton instance;
  private Singleton() {}; 
  public static Singleton getInstance() {
    if(instance == null) { 
      synchronized(Singleton.class) {
        if (instance == null) {
          instance = new Singleton();
        }
      }
    }
    return instance;
  }
}

そして、最後に示すのがInitialization-on-demand holder idiom。
LazyHolderの初期化は、getInstance()が実行されるまで行なわれないので、
スレッドセーフかつ高速なシングルトンの遅延初期化が実現できる。

@ThreadSafe
public class Singleton {
  private Singleton() {}
 
  private static class LazyHolder {
    public static final Singleton INSTANCE = new Singleton();
  }
 
  public static Singleton getInstance() {
    return LazyHolder.INSTANCE;
  }
}

refs

Scala 2.9.1 + Ensime 0.7.6 + SBT 0.11.0 でensime-sbtが動かない

エラー内容

        ...

	==== Scala-Tools Maven2 Snapshots Repository: tried

	  http://scala-tools.org/repo-snapshots/org/scala-tools/sbt/sbt_2.9.1/0.7.4/sbt_2.9.1-0.7.4.pom

		::::::::::::::::::::::::::::::::::::::::::::::

		::          UNRESOLVED DEPENDENCIES         ::

		::::::::::::::::::::::::::::::::::::::::::::::

		:: org.scala-tools.sbt#sbt_2.9.1;0.7.4: not found

		::::::::::::::::::::::::::::::::::::::::::::::



:: USE VERBOSE OR DEBUG MESSAGE LEVEL FOR MORE DETAILS
unresolved dependency: org.scala-tools.sbt#sbt_2.9.1;0.7.4: not found
Error during sbt execution: Error retrieving required libraries
  (see /Users/euler/.sbt/boot/update.log for complete log)
Error: Could not retrieve sbt 0.7.4

Process sbt exited abnormally with code 1

ensime-sbt-project-dir-pに"/project"をセットするか、空の/project/build.propertiesを作成すれば良いっぽい。

ref https://github.com/aemoncannon/ensime/issues/193

Ubuntu 11.10で開き方にemacsclientを追加する

mkdir -p ~/.local/share/applications
cat > !$/emacsclient.desktop <<EOF
[Desktop Entry]
Version=1.0
Name=Emacsclient
GenericName=Text Editor
Comment=View and edit files
MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
Exec=/usr/bin/emacsclient -c %F
Icon=/usr/share/icons/hicolor/scalable/apps/emacs23.svg
Type=Application
Terminal=false
Categories=Utility;Development;TextEditor;
StartupWMClass=Emacsclient
EOF

refs

Lombokを使えばJavaでScalaのval(っぽいもの)が使えるんだぜ!

という煽りでしかないエントリー書こうと思ってたけど、
なんかもう僕の中で満足しちゃったので、
先日、社内勉強会の発表に使った資料を貼ってお茶濁し。

なれそめ

kiris:
招待してくんねぇかなー。「はてなブログβ使いたい」とか呟くと @nitro_idiot あたりが招待してくんねぇかなー。
nitro_idiot:
え、まだはてなブログ使ってないんですかっ!??
kiris:
えー、ほら俺はてな民とかそういうのと違うからー
kiris:
招待きた。twitterすごい。

 

はてなブログ始めました。

当分はメモ帳代りかなー。