kagamihogeの日記

kagamihogeの日記です。

GlassFish 4でArquillianうごかす

やったこと

Mavenプロジェクトの作成

archetypeでwebapp-javaee7を選んでプロジェクトを作る。

テスト対象クラスの作成

Getting Started · Arquillian GuidesのコピペだけどJavaのフツーのクラスをつくる。

package arquilliantutorial;

import java.io.PrintStream;

public class Greeter {
    public void greet(PrintStream to, String name) {
        to.println(createGreeting(name));
    }

    public String createGreeting(String name) {
        return "Hello, " + name + "!";
    }
}
テストコードの作成

ここもほぼコピペ。1つのテストが成功して、もう1つは失敗する。

package arquilliantutorial;

import static org.junit.Assert.fail;

import javax.inject.Inject;

import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(Arquillian.class)
public class GreeterTest {

    @Deployment
    public static JavaArchive createDeployment() {
        return ShrinkWrap.create(JavaArchive.class)
            .addClass(Greeter.class)
            .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
    }
    
    @Inject
    Greeter greeter;
    
    @Test
    public void testGreet() {
        Assert.assertEquals("Hello, Earthling!",
                greeter.createGreeting("Earthling"));
            greeter.greet(System.out, "Earthling");
    }

    @Test
    public void testCreateGreeting() {
        fail("Not yet implemented");
    }

}
pom.xmlにdependency追加

javaee-web-abiは置いておくとして。

  • Arquillian API
  • Arquillian-JUnitインテグレーション
  • Embedded GlassFishコンテナアダプタ
  • Embedded GlassFish All-In-One

の依存性を追加する。
下記はembeddedの場合。

<dependencies>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-web-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.arquillian</groupId>
        <artifactId>arquillian-bom</artifactId>
        <version>1.0.0.Final</version>
        <scope>import</scope>
        <type>pom</type>
    </dependency>
    <dependency>
        <groupId>org.jboss.arquillian.junit</groupId>
        <artifactId>arquillian-junit-container</artifactId>
        <version>1.0.0.Final</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.arquillian.container</groupId>
        <artifactId>arquillian-glassfish-embedded-3.1</artifactId>
        <version>1.0.0.CR4</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.glassfish.main.extras</groupId>
        <artifactId>glassfish-embedded-all</artifactId>
        <version>4.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

下記はremoteの場合。
arquillian-glassfish-embedded を arquillian-glassfish-remote にする。glassfish-embedded-allは要らない。使い分ける場合、profileで切替するらしい。

<dependencies>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-web-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.arquillian</groupId>
        <artifactId>arquillian-bom</artifactId>
        <version>1.0.0.Final</version>
        <scope>import</scope>
        <type>pom</type>
    </dependency>
    <dependency>
        <groupId>org.jboss.arquillian.junit</groupId>
        <artifactId>arquillian-junit-container</artifactId>
        <version>1.0.0.Final</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.arquillian.container</groupId>
        <artifactId>arquillian-glassfish-remote-3.1</artifactId>
        <version>1.0.0.CR4</version>
        <scope>test</scope>
    </dependency>
</dependencies>
動かす

embeddedの場合。JUnitのテストケースを実行する。

remoteの場合。GlassFishを起動させたあと、JUnitのテストケースを実行する。

はまりどころ

java.lang.NoSuchMethodError: org.jboss.shrinkwrap.descriptor.api.DescriptorImporter.fromString(Ljava/lang/String;)Lorg/jboss/shrinkwrap/descriptor/api/Descriptor;

エラーログはこんな感じ。

java.lang.RuntimeException: Could not create new instance of class org.jboss.arquillian.test.impl.EventTestRunnerAdaptor
	at org.jboss.arquillian.test.spi.SecurityActions.newInstance(SecurityActions.java:160)
	(中略)
Caused by: java.lang.NoSuchMethodError: org.jboss.shrinkwrap.descriptor.api.DescriptorImporter.fromString(Ljava/lang/String;)Lorg/jboss/shrinkwrap/descriptor/api/Descriptor;
	at org.jboss.arquillian.config.impl.extension.ConfigurationSysPropResolver.resolveSystemProperties(ConfigurationSysPropResolver.java:55)
	(中略)

MavenのDependency Hierarchyが上手くいっていないために発生する。Arquillian APIとEmbedded GlassFishコンテナアダプタのバージョンが噛みあっていないとこのエラーが出る。2013/10/8現在、Arquillian APIの最新バージョンは1.1.1.FinalなんだけどGlassFishコンテナアダプタ1.0.0.CR4はソレに対応していないのだと思われる。ただし、GlassFishコンテナアダプタ3.1でもGlassFish4で動くので、一応問題は無い。参考⇒Arquillian Container GlassFish 1.0.0.CR4 Released · Arquillian Blog

java.lang.NoClassDefFoundError: org/glassfish/embeddable/GlassFishException

エラーログはこんな感じ。

java.lang.RuntimeException: Could not create a new instance of class org.jboss.arquillian.test.impl.EventTestRunnerAdaptor see cause.
	at org.jboss.arquillian.test.spi.SecurityActions.newInstance(SecurityActions.java:170)
        (中略)
Caused by: java.lang.NoClassDefFoundError: org/glassfish/embeddable/GlassFishException
	at java.lang.Class.getDeclaredConstructors0(Native Method)
        (中略)

glassfish-embedded-allが無いとこうなる。

Could not connect to DAS on: http://localhost:4848

remoteの場合、GlassFishを起動していないとこんな感じのエラーになる。

10 08, 2013 8:18:47 午後 org.jboss.arquillian.container.glassfish.CommonGlassFishManager start
重大: Could not connect to DAS on: http://localhost:4848 | Connection refused: connect