Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: ScheuledExecutorService not work in @PostConstruct bean lifecycle hook #656

Closed
hantsy opened this issue Jan 15, 2025 · 5 comments
Closed
Labels
bug Something isn't working

Comments

@hantsy
Copy link

hantsy commented Jan 15, 2025

Specification Version

3.1.1

Bug report

I tried to convert the EJB timer-based scheduling work to use CDI and ScheduledExecutorService instead.

The original EJB @Singleton beans with a @Startup annotation.

@Startup
@Singleton // imported from ejb
public class CargoInspectedStub {
    private static final Logger LOGGER = Logger.getLogger(CargoInspectedStub.class.getName());

    @Inject @CargoInspected Event<Cargo> cargoEvent;
    @Resource TimerService timerService;

    @PostConstruct
    public void initialize() {
        LOGGER.log(Level.INFO, "raise CDI event after 5 seconds...");
        timerService.createTimer(5000, "delayed 5 seconds to execute");
    }

    @Timeout
    public void raiseEvent(Timer timer) {
        LOGGER.log(Level.INFO, "raising event: {0}", timer.getInfo());
        cargoEvent.fire(
                new Cargo(
                        new TrackingId("AAA"),
                        new RouteSpecification(
                                SampleLocations.HONGKONG,
                                SampleLocations.NEWYORK,
                                LocalDate.now().plusMonths(6))));
    }
}

and then convert to the following.

@ApplicationScoped
public class CargoInspectedSseEventStub {
    private static final Logger LOGGER =
            Logger.getLogger(CargoInspectedSseEventStub.class.getName());

    @Inject @CargoInspected Event<Cargo> cargoEvent;
    @Inject ManagedScheduledExecutorService scheduledExecutorService;

    @PostConstruct
    public void initialize() {
        LOGGER.log(Level.INFO, "raise event after 5 seconds...: {0}", startup);
        scheduledExecutorService.schedule(this::raiseEvent, 5000, TimeUnit.MILLISECONDS);
    }

    private void raiseEvent() {
        Cargo cargoEvent =
                new Cargo(
                        new TrackingId("AAA"),
                        new RouteSpecification(
                                SampleLocations.HONGKONG,
                                SampleLocations.NEWYORK,
                                LocalDate.now().plusMonths(6)));
        LOGGER.log(Level.INFO, "raise event: {0}", cargoEvent);
        this.cargoEvent.fire(cargoEvent);
    }
}

It does not work, there are no exceptions, and no useful information is provided to developers and tell developers what is wrong.

But changed to observing the Startup event, and it worked.

public void initialize(@Observes Startup startup) {
        LOGGER.log(Level.INFO, "raise event after 5 seconds...: {0}", startup);
        scheduledExecutorService.schedule(this::raiseEvent, 5000, TimeUnit.MILLISECONDS);
    }

Additional information

No response

@hantsy hantsy added the bug Something isn't working label Jan 15, 2025
@hantsy hantsy changed the title [Bug]: ScheuledExecutorService can not executed in the @PostConstruct bean lifecycle hook [Bug]: ScheuledExecutorService not work in @PostConstruct bean lifecycle hook Jan 15, 2025
@njr-11
Copy link
Contributor

njr-11 commented Jan 15, 2025

A PostConstruct method not being invoked on an ApplicationScoped CDI bean does not indicate a bug in the Jakarta Concurrency specification.

There might be a bug somewhere else, such as the CDI implementation, but I would guess the more likely cause is a wrong expectation. PostConstruct should be invoked after an instance of the bean is constructed, which might not happen until you invoke a method on it, which defeats the purpose of having it automatically trigger something to happen at application startup.

You might want to consider something else, like, jakarta.enterprise.event.Observes and jakarta.enterprise.event.Startup,

public void initialize(@Observes Startup event) {

but that is the domain of the CDI specification, not Jakarta Concurrency.

@hantsy
Copy link
Author

hantsy commented Jan 16, 2025

@njr-11 But in the original EJB @Singletone bean, the timerservice in @PostCostruct worked well.

@njr-11
Copy link
Contributor

njr-11 commented Jan 16, 2025

@njr-11 But in the original EJB @Singletone bean, the timerservice in @PostCostruct worked well.

If you have concerns about the design of how @PostConstruct works for @ApplicationScoped beans, please raise the issue against the CDI specification, not the Jakarta Concurrency specification. I recommend closing this issue against Concurrency.

@hantsy
Copy link
Author

hantsy commented Jan 16, 2025

@njr-11 Can you transfer it to CDI Github issues?

@njr-11
Copy link
Contributor

njr-11 commented Jan 16, 2025

@njr-11 Can you transfer it to CDI Github issues?

I don't have authority to do that. I can point you at the github project for CDI and you can open an issue that links back to this one if you like. I'm not going to open it myself because it seems reasonable to me that PostConstruct would only happen after constructing the bean instance and that the bean instance shouldn't need to be constructed until the application invokes something on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants