(無駄に大仰な)ズンドコキヨシ with AngularJS 2, Java EE 7(JAX-RS, CDI)
ミニマムな方向はいろいろ出ているので、大仰な方向に走ってみました。
ズンドコキヨシまとめ
概要
AnguarJSからREST APIを叩いて「ズン」または「ドコ」の取得を繰り返し、「ズンズンズンズンドコ」が並んだら「キ・ヨ・シ!」と表示します。
仕様
サーバ側
JAX-RSリソース/webapi/zundoko
へGETアクセスするとJSONが返る。
JSONの内容はこんな感じにします。
{
zundoko: 'zun'
}
または
{
zundoko: 'doko'
}
毎回異なる結果が返るという、全然RESTじゃない仕様
クライアント側
zundoko
ディレクティブを作成する。
nミリ秒ごとにズンドコリソースへアクセスし、取得結果を表示する。
直近5つが例の並びなら「キ・ヨ・シ!」と表示する。
せっかくなのでi18n化
プロジェクト準備~
このプロジェクトで使うものです。
項目 | 使うもの |
---|---|
JDK | Oracle JDK 8 |
統合開発環境 | NetBeans |
依存性管理/ビルドツール | Maven |
Javaフレームワーク | Java EE 7 |
Java EEサーバ | Glassfish 4.1.1 |
Javaテストツール | junit、Arquillian |
JavaScriptフレームワーク | AngularJS 2 |
JavaScriptテストツール | Google Chrome |
プロジェクト開始〜
mavenを使ってArquillian1のサンプルから開始
% mvn archetype:generate \
-DarchetypeArtifactId=javaee7-arquillian-archetype \
-DarchetypeGroupId=org.javaee-samples \
-DinteractiveMode=false -DgroupId=com.example -DartifactId=zundoko
テスト用embeded glassfishのポート番号を変えます。デフォルトだとバッティングすることがあるので。
src/test/resources/arquillian.xml
<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.org/schema/arquillian"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://jboss.org/schema/arquillian
http://www.jboss.org/schema/arquillian/arquillian_1_0.xsd">
<container qualifier="glassfish-embedded" default="true">
<configuration>
<property name="bindHttpPort">18181</property>
</configuration>
</container>
</arquillian>
とりあえず雛形のテストを実行してみたり。ここでエラーだと、環境的に何か足りないかもです。
% mvn -Pglassfish-embedded-arquillian test
ごいごいとサーバ側を実装
ZunDokoはEnumで
ZunとDokoはEnumにしてみました。せっかくEnumにしたので、色気も出してvalueOf(boolearn)
なんてのを追加。
src/main/java/com/example/ZunDokoEnum.java
public enum ZunDokoEnum {
zun,
doko;
public static ZunDokoEnum valueOf(boolean b) {
return b ? ZunDokoEnum.zun : ZunDokoEnum.doko;
}
}
ZunDokoインスタンス
JAX-RSから出力するクラスを作ります。
src/main/java/com/example/ZunDoko.java
public class ZunDoko {
private ZunDokoEnum zunDoko;
// コンストラクタやらsetterやらgetterやら
}
ZunDokoインスタンスの生成はファクトリクラスで
二分の一の確率でズン・ドコを生成するファクトリクラスを作りました。
なぜファクトリクラスを使うかといえば、ズンまたはドコを生成するという複雑なビジネスロジック をここへ閉じ込めるためです。
src/main/java/com/example/ZunDokoFactory.java
public class ZunDokoFactory {
private static final ZunDokoFactory SELF = new ZunDokoFactory();
private final Random random = new Random();
public static ZunDoko createZunDoko() {
return SELF.create();
}
private ZunDoko create() {
return new ZunDoko(ZunDokoEnum.valueOf(random.nextBoolean()));
}
}
テストも書きましょー。
src/test/java/com/example/ZunDokoFactoryTest.java
public class ZunDokoFactoryTest {
/**
* Test of createZunDoko method, of class ZunDokoFactory.
*/
@Test
public void testCreateZunDoko() {
System.out.println("===>>> createZunDoko");
// 略
}
}
あえてCDIを使う
ZunDokoクラスのインスタンスは、CDIを使ってクラス外から注入することにします。
インスタンス生成はファクトリクラスに任せたので、ファクトリクラスを呼ぶCDIプロデューサを作ります。
クオリファイアを作成
DIコンテナが迷わずプロデューサを使ってくれるように、目印となるクオリファイアも作ります。
src/main/java/com/example/ZunDokoQualifier.java
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface ZunDokoQualifier {
}
プロデューサを作成
リクエストごとにズンドコインスタンスを生成するように、リクエストスコープにしてます。
src/main/java/com/example/ZunDokoProducer.java
import javax.enterprise.inject.Produces;
@RequestScoped
public class ZunDokoProducer {
@Produces
@ZunDokoQualifier
public ZunDoko produceZunDoko() {
return ZunDokoFactory.createZunDoko();
}
}
CDIのテスト
Arquillianを使ってテストします。
リアルにJava EEサーバが立ち上がって重たいので、CDI-Unit2を使いたいところですが、依存性でArquillianと喧嘩するので混ぜないでおきます。
ArquillianではいろいろなJava EEサーバを使えます3。ここでは慣れたGlassfish embeddedを使いました。
pom.xml
のglassfish-embedded-arquillian
プロファイルの内容を変更します。
pom.xml
<profile>
<id>glassfish-embedded-arquillian</id>
<dependencies>
<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-glassfish-embedded-3.1</artifactId>
<version>${version.arquillian_glassfish_embedded}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.main.extras</groupId>
<artifactId>glassfish-embedded-all</artifactId>
<version>${version.glassfish}</version>
<scope>test</scope>
</dependency>
</dependencies>
</profile>
テストクラスを作成します。
Java EEサーバにデプロイする必要分だけwarファイルを@Deployment
アノテーションをつけたメソッドで作成します。
@Inject
、@ZunDokoQualifier
を付けることで、プロデューサからZunDokoクラスのインスタンスが注入されます。
src/test/java/com/example/inject/ZunDokoProducerTest.java
@RunWith(Arquillian.class)
public class ZunDokoProducerTest {
@Deployment
public static Archive<?> createDeployment() {
final WebArchive war = ShrinkWrap.create(WebArchive.class,
ZunDokoProducerTest.class.getSimpleName() + ".war")
.addClass(ZunDokoProducer.class)
.addClass(ZunDokoFactory.class)
.addClass(ZunDoko.class);
return war;
}
@Inject
@ZunDokoQualifier
ZunDoko instance;
// 略
}
JAX-RSリソースの作成
CDIコンテナにのせるために@Dependent
をつけます。
src/main/java/com/example/ZunDokoResource.java
package com.example;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Dependent
@Path("zundoko")
public class ZunDokoResource {
@Inject
private ZunDoko zunDoko;
@GET
@Produces(MediaType.APPLICATION_JSON)
public ZunDoko getZunDoko() {
return zunDoko;
}
}
JAX-RSリソースのテスト
Arquillianを使います。
@Deployment
アノテーションにtestable = false
引数を与えて、Webクライアントとして動作するテストにします。
setUp
メソッド内でWebクライアントを初期化しています。
src/test/java/com/example/ZunDokoResourceTest.java
@RunWith(Arquillian.class)
public class ZunDokoResourceTest {
@Deployment(testable = false)
public static Archive<?> createDeployment() {
// 略
}
@ArquillianResource
private URI base;
private WebTarget target;
@Before
public void setUp() {
final Client client = ClientBuilder.newClient();
target = client.target(base)
.path("webapi")
.register(ZunDoko.class);
}
@Test
public void testGetZunDoko() {
System.out.println("===>>> getZunDoko");
// 略
}
}
つづく。。。
長くなりましたので、【クライアント側編】へ続きます。
ソース全体はこちらに置いています。
https://github.com/sengokyu/zundoko