"Unsatisfied dependencies" 尝试将 EJB 注入另一个组件时出现 UnsatisfiedResolutionException
"Unsatisfied dependencies" with UnsatisfiedResolutionException when trying to inject EJB into another component
我正在尝试实现 Java EE 的托管执行器 ManagedExecutorService
以提交可调用任务,其中每个任务都会调用注入的 bean 方法。
我正在使用 Instance
class 让容器知道任务对象,但是当执行 get()
时抛出以下异常:
Caused by: javax.ejb.EJBException:
org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001334:
Unsatisfied dependencies for type MyTask with qualifiers @Default
我在 WildFly 14 上运行。
注入的bean:
@Stateless
public class MyBean {
public void print() {
System.out.println("MyBean printed");
}
}
任务:
@Stateless
public class MyTask implements Callable<String> {
@Inject
MyBean myBean;
@Override
public String call() throws Exception {
System.out.println("MyTask called");
myBean.print();
return "Task called";
}
}
任务调用者:
@Stateless
public class TestBean {
@Inject
Instance<MyTask> myTaskInstance;
@Resource
private ManagedExecutorService executor;
public void test() throws InterruptedException, ExecutionException {
List<Callable<String>> tasks = new ArrayList<>();
MyTask task = myTaskInstance.get(); // <------- Exception is thrown here
tasks.add(task);
MyTask task2 = myTaskInstance.get();
tasks.add(task2);
List<Future<String>> taskResults = null;
taskResults = executor.invokeAll(tasks);
List<String> results = new ArrayList<>();
for(Future<String> taskResult : taskResults) {
results.add(taskResult.get());
}
}
}
为什么会抛出异常,如何解决这个问题? class路径中是否缺少库?
问题是 MyTask 作为实现 Callable 的 EJB,您已经删除了 MyTask class本身来自这个bean的"bean type",也就是说不能注入@Inject MyTask xxx
"client",按照CDI 2.0 spec里面的规则]:
18.2.2. Bean types of a session bean
The unrestricted set of bean types for a session bean contains all local interfaces of the bean and their superinterfaces. If the session bean has a no-interface view, the unrestricted set of bean types contains the bean class and all superclasses. In addition, java.lang.Object is a bean type of every session bean.
这就是为什么 Weld 找不到有效的 MyTask bean 来满足对 TestBean 客户端的注入。
您可以通过添加 @LocalBean
注释为 MyTask EJB 提供无接口视图,例如:
@Stateless
@LocalBean
public class MyTask implements Callable<String> {
或者,您可以删除 implements Callable
并重构为:
public class MyTask {
@Inject
MyBean myBean;
MyCallable callable = new MyCallable();
public Callable getCallable() {
return callable;
}
private class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("MyTask called");
myBean.print();
return "Task called";
}
}
}
public class TestBean {
// ...
MyTask task = myTaskInstance.get();
tasks.add(task.getCallable())
// ...
}
有关更多讨论,请参阅 here for a quick reference on the no-interface view, as well as this post。
我正在尝试实现 Java EE 的托管执行器 ManagedExecutorService
以提交可调用任务,其中每个任务都会调用注入的 bean 方法。
我正在使用 Instance
class 让容器知道任务对象,但是当执行 get()
时抛出以下异常:
Caused by: javax.ejb.EJBException: org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001334: Unsatisfied dependencies for type MyTask with qualifiers @Default
我在 WildFly 14 上运行。
注入的bean:
@Stateless
public class MyBean {
public void print() {
System.out.println("MyBean printed");
}
}
任务:
@Stateless
public class MyTask implements Callable<String> {
@Inject
MyBean myBean;
@Override
public String call() throws Exception {
System.out.println("MyTask called");
myBean.print();
return "Task called";
}
}
任务调用者:
@Stateless
public class TestBean {
@Inject
Instance<MyTask> myTaskInstance;
@Resource
private ManagedExecutorService executor;
public void test() throws InterruptedException, ExecutionException {
List<Callable<String>> tasks = new ArrayList<>();
MyTask task = myTaskInstance.get(); // <------- Exception is thrown here
tasks.add(task);
MyTask task2 = myTaskInstance.get();
tasks.add(task2);
List<Future<String>> taskResults = null;
taskResults = executor.invokeAll(tasks);
List<String> results = new ArrayList<>();
for(Future<String> taskResult : taskResults) {
results.add(taskResult.get());
}
}
}
为什么会抛出异常,如何解决这个问题? class路径中是否缺少库?
问题是 MyTask 作为实现 Callable 的 EJB,您已经删除了 MyTask class本身来自这个bean的"bean type",也就是说不能注入@Inject MyTask xxx
"client",按照CDI 2.0 spec里面的规则]:
18.2.2. Bean types of a session bean
The unrestricted set of bean types for a session bean contains all local interfaces of the bean and their superinterfaces. If the session bean has a no-interface view, the unrestricted set of bean types contains the bean class and all superclasses. In addition, java.lang.Object is a bean type of every session bean.
这就是为什么 Weld 找不到有效的 MyTask bean 来满足对 TestBean 客户端的注入。
您可以通过添加 @LocalBean
注释为 MyTask EJB 提供无接口视图,例如:
@Stateless
@LocalBean
public class MyTask implements Callable<String> {
或者,您可以删除 implements Callable
并重构为:
public class MyTask {
@Inject
MyBean myBean;
MyCallable callable = new MyCallable();
public Callable getCallable() {
return callable;
}
private class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("MyTask called");
myBean.print();
return "Task called";
}
}
}
public class TestBean {
// ...
MyTask task = myTaskInstance.get();
tasks.add(task.getCallable())
// ...
}
有关更多讨论,请参阅 here for a quick reference on the no-interface view, as well as this post。