Charles Greiner
Charles Greiner

Reputation: 63

Java CDI Invalid DependsOn dependency

I am trying to update some content in the database at application startup. In order to do so I have created a class A which will do so.

@Singleton
@Startup
@DependsOn({ "B", "C" })
public class A{
    @Inject B b;
    @Inject C c; 
    ...
}

B is a class which reads some configuration values from the database. B:

@Singleton
@Startup
public class B {
     @PersistenceContext
     EntityManager em; 
     ...
}


C is a tree structure which uses the data from classes D and E to construct a correctly formatted tree.
C:

@Singleton
@Startup
@DependsOn({ "D", "E" })
public class C{
     @Inject
     D d;
     @Inject
     E e; 
     ...
 }

D and E are leaf singletons in the sense that they don't depend on other singletons; They provide data (which is read from files to the db):
D:

@Singleton
@Startup
public class D { ... }


E:

@Singleton
@Startup
public class E { ... }

Based on the DependsOn annotation documentation I assumed that CDI will create the dependency graph for the singletons and will initialize them in the specified order (B, D, and E will be initialized before C will, and before finally A will be initialized). However, when I try to deploy the application, I get an exception telling me:
Exception during lifecycle processing java.lang.RuntimeException: Invalid DependsOn dependency 'C' for EJB ContentUpdater.

Full stack trace:

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$2$1.run(CommandRunnerImpl.java:539)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.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$2.execute(CommandRunnerImpl.java:534)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$3.run(CommandRunnerImpl.java:565)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$3.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.access$1300(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$9.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.access$100(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)

Does anyone know why this exception occurs given the structure described above?

When I leave out class C in the @DependsOn annotation in class A, I get another exception, so unfortunately that is not a solution. The application is deployed on GlassFish 4.1

Upvotes: 0

Views: 1656

Answers (2)

Martin
Martin

Reputation: 655

There is a mistake in the naming. Here the expected bean with name "C" does not exist, instead the Singleton bean name is "QuestionHandler", and also D is a duplicated class, with Singleton names D and E. This is a mistake in the question and not necessarily the cause of the problem.

So, how do you avoid these "spelling" mistakes.

One solution could be to use static fields to connect the dots.

A:

@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; 
    ...
}

B:

@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";
     ...
 }

Upvotes: 0

Sergej Samsonow
Sergej Samsonow

Reputation: 93

I suggest you rethink your design and create just only one "StartUpController" that triggers init methods on all others ejbs in order you need.

@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 is not really a "dependency control" this is just a control of initialization order and it makes sense only together with @PostConstruct method. (I don't see any initialization methods in you example) so @DependsOn is not necessary. You can connect ejb's into chain without this annotation look this and this example.

I can't answer exactly why you code not works maybe it is just an typing error. For example you don't have C.class in code posted above you have QuestionHandler.class instead and again I don't see any @PostConstruct methods in you code. The other reason can be glashfish configuration I suggest you to try you code on wildfly server.

Upvotes: 1

Related Questions