Search code examples
jsfjakarta-eeejbexecutorservice

Inject stateless bean into runnable for ScheduledExecutorService


I want to run some process just after the deployment of Glassfish. Process will run every hour and it contains fetching data from DB table via stateless bean CarService with findAll() below:

@PersistenceContext
private EntityManager em;

public List<Cars> findAll() {
    javax.persistence.criteria.CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
    cq.select(cq.from(Cars.class));
    return em.createQuery(cq).getResultList();
}

Then i am using ScheduledExecutorService with starts process after deployment.

@ManagedBean(eager=true)
@ApplicationScoped
public class ApplicationStateChange {

private ScheduledExecutorService scheduler;

@PostConstruct
public void init() {
    System.out.println("ejb init method called");
    scheduler = Executors.newScheduledThreadPool(2);
    scheduler.scheduleAtFixedRate(new ScheduleTask();, 15, 30, TimeUnit.SECONDS);
}

@PreDestroy
    public void destroy() {
        /* Shutdown stuff here */
        System.out.println("ejb destroy method called");
        scheduler.shutdownNow();
    }

above ScheduleTask() contains the process including business logic e.g:

public class ScheduleTask implements Runnable {

    @Inject
    CarService carService;
    private volatile ScheduledExecutorService scheduler = null;

    @Override
    public void run() {
        System.out.println("scheduletask is called");
        List<Car> carList = new ArrayList<>();
               carList = carService.findAll();
        if (carList != null) {
            for (Car car : carList) {
                System.out.println(car);
            }
        }
    }

i am unable to get the findALL() method by injecting into above runnable class. scheduler works fine but it fails when it reaches to carList = carService.findAll(); infact its failing at javax.persistence.criteria.CriteriaQuery cq = em.getCriteriaBuilder().createQuery();

I suspect persistence context is not loaded properly at the time of its calling.

I have followed following questionsSpawning threads in a JSF managed bean for scheduled tasks using a timer

scheduledExecutorService, timerService and Stateless EJB on scheduled jobs


Solution

  • As clearly exposed in the answer for the first question you have linked, simply use @Schedule into a @Singleton SessionBean annotated with @Startup in order to ensure it runs when the server starts or the application is deployed.

    As you correctly mentioned, EntityManager and PersistenceContext cannot be injected into a non container-mananged class (and Singleton SessionBean is a managed class).

    Linked Answer:

    Spawning threads in a JSF managed bean for scheduled tasks using a timer