我尝试使用POJO作为CDI生产者来注入正确的EJB,但我得到 org.jboss.weld.exceptions.UnsatisfiedResolutionException:WELD-001308 。
这是我的制片人POJO
public class STGatewayUtilProducer {
@Produces
@Chosen
public ISTGatewayUtil getISTGatewayUtil(Instance<STGatewayWSUtil> ws, Instance<STGatewayMQTTUtil> mqtt, ConfigurationManager cm) {
switch(cm.getGatewayProtocol()) {
case ConfigurationManager.GATEWAY_PROTOCOL_TYPE_MQTT:
return mqtt.get();
default:
return ws.get();
}
}
}
这是限定符定义:
@Qualifier
@Target({ TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
public @interface Chosen {}
这些是EJB声明:
@Stateless
public class STGatewayMQTTUtil implements Serializable, ISTGatewayUtil {
...
}
@Stateless
public class STGatewayWSUtil implements Serializable, ISTGatewayUtil {
...
}
最后,这就是我注入EJB的方式:
@Inject
@Chosen
private Instance<ISTGatewayUtil> gtwUtil;
我正面临JBoss AS 7和WildFly 10的问题。
我找到了问题的核心!我声明了一个公共abstract
父类,它实现了ejb接口,让我的会话bean扩展它:使用这种结构,bean无法解析。
相反,如果我在会话bean上移动implements
子句,问题就会消失:有人可能会解释我的类层次结构有什么问题吗?
答案 0 :(得分:2)
3.2.2。会话bean的Bean类型
会话bean的无限制bean类型包含all bean的本地接口及其超接口。如果是会话 bean有一个无界面视图,一组不受限制的bean类型 包含bean类和所有超类。此外, java.lang.Object是每个会话bean的bean类型。
远程接口不包含在bean类型集中。
所以这里因为你的会话bean都有一个本地接口,所以它们的bean类型集合中没有它们的类。因此,你无法用他们的班级解决这些问题是正常的。
您需要向会话bean定义添加额外信息,以便能够区分它们或将它们声明为带有@LocalBean注释的No-Interface视图EJB。 这是您的代码的新版本,将您的EJB声明为NIV
@Stateless
@LocalBean
public class STGatewayMQTTUtil implements Serializable, ISTGatewayUtil {
...
}
@Stateless
@LocalBean
public class STGatewayWSUtil implements Serializable, ISTGatewayUtil {
...
}
您的制作人不需要注入2 Instances<T>
。您可以注入两个bean并返回所选择的bean。
public class STGatewayUtilProducer {
@Produces
@Chosen
public ISTGatewayUtil getISTGatewayUtil(STGatewayWSUtil ws, STGatewayMQTTUtil mqtt, ConfigurationManager cm) {
switch(cm.getGatewayProtocol()) {
case ConfigurationManager.GATEWAY_PROTOCOL_TYPE_MQTT:
return mqtt;
default:
return ws;
}
}
}
或像这样使用Instance<T>
public class STGatewayUtilProducer {
@Produces
@Chosen
public ISTGatewayUtil getISTGatewayUtil(Instance<ISTGatewayUtil> gw, ConfigurationManager cm) {
switch(cm.getGatewayProtocol()) {
case ConfigurationManager.GATEWAY_PROTOCOL_TYPE_MQTT:
return gw.select(STGatewayMQTTUtil.class).get();
default:
return gw.select(STGatewayWSUtil.class).get();
}
}
}
使用bean实例生成新bean时要小心,它应该具有@Dependent
范围(以避免在生成的bean上重叠2生命周期)或者使用@New
关键字注入。在这里,您的会话bean位于@Dependent
范围内,因为它们没有指定任何范围。
答案 1 :(得分:0)
此处的案例场景非常适用于CDI限定符,如果您需要事务管理,您仍然可以维护ejb会话bean(如果您不需要任何事务逻辑,那么我将首先取消ejbs )。
那就是说,我会设计你的场景:
@Qualifier
@Retention(RUNTIME)
@Target(FIELD, METHOD, PARAMETER, TYPE)
public @interface ISTGateway {
ISTGatewayType value()
enum ISTGatewayType {
MQT,
WS
}
}
用法如下所示:(注意ejbs已注释@Dependent
以使CDI容器能够自动检测它们。
@Stateless
@Dependent
@ISTGateway(MQT)
public class STGatewayMQTTUtil implements Serializable, ISTGatewayUtil {
...
}
@Stateless
@Dependent
@ISTGateway(WS)
public class STGatewayWSUtil implements Serializable, ISTGatewayUtil {
...
}
你的制作人应该是这样的:(关于制作人的好处是你永远不需要更新它,如果你曾经添加新的ISTGatewayUtil)
@ApplicationScoped
public class STGatewayUtilProducer {
@Any
@Inject
private Instance<ISTGatewayUtil> istGatewayUtils;
@Inject
private ConfigurationManager configurationManager;
@Chosen
@Produces
public ISTGatewayUtil getISTGatewayUtil() {
final ISTGateway istGateway = new ISTGatewayImpl(cm.getGatewayProtocol());
return istGatewayUtils.select(istGateway).get();
}
private static final class ISTGatewayImpl extends AnnotationLiteral<ISTGateway> implements ISTGateway {
private final ISTGatewayType istGatewayType;
private ISTGatewayImpl( final ISTGatewayType istGatewayType) {
this.istGatewayType = istGatewayType;
}
public ISTGatewayType value() {
return istGatewayType;
}
}
}