Jakarta EEのApplicationScopedアノテーションのメモ。
アプリケーション全体でひとつのインスタンスだけが共有されるオブジェクト(アプリケーション終了時に破棄されるオブジェクト)はApplicationScopedで作成できる。
ApplicationScopedを使うには、build.gradleのdependenciesに以下のライブラリーを指定する。
dependencies { compileOnly 'org.glassfish.jersey.core:jersey-server:3.1.5' compileOnly 'jakarta.enterprise:jakarta.enterprise.cdi-api:4.0.1' }
import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped public class MyApplicationResource { @PostConstruct public void construct() { // フィールドの初期化 } public void 操作() { 〜 } @PreDestroy public void destroy() { // フィールドのオブジェクトのクローズ } }
クラスにApplicationScopedアノテーションを付ける。
必要に応じて、生成時に呼ばれるPostConstructや終了時に呼ばれるPreDestroyのメソッドを実装する。
PostConstructやPreDestroyアノテーションを付けたメソッドでは、IOException等のチェック例外をthrows宣言することは出来ない。[2024-02-22]
チェック例外をthrows宣言すると、デプロイ時に以下のようなエラーが発生する。
> asadmin deploy --force=true example-glassfish7.war remote failure: Error occurred during deployment: Exception while deploying the app [example-glassfish7] : org.glassfish.apf.AnnotationProcessorException: The lifecycle method [construct] must not throw a checked exception. Related annotation information: Annotation [@jakarta.annotation.PostConstruct()] on annotated element [public void com.example.glassfish7.server.MyApplicationResource.construct() throws java.io.IOException] of type [METHOD]. Please see server.log for more details. Command deploy failed.
ApplicationScopedアノテーションを付けたリソースクラスでは、引数を持つコンストラクターを定義できないようだ。[2024-02-22]
したがって、他のリソースをインジェクトする場合は、(コンストラクターインジェクションでなく)フィールドインジェクションを使う。
import jakarta.inject.Inject;
@ApplicationScoped public class MyApplicationResource { @Inject private OtherResource otherResource; 〜 }
ApplicationScopedのオブジェクトを使う側は、インジェクトする。
import jakarta.inject.Inject;
@Path("/resource3") public class Resource3 { @Inject private MyApplicationResource myResource; @GET @Produces(MediaType.TEXT_PLAIN) public String hello() { myResource.操作(); return 〜; } }