2017-04-12 10 views
-1

私は、アプリケーションの実行中にディレクトリを監視するために使用している再帰的な監視サービスを持っています。知られていない理由で、約1日後にウォッチサービスが停止するように見えます。その時点で、監視対象のディレクトリに新しいファイルを追加してログステートメントを取得することはできません。また、オブザーバには通知されません。Java WatchServiceが突然動作を停止する

私はSpringがBeanを破壊している可能性があるので、クラスの@ pre-destroyセクションにlogステートメントを追加しましたが、watchserviceが動作を停止した後にそのログステートメントが表示されないので、まだ存在していますが、期待どおり機能していません。

import com.sun.nio.file.SensitivityWatchEventModifier; 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.stereotype.Service; 

import java.io.File; 
import java.io.IOException; 
import java.nio.file.*; 
import java.nio.file.attribute.BasicFileAttributes; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.function.Consumer; 

import javax.annotation.PostConstruct; 
import javax.annotation.PreDestroy; 

import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; 
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE; 

@Service 
public class DirectoryMonitor { 

private static final Logger logger = LoggerFactory.getLogger(DirectoryMonitor.class); 
private WatchService watcher; 
private ExecutorService executor; 
private List<DirectoryMonitorObserver> observerList = new ArrayList<>(); 
private final Map<WatchKey, Path> keys = new HashMap<>(); 

public void addObserver(DirectoryMonitorObserver observer){ 
    observerList.add(observer); 
} 

private void notifyObservers(){ 
    observerList.forEach(DirectoryMonitorObserver::directoryModified); 
} 

@PostConstruct 
public void init() throws IOException { 
    watcher = FileSystems.getDefault().newWatchService(); 
    executor = Executors.newSingleThreadExecutor(); 
} 

@PreDestroy 
public void cleanup() { 
    try { 
     logger.info("Stopping directory monitor"); 
     watcher.close(); 
    } catch (IOException e) { 
     logger.error("Error closing watcher service", e); 
    } 
    executor.shutdown(); 
} 

@SuppressWarnings("unchecked") 
public void startRecursiveWatcher(String pathToMonitor) { 
    logger.info("Starting Recursive Watcher"); 

    Consumer<Path> register = p -> { 
     if (!p.toFile().exists() || !p.toFile().isDirectory()) 
      throw new RuntimeException("folder " + p + " does not exist or is not a directory"); 

     try { 
      Files.walkFileTree(p, new SimpleFileVisitor<Path>() { 
       @Override 
       public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { 
        logger.info("registering " + dir + " in watcher service"); 
        WatchKey watchKey = dir.register(watcher, new WatchEvent.Kind[]{ENTRY_CREATE, ENTRY_DELETE}, SensitivityWatchEventModifier.HIGH); 
        keys.put(watchKey, dir); 
        return FileVisitResult.CONTINUE; 
       } 
      }); 
     } catch (IOException e) { 
      throw new RuntimeException("Error registering path " + p); 
     } 
    }; 

    register.accept(Paths.get(pathToMonitor)); 

    executor.submit(() -> { 
     while (true) { 
      final WatchKey key; 
      try { 
       key = watcher.take(); 
      } catch (InterruptedException ex) { 
       logger.error(ex.toString()); 
       continue; 
      } 

      final Path dir = keys.get(key); 

      key.pollEvents().stream() 
        .map(e -> ((WatchEvent<Path>) e).context()) 
        .forEach(p -> { 
         final Path absPath = dir.resolve(p); 
         if (absPath.toFile().isDirectory()) { 
          register.accept(absPath); 
         } else { 
          final File f = absPath.toFile(); 
          logger.info("Detected new file " + f.getAbsolutePath()); 
         } 
        }); 

      notifyObservers(); 
      key.reset(); 
     } 
    }); 
} 

}

を次のようにクラスは、それはエラーが私の例外であったと思わ

@Component 
public class MovieInfoFacade { 
    @Value("${media.path}") 
    private String mediaPath; 
    private MovieInfoControl movieInfoControl; 
    private DirectoryMonitor directoryMonitor; 
    private FileListProvider fileListProvider; 

@Autowired 
public MovieInfoFacade(MovieInfoControl movieInfoControl, DirectoryMonitor directoryMonitor, FileListProvider fileListProvider){ 
    this.movieInfoControl = movieInfoControl; 
    this.directoryMonitor = directoryMonitor; 
    this.fileListProvider = fileListProvider; 
} 

@PostConstruct 
public void startDirectoryMonitor(){ 
    if(!mediaPath.equalsIgnoreCase("none")) { 
     directoryMonitor.addObserver(fileListProvider); 
     directoryMonitor.startRecursiveWatcher(mediaPath); 
    } 
} 

public int loadMovieListLength(String directoryPath){ 
    return fileListProvider.listFiles(directoryPath).length; 
} 

public List<MovieInfo> loadMovieList(MovieSearchCriteria searchCriteria) { 
    List<File> files = Arrays.asList(fileListProvider.listFiles(searchCriteria.getPath())); 

    return files.parallelStream() 
      .sorted() 
      .skip(searchCriteria.getPage() * searchCriteria.getItemsPerPage()) 
      .limit(searchCriteria.getItemsPerPage()) 
      .map(file -> movieInfoControl.loadMovieInfoFromCache(file.getAbsolutePath())) 
      .collect(Collectors.toList()); 
} 

public MovieInfo loadSingleMovie(String filePath) { 
    return movieInfoControl.loadMovieInfoFromCache(filePath); 
} 

}

+0

正確にはどうなりますか?それがどうやって止まるのかあなたは、OSのイベントハンドラにどんなイベントも見ますか? – bestprogrammerintheworld

+0

私はこの質問にさらに詳しい情報を追加しました。基本的にはログ出力は得られません。通常のように、私のオブザーバには通知されません。 – NRahm

+1

プログラムが実際に停止したことをどう知っていますか? :-) – bestprogrammerintheworld

答えて

0

..私はモニターBeanを作成しています場所ですです取り扱い。 throw文を削除した後(そしてそれらをログに置き換える)、私は何の問題も持っていません。

関連する問題