简体   繁体   中英

Make a method inside EJB @Schedule to be called only once

So I have a relatively simple EJB. I want to check every ten seconds for a pdf file at a specific location and when I find it send a mail. Work fine and as expected but I always receive two identical email instead of one.The code is like this:

@Stateless
public class TimerBean {

    private EmailService emailService ;
    private boolean fileNotFound;

    public TimerBean(){
       this.fileNotFound= true;
       emailService = new EmailService();
    }

    @Schedule(second = "*/10", minute = "*", hour = "*")
    public void searchForPdf(){
       PDFChecker pdfChecker = new PDFChecker("directoryPath");
       String pdf =  pdfChecker.getPdfFile();
       processSendMail(pdf);
    }

    private void processSendMail(String pdf){
        if (!pdf.equals("") & this.fileNotFound){
            GlassfishLogger.log("Inside processSendMail. The fileNotFound variable is " + this.fileNotFound);
            this.fileNotFound= false;
            emailService.sendMail("dummyMail", "Dummy", "Pdf Found "+pdf);
        } 
    }
}

The method processSendMail is executed twice and somehow this.fileNotFound stays true . I receive 2 emails and then this.fileNotFound is set to false . I've try using AtomicBoolean and also make the bean @Singleton (or @Lock(LockType.Write) as sugested here ). What I'm doing wrong and how to make this code to send only one mail?

Update

I've added a log inside the processSendMail method and this are the results:

在此处输入图像描述


在此处输入图像描述

You are doing 2 errors here, you should first read carefully a tutorial about EJB and their lifecycle. The first error is that the EJB is @Stateless , therefore it doesn't preserve its status on each run of the scheduled task.

The second mistake is initializing the boolean default value inside the constructor. You cannot trust the constructor, because the EJB istance might be used again by the container. You must initialize it into a method annotated with @PostConstruct

Defining the bean as @Singleton will retain the status, and using the following initialization method is a good practice anyway:

@PostConstruct 
public void init() {

    fileNotFound = true;
}

See also:

Oracle's Java EE Tutorial - Enterprise Beans

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM