web-dev-qa-db-ja.com

インジェクションポイントで修飾子[@Default]を使用したタイプ[...]の依存関係が満たされていない(CDIで@Stateful EJBを使用)

2種類のリポジトリを管理する次のコードがあります。両方のリポジトリクラスは、リソースを再初期化できるようにするインターフェイスを継承しています。

public interface CachingRepository
{
    public void invalidateCache();
}

アプリケーションスコープのグローバルリポジトリ:

@Named("globalRepo")
@ApplicationScoped
public class GlobalRepository implements CachingRepository
{
    private List<Category> categories;

    ...

    @Override
    public void invalidateCache()
    {
        categories = null;
    }

    ...
}

ユーザーごとの、セッションスコープのリポジトリ:

@Named("userRepo")
@SessionScoped
//@Stateful         // <- NOTE HERE
public class UserRepository implements CachingRepository, Serializable
{
    private List<MyFile> files;

    @Override
    public void invalidateCache()
    {
        files = null;
    }

    ...
}

これを(@Statefulなしで)コンテキストに挿入するとき

@Named
@ViewScoped
public class MyHandler implements Serializable
{
    @Inject
    private UserRepository userRepo;

    ...
}

できます。ただし、@StatefulUserRepositoryクラスに追加すると、デプロイメントが失敗し、次のような例外が発生します。

Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [UserRepository] with qualifiers [@Default] at injection point [[field] @Inject private de.company.project.pack.MyHandler.userRepo]
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.Java:275)
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.Java:244)
    at org.jboss.weld.bootstrap.Validator.validateBean(Validator.Java:107)
    at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.Java:127)
    at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.Java:346)
    at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.Java:331)
    at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.Java:366)
    at org.jboss.as.weld.WeldContainer.start(WeldContainer.Java:83)
    at org.jboss.as.weld.services.WeldService.start(WeldService.Java:76)
    ... 5 more

のようなCDI Beanの名前を追加する

@Inject @Named("userRepo")
private UserRepository userRepo;

同じ例外が発生します。 @Statefulと連動して機能するのは、var宣言でインターフェースを使用することだけです。

@Inject @Named("userRepo")
private CachingRepository userRepo;

ただし、ここではサブクラスの機能が必要になる可能性があるため、(現時点では)CachingRepositoryを使用することはあまり望ましくありません。

Q's

  1. なぜこれが期待どおりに機能しないのですか? UserRepository varはインスタンス化するクラスをすでに識別しているはずですよね?これの論理は何ですか?
  2. ここで@Stateful EJBアノテーションがこのように深刻な影響を与えるのはなぜですか?なぜそれが本質的にvar宣言でCachingRepositoryインターフェースを使わざるを得ないのですか?

、Seam 3 Facesを使用して@ViewScopedをCDIビュースコープのBeanにしているため、問題はおそらくCDIのみです。

16
Kawu

私はこの誤解を招く例外で同じ問題を抱えていました...

@StatefulUserRepositoryに追加すると、インターフェースなしのビューを宣言せずにCachingRepositoryインターフェースのEJBメソッドを公開できます。 @LocalBeanUserRepositoryに追加して、インターフェースなしのビューをアクティブにします。 EJB 3.1仕様のセクション4.9.8「セッションBeanのインターフェースなしビュー」を参照してください。

Beanクラスは、Beanクラス定義を介して、またはデプロイメント記述子で非インターフェースビューを公開することを指定する必要があります。次の規則が適用されます。

  • ...
  • Beanが少なくとも1つの他のクライアントビューを公開する場合、Beanは、Beanクラスまたはデプロイメント記述子の@LocalBeanアノテーションを使用して、インターフェースなしのビューを公開することを指定します。
  • ...

インターフェイスなしのビューの詳細については、 this stackoverflow answerも参照してください。

10
kraftan

同じエラーが発生しました。

原因:org.jboss.weld.exceptions.DeploymentException:WELD-001408:インジェクションポイント[BackedAnnotatedField] @Inject ...

私はこの問題を次のように解決しました。エラーを受け取ったときに、このようにUserTransactionを使用しました。

@Inject
UserTransaction trans;

の代わりに @Inject、私は@Resourceアノテーション。

1
Remziye Şahin

私も同じ問題を抱えていました。これが誰かの役に立つことを願っています。

問題を解決するため:

  • プロジェクトを右クリック
  • Propertiesをクリックします
  • 検索Project facets
  • Project facetsで、オプションCDIをアクティブにします
  • 適用して保存します。

今はすべて元気です。

0
hubert

私も同じ問題を抱えていました。

そして、これは私がそれを解決するためにしたことです:

Wildflyコンテナを使用して、以下のように注入しようとしているEJBを作成する必要がありました。

@ApplicationScoped
    public class Resources {
     private static final String DISCOUNT_SERVICE_ENDPOINT_PROPERTY =
        "services.discount.endpoint";
     private MyServiceImpl myService;
    }

@Produces
 public MyServiceImpl produceMyServiceImpl() {
     if (myService == null) {
         String endpoint = System.getProperty(DISCOUNT_SERVICE_ENDPOINT_PROPERTY);
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(MyServiceImpl.class);
        factory.setServiceName(MyService.SERVICE);
        factory.setAddress(endpoint);
        myService = (MyServiceImpl) factory.create();
     }
     return myService;

}

以下は、standalone-full.xmlファイルの下にある設定です。

<property name="services.discount.endpoint" value="http://localhost:8080/my_service/MyService/MyServiceImpl"/>
0
Sydney Molobela

おそらく、パラメータ化されていないコンストラクタをBeanクラスに追加する必要があります。私は言うJbossドキュメンテーションを読みます:具体的なJavaパラメーターのないコンストラクターを持つクラス(またはアノテーション@Injectで指定されたコンストラクター)はBeanです。

0
Ricky Benitez