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

StackOverflow https://stackoverflow.com/questions/15696209

Question

I have a ServletContextListener that runs a tasks every 20 seconds - That task is to listen on a folder and check for new files and if found import the new file into a database. This is set up using the answer given from this question: Spawning threads in a JSF managed bean for scheduled tasks using a timer

Java Code for 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 Code for 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 Code for LocalBean to import the data to the database via 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);

        }

The listener does check the folder successfully - but when the code to import the database is called - it just seems to stall, with no error coming up on the JBOSS console. I have tried to inject the LoaderManager in many ways but have hit a brick wall... The method call loaderManager.loadDatabase(pathToNewFile); does not reach the LoaderManager class (Checked with print statements) unless i use instantiate it like

LoaderManager loaderManager = new LoaderManager():

.. which im pretty sure is wrong, and even with that it only gets as far as (but doesnt execute, checked via print statements)

em.persist(elementsInRow);

None of the rest of the functionality of the WebApp seems to be affected by any of this, Any help/advice would be much appreciated,

Cheers.

Was it helpful?

Solution

Your code makes very little sense. Injections are wrong and use of unmanaged threads is generally a bad idea in Java EE environment. Since you're using a container with Java EE 6, consider using singleton startup bean and 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);
     }
   }

Also I think that you should be using a singleton bean instead of stateless bean for LoaderManager.

OTHER TIPS

You are instantiating MyTask in the following line

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

Which makes use of

@EJB
LoaderManager loaderManager;

Which will be injected by the EJB Container. This way most probably it won't work.

One way to achieve this is by doing the following by having a Constructor for MyTask

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

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

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

In this case if LoaderManager is exposed to other applications as a Remote Client then you should be able to get this back.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top