Payara icon indicating copy to clipboard operation
Payara copied to clipboard

If the Constructor Injection of an Alternative CDI bean contains a required ConfigProperty, cdI seems to fail to load. /FISH-86

Open Empressia opened this issue 4 years ago • 5 comments

Description


Alternative な CDI Bean の Constructor Injectionに、必須の ConfigProperty を含む場合、CDI の読み込みに失敗するようです。
不要な設定が強制されます。

確認用のWebアプリケーション: https://github.com/Empressia/MicroProfileConfigTest01

Expected Outcome

根拠はありませんが、設定が必須でも、
利用されないCDI Beanの場合は成功するべきだと思いました。

Current Outcome

[2020-01-26T16:49:22.961+0900] [] [�[1;91m重大] [NCLS-CORE-00026] [�[1;94mjavax.enterprise.system.core] [tid: _ThreadID=1 _ThreadName=main] [timeMillis: 1580024962961] [levelValue: 1000] [[
  Exception during lifecycle processing
org.glassfish.deployment.common.DeploymentException: CDI definition failure:Exception List with 1 exceptions:
Exception 0 :
javax.enterprise.inject.spi.DeploymentException: Deployment Failure for ConfigProperty config01 in class jp.empressia.test.microprofile_config.MicroProfileConfigTest01.Config01 Reason Microprofile Config Property config01 can not be found
	at fish.payara.microprofile.config.cdi.CDIExtension.validateInjectionPoint(CDIExtension.java:92)
(中略)
	at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: javax.enterprise.inject.spi.DeploymentException: Microprofile Config Property config01 can not be found
	at fish.payara.microprofile.config.cdi.ConfigPropertyProducer.getGenericProperty(ConfigPropertyProducer.java:110)
	at fish.payara.microprofile.config.cdi.CDIExtension.validateInjectionPoint(CDIExtension.java:77)
	... 49 more
(以下略)

Steps to reproduce (Only for bug reports)

1 -** 以下のWebアプリケーションをダウロードします。

https://github.com/Empressia/MicroProfileConfigTest01/releases

2 -** Payara Microで起動します。

3 -** ログを確認します。

Samples

https://github.com/Empressia/MicroProfileConfigTest01

Webアプリケーションのバイナリ: https://github.com/Empressia/MicroProfileConfigTest01/releases

対象の主なソースコード: https://github.com/Empressia/MicroProfileConfigTest01/blob/master/src/main/java/jp/empressia/test/microprofile_config/MicroProfileConfigTest01.java

	@Dependent
	@Alternative
	public static class Config01 {
		@Inject
		public Config01(
			@ConfigProperty(name="config01") String config01
		) {
		}
	}

Context (Optional)

Environment

  • Payara Version: 5.194
  • Edition: Micro
  • JDK Version: 11 - Oracle
  • Operating System: Windows
  • Database: none

Empressia avatar Jan 26 '20 11:01 Empressia

https://translate.google.com/translate?hl=en&sl=ja&tl=en&u=https%3A%2F%2Fgithub.com%2Fpayara%2FPayara%2Fissues%2F4455

;)

chrjohn avatar Jan 27 '20 11:01 chrjohn

MicroProfile Config 1.3 の仕様では、フィールド以外のインジェクション・ポイントで @ConfigProperty を使用した場合の動作は定義されていません。そのため、現時点で Payara Micro / Payara Server では Config プロパティのコンストラクタ・インジェクションは動作しませんが、他の MicroProfile 実装では動作する場合があります。

私が試した範囲では、ご提供いただいたサンプルは Open LibertyHelidon MP では正常に動作しているように見受けられます。


The behaviour of using @ConfigProperty on injection points without fields is not defined in the specification of MicroProfile Config 1.3. Thus, constructor injection for Config properties currently does not work on Payara Micro / Payara Server. It would work on other MicroProfile implementation(s).

As I tried, the reproducer you provided seems to be running on Open Liberty and Helidon MP successfully at least.

khasunuma avatar Feb 07 '20 05:02 khasunuma

I raised an internal issue CUSTCOM-188.

khasunuma avatar Feb 07 '20 06:02 khasunuma

ConfigPropertyを指定したコンストラクタインジェクションのPayaraでの動作について

Payara Microでも、コンストラクタインジェクションを指定したConfigPorpertyは動作しています。
実際に、サンプルでは、『microprofile-config.properties』に『config01=』の行を追加することでエラーは出なくなります。

Alternativeを指定したクラスのインジェクションについて

MicroProfile Config 1.3 の仕様では、フィールド以外のインジェクション・ポイントで @ConfigProperty を使用した場合の動作は定義されていません。

サンプルのコンストラクタインジェクション(パターン A)を、
フィールドインジェクション(パターン B)に変更しても、
エラーとなりました。

パターン A.

	@Dependent
	@Alternative
	public static class Config01 {
		@Inject
		public Config01(
			@ConfigProperty(name="config01") String config01
		) {
		}
	}

パターン B.

	@Dependent
	@Alternative
	public static class Config01 {

		@Inject @ConfigProperty(name="config01") String config01;

		public Config01(
		) {
		}
	}

問題は、Alternativeが指定されて、CDIでInjectの対象となっていないBeanの設定が、
Startupのときのチェックでエラーとなることではないでしょうか。

いずれにしても、仕様に明記されていないというのは確かだと思います。

継承されたクラスのコンストラクタインジェクションについて

CDIでInjectの対象となっていないBeanの設定としては、
継承されたクラスのコンストラクタインジェクションも同じだと思ったので、
比較のために確認しました。

CDIの以下の仕様を参照しました。 https://docs.jboss.org/cdi/spec/2.0/cdi-spec.html#bean_constructors

こちらの資料によると、以下のように記載されています。 『The application may call bean constructors directly. However, if the application directly instantiates the bean, no parameters are passed to the constructor by the container』

直接的には明記されていませんが、 継承されたコンストラクタは、そのクラスが直接、CDIの対象となっていない限りは、 コンストラクタインジェクションとしての機能は有効にならないように見えます (『super(parameter)などで直接呼ばれる』ため、注入の余地がありませんし)。

サンプルでは、Config02クラスのコメントアウトを解除し、Config01のクラスのアノテーションを除去することで、 エラーが発生しなくなります(パターン C)(わたしが期待していた通りの動きです)。

パターン C.

	public static class Config01 {
		@Inject
		public Config01(
			@ConfigProperty(name="config01") String config01
		) {
		}
	}

	@Dependent
	public static class Config02 extends Config01 {
		@Inject
		public Config02(
			@ConfigProperty(name="config02") String config02
		) {
			super(config02);
		}
	}

また、パターン Cからさらに、フィールドインジェクションに切り替えると、 エラーとして検出されます(パターンD)(わたしが期待していた通りの動きです)。

パターン D.

	public static class Config01 {

		@Inject @ConfigProperty(name="config01") String config01;

		public Config01(
		) {
		}
	}

	@Dependent
	public static class Config02 extends Config01 {
		@Inject
		public Config02(
			@ConfigProperty(name="config02") String config02
		) {
			super();
		}
	}

パターンの整理

ここまでのパターンをまとめると、以下が、各InjectのPayara Microでの動作結果です。

* パターン わたしが期待する結果 実際の結果
A コンストラクタインジェクションを指定したクラスをAlternativeにした 無視される エラーになる
B フィールドインジェクションを指定したクラスをAlternativeにした 無視される エラーになる
C コンストラクタインジェクションを指定したクラスを継承した 無視される 無視される
D フィールドインジェクションを指定したクラスを継承した エラーになる エラーになる

パターン Cでは、わたしの期待通り、無視されています。 わたしの期待から外れるパターンは、パターン Aとパターン Bです。

このことから、タイトルには、コンストラクタインジェクションとAlternativeの両方の単語を含めましたが、 問題とすべきは、コンストラクタインジェクションではなく、Alternativeの場合にどのように動作すべきか、ということかと思いました。

Empressia avatar Feb 10 '20 10:02 Empressia

詳細な情報をご提供くださり、ありがとうございます。 また、先の私のコメントに不正確な点がございましたので、この場で訂正させてください。

MicroProfile Config 1.3 の仕様によると、以下の通りとなります。

  • インジェクション・ポイントに関する言及はない。
    • 仕様書上の記載ではフィールド・インジェクションのみ用いている。
  • 同様に Alternative CDI bean に対する Config プロパティのインジェクションに関する言及もない。

@ConfigProperty通常の CDI Qualifier として定義されていますので、@inject が使用できる場所であればどこでも動作するのが自然な振る舞いと考えられます。

ただし、Payara Micro が MicroProfile Config 1.3 の TCK をパスしていることを考慮すると、上記パターン A および B の動作は未定義(すなわち仕様不備)の可能性があります。


Thank you for your detail information. Since I gave incorrect explanation in my last comment, I'll correct that here.

According to MicroProfile Config 1.3 specification:

  • There's no mention to injection points.
    • In the specification document, only field injection is used.
  • There's also no mention to injection Config Property to Alternative CDI bean.

@ConfigProperty is a standard CDI Qualifier and therefore injection should work in all places where @Inject works.

However, considering Payara Micro passed the TCK of MicroProfile Config 1.3, the behaviours of the Pattern A and B as above may be undefined (i.e. insufficient specification).

khasunuma avatar Feb 11 '20 09:02 khasunuma