Mario Köhler
Mario Köhler

Reputation: 202

Why is my CDI startup class called twice?

I'm using the following class to do some initialization after my .war is deployed on Payara. And i can see that the init() method is actually called twice during the startup of the application.

package mypackage;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Initialized;
import javax.enterprise.event.Observes;
import javax.inject.Inject;

import lombok.extern.log4j.Log4j2;

@Log4j2
@ApplicationScoped
public class StartupService {

    @Inject LogConfig logConfig;

    void init(@Observes @Initialized(ApplicationScoped.class) Object init) {
        log.debug("### STARTUP SERVICE CALLED ###");

        logConfig.startup();
    }
}

can someone explain to me why this is called twice and how i can avoid it?

I mean, i can of course implement a static boolean flag to recognize that i was already called once before, but i would prefer to fix the root cause and only get called once from the start.

Upvotes: 1

Views: 935

Answers (1)

Siliarus
Siliarus

Reputation: 6753

Ok, I'll try to sum this up, it might not be exactly the case, I can try to dig deeper. But here is what I think is going on...

You get the event twice, each time with different payload. There can be various reasons for this, but most likely one is that Paraya has a tiny flaw in integration. Weld recommends integrators to define the environment in which it operates through SPI. If they don't, Weld can handle it, but needs to do some assumptions and guesses so as to fulfill specification requirements.

In this case, I suspect Paraya wrongly defines Environment and Weld is not sure which events to fire - for web modules, there is a requirement to fire event with ServletContext payload, while the rest of module have plain Object as payload.

Sadly, there is no easy way to prevent both events from being fired except for having the information about environment preemptively. The reason is that Weld needs to decide about the Object payload event long before there is any hook active for web modules.

The solution in your case is probably to specify the Object to a more concrete type - so that only one event is observed. Based on your sample I assume ServletContext payload will be the one you are looking for.

Upvotes: 2

Related Questions