0

我有一个每 20 秒运行一次任务的 ServletContextListener - 该任务是侦听文件夹并检查新文件,如果发现将新文件导入数据库。这是使用从这个问题给出的答案设置的:Spawning threads in a JSF managed bean for scheduled tasks using a timer

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
            }
        }
    }

}

LocalBean 的 Java 代码,用于通过 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():

..我很确定这是错误的,即使这样它也只能达到(但不执行,通过打印语句检查)

em.persist(elementsInRow);

WebApp 的其他功能似乎都不受此影响,任何帮助/建议将不胜感激,

干杯。

4

2 回答 2

2

您的代码几乎没有意义。注入是错误的,在 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。

于 2013-03-29T10:20:33.147 回答
1

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作为远程客户端暴露给其他应用程序,那么您应该能够将其取回。

于 2013-03-29T08:23:48.963 回答