Планировщик ServletContextListener выполняет задачу, а затем останавливается при вызове метода EJB для сохранения в базе данных в JBOSS 7.1.

У меня есть ServletContextListener, который запускает задачи каждые 20 секунд. Эта задача состоит в том, чтобы прослушивать папку и проверять наличие новых файлов и, если они найдены, импортировать новый файл в базу данных. Это настраивается с использованием ответа, полученного из этого вопроса: Создание потоков в управляемом компоненте JSF для запланированных задач с помощью таймера

Код Java для ServletContextListener

@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");
        }
}

Код Java для MyTask

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 для 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():

.. что я почти уверен, что это неправильно, и даже с этим он доходит только до (но не выполняется, проверяется с помощью операторов печати)

em.persist(elementsInRow);

Ни одна из остальных функций WebApp, по-видимому, не затронута этим. Любая помощь / совет будут высоко оценены,

Ваше здоровье.


person user1694873    schedule 29.03.2013    source источник


Ответы (2)


Ваш код имеет очень мало смысла. Внедрения — это неправильно, а использование неуправляемых потоков — вообще плохая идея в среде Java EE. Поскольку вы используете контейнер с Java EE 6, рассмотрите возможность использования одноэлементного стартового компонента и службы таймера:

   @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.

person Sami Korhonen    schedule 29.03.2013
comment
Большое спасибо - это заработало! Очень признателен! - person user1694873; 29.03.2013

Вы создаете экземпляр 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 доступен другим приложениям в качестве удаленного клиента, вы сможете вернуть его обратно.

person shazin    schedule 29.03.2013
comment
Спасибо, shazin - я добавил этот конструктор в класс MyTask, но, к сожалению, он входит в блок catch. Однако веб-прослушиватель по-прежнему выполняет свой метод запуска каждые 20 секунд, но все еще останавливается, когда находит новый файл для импорта в базу данных, как описано выше, любые дальнейшие предложения приветствуются. - person user1694873; 29.03.2013