Java CDI 无效的 DependsOn 依赖
Java CDI Invalid DependsOn dependency
我正在尝试在应用程序启动时更新数据库中的一些内容。为此,我创建了一个 class A 来执行此操作。
@Singleton
@Startup
@DependsOn({ "B", "C" })
public class A{
@Inject B b;
@Inject C c;
...
}
B 是一个 class,它从数据库中读取一些配置值。 B:
@Singleton
@Startup
public class B {
@PersistenceContext
EntityManager em;
...
}
C 是一个树结构,它使用来自 classes D 和 E 的数据来构造正确格式的树。
C:
@Singleton
@Startup
@DependsOn({ "D", "E" })
public class C{
@Inject
D d;
@Inject
E e;
...
}
D 和 E 是叶单例,因为它们不依赖于其他单例;他们提供数据(从文件读取到数据库):
D:
@Singleton
@Startup
public class D { ... }
E:
@Singleton
@Startup
public class E { ... }
基于 DependsOn annotation documentation 我假设 CDI 将为单例创建依赖图并按指定顺序初始化它们(B、D 和 E 将在 C 之前初始化,最后在 finally 之前A 将被初始化)。但是,当我尝试部署应用程序时,出现异常告诉我:
生命周期处理期间的异常
java.lang.RuntimeException: EJB ContentUpdater 的 DependsOn 依赖项无效 'C'。
完整堆栈跟踪:
java.lang.RuntimeException: Invalid DependsOn dependency 'C' for EJB A
at org.glassfish.ejb.deployment.util.EjbBundleValidator.checkDependsOn(EjbBundleValidator.java:602)
at org.glassfish.ejb.deployment.util.EjbBundleValidator.accept(EjbBundleValidator.java:300)
at org.glassfish.ejb.deployment.descriptor.EjbDescriptor.visit(EjbDescriptor.java:2823)
at org.glassfish.ejb.deployment.descriptor.EjbDescriptor.visit(EjbDescriptor.java:2811)
at org.glassfish.ejb.deployment.util.EjbBundleValidator.accept(EjbBundleValidator.java:115)
at com.sun.enterprise.deployment.BundleDescriptor.visit(BundleDescriptor.java:625)
at org.glassfish.ejb.deployment.descriptor.EjbBundleDescriptorImpl.visit(EjbBundleDescriptorImpl.java:757)
at com.sun.enterprise.deployment.util.ApplicationValidator.accept(ApplicationValidator.java:121)
at com.sun.enterprise.deployment.BundleDescriptor.visit(BundleDescriptor.java:625)
at com.sun.enterprise.deployment.archivist.ApplicationFactory.openArchive(ApplicationFactory.java:190)
at org.glassfish.javaee.core.deployment.DolProvider.processDOL(DolProvider.java:203)
at org.glassfish.javaee.core.deployment.DolProvider.load(DolProvider.java:227)
at org.glassfish.javaee.core.deployment.DolProvider.load(DolProvider.java:96)
at com.sun.enterprise.v3.server.ApplicationLifecycle.loadDeployer(ApplicationLifecycle.java:881)
at com.sun.enterprise.v3.server.ApplicationLifecycle.setupContainerInfos(ApplicationLifecycle.java:821)
at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:377)
at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:219)
at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:491)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:539)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:535)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:360)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.execute(CommandRunnerImpl.java:534)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:565)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:557)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:360)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:556)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1464)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.access00(CommandRunnerImpl.java:109)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1846)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1722)
at com.sun.enterprise.v3.admin.AdminAdapter.doCommand(AdminAdapter.java:534)
at com.sun.enterprise.v3.admin.AdminAdapter.onMissingResource(AdminAdapter.java:224)
at org.glassfish.grizzly.http.server.StaticHttpHandlerBase.service(StaticHttpHandlerBase.java:189)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
at org.glassfish.grizzly.filterchain.ExecutorResolver.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access0(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Thread.java:745)
有谁知道为什么会出现上述结构的异常?
当我在 class A 的 @DependsOn 注释中遗漏 class C 时,我得到另一个异常,所以不幸的是这不是解决方案。
该应用程序部署在 GlassFish 4.1
我建议您重新考虑您的设计并只创建一个 "StartUpController"
这会按您需要的顺序触发所有其他 ejb 上的 init 方法。
@Singleton
public class A {
public void init() {}
}
@Singleton
public class B {
public void init() {}
}
@Singleton
public class C {
public void init() {}
}
@Startup
@Singleton
public class StartUpController {
@Inject
private A a;
@Inject
private B b;
@Inject
private C c;
@PostConstruct
protected void setup() {
a.init();
b.init();
c.init();
}
}
@DependsOn 并不是真正的 "dependency control" 这只是初始化顺序的控制,只有与 @PostConstruct 方法一起使用才有意义。(我不请参阅示例中的任何初始化方法),因此不需要 @DependsOn。您可以在没有此注释的情况下将 ejb 连接到链中 this and this 示例。
我无法准确回答您的代码为何不起作用,也许这只是一个输入错误。例如,您在上面发布的代码中没有 C.class,而是使用了 QuestionHandler.class,而且我在您的代码中没有看到任何 @PostConstruct 方法。另一个原因可能是 glashfish 配置我建议你尝试在 wildfly 服务器上编写代码。
命名有误。
这里名称为 "C" 的预期 bean 不存在,Singleton bean 名称为 "QuestionHandler",并且 D 是重复的 class,Singleton 名称为 D 和 E。这是一个错误在问题中,不一定是问题的原因。
那么,如何避免这些 "spelling" 错误。
一种解决方案可能是使用静态字段来连接点。
甲:
@Singleton(name = A.BEAN_NAME)
@Startup
@DependsOn({ B.BEAN_NAME, C.BEAN_NAME })
public class A {
public static final BEAN_NAME = "A";
@Inject B b;
@Inject C c;
...
}
乙:
@Singleton(name = B.BEAN_NAME)
@Startup
public class B {
public static final BEAN_NAME = "B";
@PersistenceContext
EntityManager em;
...
}
C:
@Singleton(name = QuestionHandler.BEAN_NAME)
@Startup
@DependsOn({ D.BEAN_NAME, E.BEAN_NAME })
public class QuestionHandler {
public static final BEAN_NAME = "C";
@Inject
D d;
@Inject
E e;
...
}
D:
@Singleton(name = D.BEAN_NAME)
@Startup
public class D {
public static final BEAN_NAME = "D";
...
}
E:
@Singleton(name = E.BEAN_NAME)
@Startup
public class E {
public static final BEAN_NAME = "E";
...
}
我正在尝试在应用程序启动时更新数据库中的一些内容。为此,我创建了一个 class A 来执行此操作。
@Singleton
@Startup
@DependsOn({ "B", "C" })
public class A{
@Inject B b;
@Inject C c;
...
}
B 是一个 class,它从数据库中读取一些配置值。 B:
@Singleton
@Startup
public class B {
@PersistenceContext
EntityManager em;
...
}
C 是一个树结构,它使用来自 classes D 和 E 的数据来构造正确格式的树。
C:
@Singleton
@Startup
@DependsOn({ "D", "E" })
public class C{
@Inject
D d;
@Inject
E e;
...
}
D 和 E 是叶单例,因为它们不依赖于其他单例;他们提供数据(从文件读取到数据库):
D:
@Singleton
@Startup
public class D { ... }
E:
@Singleton
@Startup
public class E { ... }
基于 DependsOn annotation documentation 我假设 CDI 将为单例创建依赖图并按指定顺序初始化它们(B、D 和 E 将在 C 之前初始化,最后在 finally 之前A 将被初始化)。但是,当我尝试部署应用程序时,出现异常告诉我:
生命周期处理期间的异常
java.lang.RuntimeException: EJB ContentUpdater 的 DependsOn 依赖项无效 'C'。
完整堆栈跟踪:
java.lang.RuntimeException: Invalid DependsOn dependency 'C' for EJB A
at org.glassfish.ejb.deployment.util.EjbBundleValidator.checkDependsOn(EjbBundleValidator.java:602)
at org.glassfish.ejb.deployment.util.EjbBundleValidator.accept(EjbBundleValidator.java:300)
at org.glassfish.ejb.deployment.descriptor.EjbDescriptor.visit(EjbDescriptor.java:2823)
at org.glassfish.ejb.deployment.descriptor.EjbDescriptor.visit(EjbDescriptor.java:2811)
at org.glassfish.ejb.deployment.util.EjbBundleValidator.accept(EjbBundleValidator.java:115)
at com.sun.enterprise.deployment.BundleDescriptor.visit(BundleDescriptor.java:625)
at org.glassfish.ejb.deployment.descriptor.EjbBundleDescriptorImpl.visit(EjbBundleDescriptorImpl.java:757)
at com.sun.enterprise.deployment.util.ApplicationValidator.accept(ApplicationValidator.java:121)
at com.sun.enterprise.deployment.BundleDescriptor.visit(BundleDescriptor.java:625)
at com.sun.enterprise.deployment.archivist.ApplicationFactory.openArchive(ApplicationFactory.java:190)
at org.glassfish.javaee.core.deployment.DolProvider.processDOL(DolProvider.java:203)
at org.glassfish.javaee.core.deployment.DolProvider.load(DolProvider.java:227)
at org.glassfish.javaee.core.deployment.DolProvider.load(DolProvider.java:96)
at com.sun.enterprise.v3.server.ApplicationLifecycle.loadDeployer(ApplicationLifecycle.java:881)
at com.sun.enterprise.v3.server.ApplicationLifecycle.setupContainerInfos(ApplicationLifecycle.java:821)
at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:377)
at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:219)
at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:491)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:539)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:535)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:360)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.execute(CommandRunnerImpl.java:534)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:565)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:557)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:360)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:556)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1464)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.access00(CommandRunnerImpl.java:109)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1846)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1722)
at com.sun.enterprise.v3.admin.AdminAdapter.doCommand(AdminAdapter.java:534)
at com.sun.enterprise.v3.admin.AdminAdapter.onMissingResource(AdminAdapter.java:224)
at org.glassfish.grizzly.http.server.StaticHttpHandlerBase.service(StaticHttpHandlerBase.java:189)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
at org.glassfish.grizzly.filterchain.ExecutorResolver.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access0(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Thread.java:745)
有谁知道为什么会出现上述结构的异常?
当我在 class A 的 @DependsOn 注释中遗漏 class C 时,我得到另一个异常,所以不幸的是这不是解决方案。 该应用程序部署在 GlassFish 4.1
我建议您重新考虑您的设计并只创建一个 "StartUpController" 这会按您需要的顺序触发所有其他 ejb 上的 init 方法。
@Singleton
public class A {
public void init() {}
}
@Singleton
public class B {
public void init() {}
}
@Singleton
public class C {
public void init() {}
}
@Startup
@Singleton
public class StartUpController {
@Inject
private A a;
@Inject
private B b;
@Inject
private C c;
@PostConstruct
protected void setup() {
a.init();
b.init();
c.init();
}
}
@DependsOn 并不是真正的 "dependency control" 这只是初始化顺序的控制,只有与 @PostConstruct 方法一起使用才有意义。(我不请参阅示例中的任何初始化方法),因此不需要 @DependsOn。您可以在没有此注释的情况下将 ejb 连接到链中 this and this 示例。
我无法准确回答您的代码为何不起作用,也许这只是一个输入错误。例如,您在上面发布的代码中没有 C.class,而是使用了 QuestionHandler.class,而且我在您的代码中没有看到任何 @PostConstruct 方法。另一个原因可能是 glashfish 配置我建议你尝试在 wildfly 服务器上编写代码。
命名有误。 这里名称为 "C" 的预期 bean 不存在,Singleton bean 名称为 "QuestionHandler",并且 D 是重复的 class,Singleton 名称为 D 和 E。这是一个错误在问题中,不一定是问题的原因。
那么,如何避免这些 "spelling" 错误。
一种解决方案可能是使用静态字段来连接点。
甲:
@Singleton(name = A.BEAN_NAME)
@Startup
@DependsOn({ B.BEAN_NAME, C.BEAN_NAME })
public class A {
public static final BEAN_NAME = "A";
@Inject B b;
@Inject C c;
...
}
乙:
@Singleton(name = B.BEAN_NAME)
@Startup
public class B {
public static final BEAN_NAME = "B";
@PersistenceContext
EntityManager em;
...
}
C:
@Singleton(name = QuestionHandler.BEAN_NAME)
@Startup
@DependsOn({ D.BEAN_NAME, E.BEAN_NAME })
public class QuestionHandler {
public static final BEAN_NAME = "C";
@Inject
D d;
@Inject
E e;
...
}
D:
@Singleton(name = D.BEAN_NAME)
@Startup
public class D {
public static final BEAN_NAME = "D";
...
}
E:
@Singleton(name = E.BEAN_NAME)
@Startup
public class E {
public static final BEAN_NAME = "E";
...
}