簡體   English   中英

ServletContextListener調度程序執行任務-然后暫停EJB方法調用以將其持久保存到JBOSS 7.1中的數據庫中

[英]ServletContextListener scheduler carry out a task - then stalls on EJB method call to persist into a database in JBOSS 7.1

我有一個ServletContextListener,它每20秒運行一次任務-該任務是偵聽文件夾並檢查是否有新文件,如果找到,則將新文件導入數據庫。 這是使用以下問題給出的答案設置的: 使用計時器在JSF托管Bean中生成線程以執行計划的任務

ServletContextListener的Java代碼

@WebListener
public class Listener implements ServletContextListener {

     private ScheduledExecutorService scheduler;

        @Override
        public void contextInitialized(ServletContextEvent event) {
            scheduler = Executors.newSingleThreadScheduledExecutor();

            scheduler.scheduleAtFixedRate(new MyTask(), 0,20, TimeUnit.SECONDS);
        }

        @Override
        public void contextDestroyed(ServletContextEvent event) {
            scheduler.shutdownNow();
            System.out.println("Terminating the Listener");
        }
}

MyTask的Java代碼

public class MyTask implements Runnable{

@EJB
LoaderManager loaderManager;

@Schedule(hour="0", minute="0", second="0", persistent=false)
public void run() {

                //Some unnecessary code left out


        if (itIsOkToImportTheDatabase)
            {


            loaderManager.loadDatabase(pathToNewFile);


            if (thisistrue) {
                //doesnt matter
            } else {
                //doesnt matter
            }
        }

        else

        {
            // not important
            }
        }
    }

}

Java Code for LocalBean通過JPA將數據導入數據庫

@Stateless
@LocalBean
public class LoaderManager implements LoaderManagerDAO{

    @Inject
    private EntityManager em;
    private Row row = null;
    private FileInputStream inp;
    private Workbook wb;

    public void loadDatabase(String FileLocation) {

        InputStream inp = null;

// some file set up stuff, using Apache POI

Sheet sheet1 = wb.getSheetAt(0);

for (int i = 1; i <= sheet1.getLastRowNum(); i++) {
            // loop through each row

            em.persist(elementsInRow);

        }

偵聽器確實檢查了文件夾-但是調用導入數據庫的代碼時-似乎停滯了,在JBOSS控制台上沒有出現錯誤。 我試圖以多種方式注入LoaderManager,但遇到了麻煩...該方法調用loaderManager.loadDatabase(pathToNewFile); 除非我使用實例化它不會達到LoaderManager類(與打印語句檢查)

LoaderManager loaderManager = new LoaderManager():

..我非常確定這是錯誤的,即使它只能達到(但不執行,通過print語句檢查)

em.persist(elementsInRow);

WebApp的所有其他功能似乎均未受此影響,任何幫助/建議將不勝感激,

干杯。

您的代碼毫無意義。 注入是錯誤的,在Java EE環境中,使用非托管線程通常不是一個好主意。 由於您將容器與Java EE 6一起使用,請考慮使用單例啟動bean和timerservice:

   @Startup
   @Singleton
   public class SchedulerBean {
     @Resource
     private TimerService timerService;
     @EJB
     private LoaderManager loaderManager;
     private Timer timer;

     @PostConstruct
     public void init() {
       timer = timerService.createIntervalTimer(20 * 1000, 20 * 1000, new TimerConfig(null, false));
     }

     @PreDestroy
     public void deinit() {
       timer.cancel();
     }

     @Timeout
     public void schedule(Timer timer) {
        // TODO: Add your checks here
        loaderManager.loadDatabase(databaseLocation);
     }
   }

另外,我認為您應該為LoaderManager使用單例bean而不是無狀態bean。

您將在以下行中實例化MyTask

scheduler.scheduleAtFixedRate(new MyTask(), 0,20, TimeUnit.SECONDS);

哪個利用

@EJB
LoaderManager loaderManager;

它將由EJB容器注入。 這樣很可能無法正常工作。

實現此目的的一種方法是通過為MyTask構造一個構造器來執行以下操作

public MyTask() {
    try {
        InitialContext ctx = new InitialContext();

        loaderManager = (LoaderManager) ctx.lookup("<Package Name>.LoaderManager");

    } catch (NamingException ex) {
        // Error Handling
    }
}

在這種情況下,如果LoaderManager作為遠程客戶端公開給其他應用程序,則您應該可以將其取回。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM