【问题标题】:Migrating to CDI 1.2 WELD Exception迁移到 CDI 1.2 WELD 异常
【发布时间】:2018-06-28 15:42:11
【问题描述】:

在 Liberty 中迁移到 CDI 1.2 后,我的应用程序开始抛出 WELD 异常,我不清楚如何解决:

org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001334: Unsatisfied dependencies for type DataHandler with qualifiers @Any @DataHandlerBean WELD-001475: The following beans match by type, but none have matching qualifiers:
  - Session bean [class com.ibm.blueargus.feed.PathSquadHandler with qualifiers [@DataHandlerBean @Any]; local interfaces are [DataHandler],
  - Session bean [class com.ibm.blueargus.feed.DownAccessPointDataHandler with qualifiers [@DataHandlerBean @Named @Any]; local interfaces are [DataHandler],
  - Session bean [class com.ibm.blueargus.feed.ATTTicketDataHandler with qualifiers [@DataHandlerBean @Any]; local interfaces are [DataHandler],
  - Session bean [class com.ibm.blueargus.feed.WirelessClientDataHandler with qualifiers [@Named @DataHandlerBean @Any]; local interfaces are [DataHandler]

这发生在我根据自定义注释值选择 bean 的情况下 - 应用程序需要能够根据存储在数据库中的标准执行特定的 EJB 实现。如何更新我的代码以使用 CDI 1.1 并仍然允许基于自定义限定符值动态选择 EJB 实现?有没有更好的方法可以为我提供相同的一般功能?

限定符规范

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface DataHandlerBean {

   String value();

}

注解实现:

public class DataHandlerBeanQualifier extends AnnotationLiteral <DataHandlerBean> implements DataHandlerBean {

    private String value;

    public DataHandlerBeanQualifier (String value) {
        this.value=value;
    }

    @Override
    public String value() {
        return this.value;
    }

}

EJB 接口:

@Local
public interface DataHandler {

    public void extractData (Monitor monitor, DataFeed dataFeed) throws Exception;

}

示例 EJB 实现:

@Stateless
@DataHandlerBean("downAccessPointHandler")
public class DownAccessPointDataHandler implements DataHandler {

导致问题的业务逻辑 EJB (sn-p): monitor.getDataHandler() 中的值用于选择适当的 EJB 实现以传递控制以进行进一步处理。

@Stateless
public class DataScannerImpl implements DataScanner {

    public static Logger logger = Logger.getLogger(DataScanner.class.getName());

    @Inject
    @Any
    private Instance <DataHandler> dataHandlerInstance;

    private String processMonitorList(List <Monitor> monitorList, boolean forceLoad) {
        ...

        try {
            dataHandler = dataHandlerInstance.select(new DataHandlerBeanQualifier(monitor.getDataHandler())).get();
            dataHandler.extractData(monitor, dataFeed);
            monitor.setDataFeed(dataFeed);
        } catch ( Exception e ) {
            e.printStackTrace();
            logger.warn("Could not execute dataHandler: " + monitor.getDataHandler(), e);
        }

        ...
    }
}

这一切在我之前的 WebSphere v8.5 生产环境中运行良好。 Web 应用程序使用的是 CDI 1.0。

当前环境(server.xml):

<featureManager>
    <feature>javaee-7.0</feature>
    <feature>webProfile-7.0</feature>
    <feature>ejbPersistentTimer-3.2</feature>
    <feature>ldapRegistry-3.0</feature>
    <feature>appSecurity-2.0</feature>
    <feature>localConnector-1.0</feature>
    <feature>jaxrs-2.0</feature>
    <feature>jaxrsClient-2.0</feature>
    <feature>servlet-3.1</feature>
    <feature>jpa-2.1</feature>
</featureManager>

【问题讨论】:

  • 这是为了迁移到 CDI 1.2
  • 您的部署结构是什么?您在那里有什么 WAR/EAR/JAR,哪个 bean 驻留在哪个存档中?从技术上讲,您的方法看起来是有效的;您之前的 Liberty 版本是否使用 Weld 作为 CDI impl 或 owb?您可能会遇到一些 impl-details(bean 跨复杂档案的可见性就是其中之一)。

标签: jakarta-ee cdi


【解决方案1】:

您必须有一个 @Producer 方法,该方法将被注入实现 DataScanner 接口的 4 个类
这 4 个类必须使用 4 种不同的注解进行注解
根据您的业务逻辑,生产者将选择并“生产”正确的实现
然后你可以直接在你需要的地方注入"DataScanner"

@Inject
private DataHandler dataHandlerInstance;

这在Weld documentatiion here中有描述

在文档中,生产者在"PaymentProcessor" 接口的两个实现之间选择:"@Synchronous PaymentProcessor syncPaymentProcessor""@Asynchronous PaymentProcessor asyncPaymentProcessor"

【讨论】:

    【解决方案2】:

    问题是由于数据库值中的拼写错误导致 monitor.getDataHandler() 的值返回实际不存在的 bean 名称。

    【讨论】:

      猜你喜欢
      • 2020-08-30
      • 2013-09-15
      • 1970-01-01
      • 2020-01-27
      • 1970-01-01
      • 2018-05-08
      • 2012-09-18
      • 2016-02-14
      • 1970-01-01
      相关资源
      最近更新 更多