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

Gradle で weld-se を使う

Java

はじめに

Gradle の Applicationプラグインで weld-se を使う場合、CDI管理の Bean の検索が beans.xml のあるファイルシステム上のパスを起点に行われてしまうため注意が必要。

CDI in Java SE (CDI2.0)

CDI 2.0 では Java EE 以外に、Java Standard Edition (SE) 向けのサポートが追加されている。

Weld では以前から Weld-se として提供されていたが、(準)標準API として javax名前空間で利用できるようになる。

CDI 2.0 仕様は EDR1 の状態であるが、weld のアルファ版で既に利用できる。

Main クラスの作成

エントリポイントの Main クラスを作成する。

package example;

import javax.enterprise.inject.spi.CDI;

public class Main {

    public static void main(String[] args) {
        try (CDI<Object> cdi = CDI.getCDIProvider().initialize()) {
            Application app = cdi.select(Application.class).get();
            app.run();
        }
    }
}

CDI プロバイダを取得して初期化している。

Application クラスと Serviceクラスの作成

HelloService を DI 対象とする Application クラスを作成する。

package example;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sjwa.app.AccountService;
import sjwa.app.SignUpReq;
import sjwa.domain.Account;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

@ApplicationScoped
public class Application {
    private static final Logger log = LoggerFactory.getLogger(Application.class);

    @Inject HelloService helloService;

    public void run() {
        String greeting = helloService.greeting();
        log.info(greeting);
    }

}

HelloService は単に Hello!! を返却。

package example;

import javax.enterprise.context.Dependent;

@Dependent
public class HelloService {
    public String greeting() {
        return "Hello !!";
    }
}

beans.xml

src/main/resources/META_INF/ 以下に beans.xml を作成する。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
       version="2.0" bean-discovery-mode="annotated">
</beans>

build.gradle

依存には weld-se-core を指定する。

jandex を追加することで、起動時の bean discovery が高速化される模様。

apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'application'

sourceCompatibility = 1.8
targetCompatibility = 1.8
version = '1.0'

mainClassName = "example.Main"

repositories {
    jcenter()
}

dependencies {
    compile 'org.slf4j:slf4j-api:1.7.7'
    compile 'ch.qos.logback:logback-classic:1.1.3'
    compile 'org.jboss.weld.se:weld-se-core:3.0.0.Alpha14'
    compile 'org.jboss:jandex:2.0.1.Final'
    testCompile 'junit:junit:4.12'
}

Gradle では、resources 以下に配備した beans.xmlbuild/resources/main/META-INF/beans.xml に入り、コンパイル後のクラスファイルとはファイルシステム上別管理となる。

weld−se では bean discovery がファイルシステム上で beans.xml のあるディレクトリを起点に行われるため、このままだとweldが CID 管理対象の bean を発見できない。

色々やり方はあるが、以下のようにリソースファイルを classes 配下にコピーしてしまうのが簡単。build.gradle に以下を追加する。

task copyResources(type: Copy) {
    from "${projectDir}/src/main/resources"
    into "${buildDir}/classes/main"
}
processResources.dependsOn copyResources

こちらを参照。

discuss.gradle.org

実行

$ ./gradlew clean build run
Hello !!



CDI - Dependency Injection in Java EE 6 (German Edition)

CDI - Dependency Injection in Java EE 6 (German Edition)