0

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.

Community
  • 1
  • 1
user1694873
  • 473
  • 1
  • 10
  • 20

2 Answers2

2

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.

Sami Korhonen
  • 1,246
  • 8
  • 17
1

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.

shazin
  • 19,072
  • 3
  • 45
  • 60
  • Thanks shazin - i have put in that constructor into the MyTask class but it goes into the catch block unfortunately. The Weblistener still executes its run method every 20 seconds howeve, but still stalls when it finds a new file to import into the database as explained above, any further suggestions welcome.. – user1694873 Mar 29 '13 at 10:08