Glassfish4でlambda式を使ってみよう、としたが・・・

先日Java SE8がついにリリースされました。

早速ラムダ式試してみました。
慣れるまでは大変そうですが、記述が簡単になるのがいいですね。

さて、今回は昨年リリースされたGlassfish4でJava8のラムダ式が使えるかどうかを試してみました。

準備

まず、Java SE8とNetBeans8をダウンロード。今回は別々にダウンロードしました。
http://www.oracle.com/technetwork/java/javase/downloads/index.html
https://netbeans.org/downloads/

Glassfishは4.0.1 build4をダウンロード
ここから4.0.1_b4のzipをダウンロードして解凍
今回はweb-profileにしました
参考

で、それぞれインストール

プロジェクト作成

NetBeans上でプロジェクトを
Maven->Webアプリケーションからプロジェクト名等は適当に入力して
サーバは上でインストールしたGlassfish4、Java EEバージョンにJava EE 7 Webを指定して新規作成。

pom.xmlmaven-compiler-pluginの設定で1.7->1.8に変更

                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
  以下略

プロジェクトのプロパティのビルド->コンパイルもJDK1.8になっていることを確認

JAX-RSの動作確認

今回はjersey(JAX-RS)を使って試したので
pom.xmlに依存性追加

        <dependency>
            <groupId>org.glassfish.jersey.ext</groupId>
            <artifactId>jersey-mvc</artifactId>
            <version>2.5.1</version>
            <scope>provided</scope>
        </dependency>

リソースクラス

@javax.ws.rs.Path("demo")
public class DemoAction {

    @javax.ws.rs.GET
    @javax.ws.rs.Produces("text/plain")
    public String demo() {
        return "this is demo!";
    }
}

コンフィグクラス

@javax.ws.rs.ApplicationPath("d")
public class DemoConfig extends org.glassfish.jersey.server.ResourceConfig {

    public DemoConfig() {
        register(DemoAction.class);
    }
}

これで
http://localhost:8080/[プロジェクト名]/d/demo
を開くと「this is demo!」と表示されるはず

ここまででJAX-RSの動作確認はひとまずOK

Java8 Stream APIの確認

ラムダ式の確認の前にJava8自体の動作確認
DemoActionを次のように書き換えます

    public String demo() {
        java.util.List<Integer> list = java.util.Arrays.asList(1, 2, 3, 4, 5);
        long count = list.stream().collect(java.util.stream.Collectors.counting());
        return "this is demo! count=" + count;
    }

http://localhost:8080/[プロジェクト名]/d/demo
を開くと「this is demo! count=5」と表示されるはず

ラムダ式の動作確認

本題です

DemoActionを次のように書き換えます

    public String demo() {
        java.util.List<Integer> list = java.util.Arrays.asList(1, 2, 3, 4, 5);
        long count = list.stream().filter(i -> i < 2).collect(java.util.stream.Collectors.counting());
        return "this is demo! count=" + count;
    }

起動時に次のようなエラーが出ました

重大:   Exception while visiting WEB-INF/classes/demo/DemoAction.class of size 2189
java.lang.ArrayIndexOutOfBoundsException: 52264
	at org.objectweb.asm.ClassReader.readClass(ClassReader.java:2015)
	at org.objectweb.asm.ClassReader.accept(ClassReader.java:469)
	at org.objectweb.asm.ClassReader.accept(ClassReader.java:425)
	at org.glassfish.hk2.classmodel.reflect.Parser$5.on(Parser.java:359)
	at com.sun.enterprise.v3.server.ReadableArchiveScannerAdapter.handleEntry(ReadableArchiveScannerAdapter.java:165)
	at com.sun.enterprise.v3.server.ReadableArchiveScannerAdapter.onSelectedEntries(ReadableArchiveScannerAdapter.java:127)
	at org.glassfish.hk2.classmodel.reflect.Parser.doJob(Parser.java:344)
	at org.glassfish.hk2.classmodel.reflect.Parser.access$300(Parser.java:67)
	at org.glassfish.hk2.classmodel.reflect.Parser$3.call(Parser.java:303)
	at org.glassfish.hk2.classmodel.reflect.Parser$3.call(Parser.java:292)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:744)

ただし、
http://localhost:8080/[プロジェクト名]/d/demo
を開くと「this is demo! count=1」と表示されるのでなんとか動いているようです