0

We have a web app in Jboss 6.4 that has to check a Folder( new Files ), our idea was use Commons IO 2.4 with FileAlterationMonitor, like a backup we wanted to control the monitor.. if is working properly or not,

For this.. we created a TimerTask to control if the thread it's running if not, create another observer to continue with the work.

Our problem:

Now in our Test's we provoked a Exception to kill the Observer and detect that if he is not working and restart again, but We don't know how we have to do this with in FileAlterationMonitor, FileAlterationObserver or in FileAlterationListener, and how?

public class App {

  private static final String FOLDER ="/Folder";
  private static final FileAlterationMonitor monitor = new FileAlterationMonitor(1000);

  public static void main(String[] args) throws Exception {

    final File directory = new File(FOLDER);
    FileAlterationObserver fao = new FileAlterationObserver(directory);
    fao.addListener(new FileAlterationListenerImpl());
    monitor.addObserver(fao);

    monitor.start();


      TimerTask task = new TimerTask() {
          @Override
          public void run() {
            System.out.println("Monitor Controler");

            ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
            int noThreads = currentGroup.activeCount();
            Thread[] lstThreads = new Thread[noThreads];
            currentGroup.enumerate(lstThreads);

            for (int i = 0; i < noThreads; i++) {
                System.out.println("Thread No:" + i + " = "+ lstThreads[i].getName());
                System.out.println(lstThreads[i].getState().toString());
                System.out.println(lstThreads[i].isInterrupted());
                System.out.println(lstThreads[i].isAlive());
            }

                for (FileAlterationObserver o :monitor.getObservers()) {
                    String obName = o.toString();
                    String obDir = o.getDirectory().toString();

                    for(FileAlterationListener l :o.getListeners()){
                      String listener = l.toString();

                    }

          }
        };

        Timer timer = new Timer();
        long delay = 0;
        long intevalPeriod = 1 * 1000; 

        // schedules the task to be run in an interval 
        timer.scheduleAtFixedRate(task, delay, intevalPeriod);

  }

}

My Solution:

   public class App {

  private static final String FOLDER = "/Folder/";
  private static final FileAlterationMonitor monitor = new FileAlterationMonitor(1000);


