0

20秒ごとにタスクを実行するServletContextListenerがあります。そのタスクは、フォルダーをリッスンして新しいファイルをチェックし、見つかった場合は新しいファイルをデータベースにインポートすることです。これは、次の質問からの回答を使用して設定されます:タイマーを使用してスケジュールされたタスクのために 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
            }
        }
    }

}

JPA 経由でデータをデータベースにインポートする LocalBean の Java コード

@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クラスに到達しません(printステートメントで確認)

LoaderManager loaderManager = new LoaderManager():

..これはかなり間違っていると確信しており、それでもそれは(実行されず、printステートメントでチェックされた)までしか到達しません

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 コンテナによって注入されるもの。この方法では、おそらくうまくいきません。

これを実現する 1 つの方法は、コンストラクターを使用して次のことを行うことです。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 に答える