読者です 読者をやめる 読者になる 読者になる

kagamihogeの日記

kagamihogeの日記です。

JBoss AS 7.1 + EJB 3.1 + Arquillian動かすところまで

Java JBoss

やったこと

JBoss Tools 4.1のインストール

Help -> Eclipse Marketplaceで「jboss tools」で検索する。

JBoss Tools (Kepler)をインストールする。

JBoss ASサーバをEclipseから起動する設定

Servers -> New で、まぁこんな感じでテキトーに。


プロジェクトはなんもAddしなくてもいいんで、JBossが立ち上がれば一先ずOK

プロジェクトの作成

EJB3.1動かすためのMavenとか、Arquillianの設定ファイルとか、イチから作るのは何気にしんどい(てか知識ゼロでやるのは絶望的にめんどい) ので、JBoss CentralからJavaEE Web Projectで雛形をさくっと作ってもらう。

下記スクショはCreate a blank projectにチェックを入れている。デフォルトのままにしておけば、JSFやらEJBやらJPAやらのサンプルコードも含まれる。今回はソースコードはカラの状態のプロジェクト作りたいんで、コレにチェック入れている。
なお、Target Runtimeは未選択にしておく。

プロジェクト名とかパッケージ名とかはとりあえずデフォを使う。

Maven関連。ここもそのまま。

Finishするとプロジェクトの作成と依存性解決などなどが始まり、やや時間がかかる。終了すれば準備OK。

EJB 3.1のコード書く
package org.jboss.tools.examples.ejb;

import javax.ejb.Stateless;

@Stateless
public class HogeEJB {
    public int add(int a, int b) {
        return a + b;
    }
}

これだけかよって感じですが、サンプルなんでとりあえずコーディングはこれでおわり。

EJB 3.1のユニットテスト

でもEJBとか動かすのチョーめんどうなんでしょう? って俺もついさっきまで思ってたわけですが。とりあえずは、論よりコードってことで、おもむろにJUnitを書く。

package org.jboss.tools.examples.ejb;

import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;

import javax.inject.Inject;

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

@RunWith(Arquillian.class)
public class HogeEJBTest {
    @Deployment
    public static Archive<?> createTestArchive() {
        return ShrinkWrap.create(WebArchive.class, "test.war")
                .addClasses(HogeEJB.class)
                .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
    }
    
    @Inject
    HogeEJB hogeEJB;
    
    @Test
    public void testHogeEJBAdd() {
        assertThat(3, is(hogeEJB.add(1, 2)));
    }
}

これを実行するまえに、Serversからjbossを立ち上げておく。デプロイはしない。


グリーンになりました。

というわけで、EJBユニットテストでカンタンに動せるようになってました(驚愕) このサンプルみたいにEJBがナンもしないとイマイチ恩恵感じないだろうけど、実際にはJPAやらなんやらゴチャゴチャと絡むのがJ2EEなわけで。そこを、JUnitでカンタンに動かせるようになっちゃってるのは本当にすごいっす。

ぐぐって色々調べてるとすでにCIで走らせるところもあるみたい。適当なサーバにJBoss入れて(Glassfishでもいいっぽいけど)そこでArquillianを走らせる、という感じ。

ハマりどころなど
  • ArchiveExportException
org.jboss.shrinkwrap.impl.base.exporter.zip.JdkZipExporterDelegate$1 call
WARNING: Exception encountered during export of archive
org.jboss.shrinkwrap.api.exporter.ArchiveExportException: Failed to write asset to output: /WEB-INF/lib/arquillian-testenricher-ejb.jar

Arquillianのドキュメントろくすっぽ読まずにやってたために無駄にハマッた。ざっくりいえば、Arquillianはwar or ear作ってすでに動いてるAPサーバにデプロイしてJUnit走らせる、を自動的にやってくれる。んで、サーバが動いていなければ当然デプロイに失敗する。というか、warを作ったもののそれをコピペしにいく場所が見つからない―だからArchiveExportExceptionなのだけど―ので、当然失敗する。

  • NullPointerException
java.lang.NullPointerException
	at org.jboss.tools.examples.ejb.HogeEJBTest.testHogeEJBAdd(HogeEJBTest.java:30)
(以下省略)

上記のテストコードでいうと、HogeEJB hogeEJBへのインジェクションが失敗する。これは、下記のようにbeans.xmlが無くてCDIの設定が効いてないために起こる。詳しくはCDIでぐぐる。

                .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
  • Could not create new instance
java.lang.RuntimeException: Could not create new instance of class org.jboss.arquillian.test.impl.EventTestRunnerAdaptor

プロジェクト -> Maven -> Select Maven Profiles.. をチェックする。下記スクショのように、

  1. arq-jbossas-remoteにはチェックが有る
  2. arq-jbossas-managedにはチェックが無い


が正しい。両方にチェックが入っていると、上記の例外が発生する。よくわかってなくて申し訳ないが、名称的にもどっちかだけ使うもんなんでしょうね。

さいごに

Arquillianは、jar吐いてソレ実行とかのテストも出来るようで実際スゴイ。