  public static void main(String[] args) throws Exception {

    final File directory = new File(FOLDER);
    FileAlterationObserver fao = new FileAlterationObserver(directory);
    fao.addListener(new FileAlterationListenerImpl());

    monitor.addObserver(fao);
    monitor.start();

      TimerTask task = new TimerTask() {
          @Override
          public void run() {

            ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
            int noThreads = currentGroup.activeCount();
            Thread[] lstThreads = new Thread[noThreads];
            currentGroup.enumerate(lstThreads);

            boolean isDead = true;
            for (int i = 0; i < noThreads; i++) {

//              System.out.println("Thread No:" + i + " = "+ lstThreads[i].getName());
//              System.out.println("getState: "+lstThreads[i].getState().toString());
//              System.out.println("isInterrupted: "+ lstThreads[i].isInterrupted());
//              System.out.println("isAlive: "+lstThreads[i].isAlive());

                if(lstThreads[i].getName().equals("monitorThread"))
                {                   
                    isDead= false;          
                }
            }

            if(isDead){
                try {
                    monitor.stop();
                    monitor.start();
                    isDead = false;
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

          }
        };

        Timer timer = new Timer();
        long delay = 0;
        long intevalPeriod = 1 * 1000; 

        timer.scheduleAtFixedRate(task, delay, intevalPeriod);

  }

}

In my FileAlterationListenerImpl :

@Override
    public void onStart(final FileAlterationObserver observer) {

        Thread.currentThread().setName("monitorThread");

Is the only place I could set the name of the Thread..

reizintolo
  • 429
  • 2
  • 7
  • 20
  • Wouldn't Timer automatically start the task after the `intervalPeriod`, it's it's short then you don't have to do any thing. I a task is killed, new one will be started after `'intervalPeriod`. – 11thdimension Apr 17 '16 at 07:45
  • ok but how I can control the thread. observer or file listener is running or dead? – reizintolo Apr 17 '16 at 07:50

1 Answers1

1

You can use setThreadFactory() method on FileAlterationMonitor to set a custom thread factory. As to know about the state of the thread on which the monitor is running we would need to access it's instance.

So create a custom ThreadFactory class as below.

class SimpleThreadFactory implements ThreadFactory {
    private Thread monitorThread;
    public Thread newThread(Runnable r) {
        Thread thread = new Thread(r);
        if( r instanceof FileAlterationMonitor) {
            monitorThread = thread;
        }

        return thread;
    }

    public boolean isMonitorThreadAlive() {
        boolean isAlive = false;
        if(monitorThread != null) {
            isAlive = monitorThread.isAlive();
        }
        return isAlive;
    }
}

Now use the setThreadFactory() on FileAlterationMonitor to set the above custom thread factory.

Then you can use custom isMonitorThreadAlive() method to check if it's alive.

Another crude but probably easier way would be to give monitor thread a name and use the top ThreadGroup to find the thread by given name (and the use isAlive() on it).

Following is a simple sample

#Edit: Following can not be used as FileAlterationMonitor is a final class as pointed out by @JOANA_Batista

FileAlterationMonitor monitor = new FileAlterationMonitor(directory) {
    @Override
    public void run () {
        //setting name
        Thread.currentThread().setName("monitorThread");
        this.run();
    }
}

Since we can not override the FileAlterationMonitor we have to find some other way to change the monitor thread name. We can set use FileAlterationListener.onStart().

As this method is called on FileAlterationObserver.checkAndNotify() which is called in the FileAlterationMonitor.run()

FileAlterationMonitor.run()

public void run() {
    while (running) {
        for (FileAlterationObserver observer : observers) {
            observer.checkAndNotify();
        ...

FileAlterationObserver.checkAndNotify()

public void checkAndNotify() {

    /* fire onStart() */
    for (FileAlterationListener listener : listeners) {
        listener.onStart(this);
    }
    ...

It all happens on the same monitor thread that's why following code should set the monitor thread name in FileAlterationListener.onStart()

@Override
void onStart(final FileAlterationObserver observer) {
    Thread.currentThread().setName("monitorThread");
    ...
}

Note: You can call stop() method on the FileAlterationMonitor to stop() the thread, however to start it again you have to add the new FileAlterationObserver again as stop method destroys the observers. This should in effect restart the monitor thread.

public synchronized void stop(long stopInterval) throws Exception {
    if (running == false) {
        throw new IllegalStateException("Monitor is not running");
    }
    running = false;
    try {
        thread.join(stopInterval);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
    /***** Observers are destroyed here ****/
    for (FileAlterationObserver observer : observers) {
        observer.destroy();
    }
}

Probably it's better to create everything (Listener, Monitor and Obsever) again after calling stop, as there's not much (only Monitor object) to reuse.

11thdimension
  • 10,333
  • 4
  • 33
  • 71
  • ok great answer thanks! 11thdimension but I have a couple doubts.. the FileAlterationMonitor is public final class I can't override.., my second questions is how I can restart the FileAlterationMonitor? – reizintolo Apr 17 '16 at 13:46
  • you can see in my initial post my solution, the only I don't like.. is the way to set the name of the Monitor Thread, What do you think? – reizintolo Apr 17 '16 at 15:36
  • @JOANA_Batista, you're right, `FileAlterationMonitor` can not be extended. I have updated my answer. – 11thdimension Apr 17 '16 at 17:29
  • 11thdimension thanks a lot it's working!, one thing more: about the FileAlterationMonitor, I defined like: private static final and the private static FileAlterationObserver, it's correct? – reizintolo Apr 26 '16 at 05:57
  • Single static `FileAlterationMonitor` should be fine however single `FileAlterationObserver` is not, as on `stop()` call, it's destroyed. – 11thdimension Apr 26 '16 at 14:20
  • ok then.. static FileAlterationMonitor and FileAlterationObserver without static, thanks a lot! – reizintolo Apr 26 '16 at 15:20