Oracle ayant récemment publié la version 7 du JRE, j'ai décidé de commencer à tester quelque peu les nouveautés disponibles.
Dans cet article, je vais présenter les possibilités offertes par la nouvelle gestion du système de fichiers, avec java.nio.file.WatchService
, qui permet de mettre en place un outil de "surveillance" des ressources.
Imaginons donc une fonctionnalité de mise à jour en temps réel de la configuration d'une application lors de la modification d'un fichier properties.
Voici le code mis en place :
package com.developpef; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardWatchEventKinds; import java.nio.file.WatchEvent; import java.nio.file.WatchKey; import java.nio.file.WatchService; import java.nio.file.attribute.BasicFileAttributes; import java.util.List; import java.util.Properties; public class PropertiesSpreader { private static final String basePath = "C:\\java\\ides\\eclipse-jee-helios-SR2\\workspace\\Test\\resources"; private static Path propDir; public static void main(String[] args) { try { loadProperties(); FileSystem fs = FileSystems.getDefault(); final WatchService watcher = fs.newWatchService(); propDir = fs.getPath(basePath); propDir.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY); Thread t = new Thread(new Runnable() { @Override public void run() { watch(watcher); } }); t.start(); System.out.println("Le watcher a été démarré..."); } catch (IOException e) { e.printStackTrace(); } } private static void watch(WatchService watcher) { WatchKey key = null; do { try { key = watcher.take(); List<WatchEvent<?>> events = key.pollEvents(); for (WatchEvent<?> event : events) { if (event.kind() == StandardWatchEventKinds.ENTRY_MODIFY) { Path propFile = (Path) event.context(); if (propFile.endsWith("test.properties")) { BasicFileAttributes bfa = Files.readAttributes( propDir.resolve(propFile), BasicFileAttributes.class); System.out .println("\n** Fichier propriétés modifié! Rechargement... (modifications du " + bfa.lastModifiedTime() + ")**"); loadProperties(); } } } } catch (InterruptedException|IOException e) { e.printStackTrace(); } } while (key.reset()); } private static void loadProperties() throws IOException { InputStream stream = new FileInputStream(new File(basePath + "\\test.properties")); Properties props = new Properties(); props.load(stream); stream.close(); System.out.println("Titre de l'application : " + props.getProperty("App.title")); } }
L'intérêt de cette implémentation est de gérer la configuration dans un thread autonome (comme un daemon) qui actualisera les propriétés de l'application.
La gestion du système de fichiers a été "allégée", notamment grâce à un nouveau "super objet" java.nio.file.FileSystem
qui facilite la manipulation des ressources de manière logique. Ainsi, par exemple, plus besoin d'instancier des java.io.File
à tour de bras : la méthode java.nio.file.FileSystem.getPath("Path")
permet de récupérer n'importe quel type de chemin, qu'il s'agisse d'un fichier ou d'un dossier, sous la forme d'un java.nio.file.Path
.
Ensuite, l'essentiel de la fonction de mise à jour réside dans la méthode watch
qui relance le chargement du fichier de configuration dès que celui-ci est modifié. Exemple de trace lors de l'utilisation :
Titre de l'application : Java 7 Watch Service Le watcher a été démarré... ** Fichier propriétés modifié! Rechargement... (modifications du 2011-08-10T09:22:37.183499Z)** Titre de l'application : Java 7 Watch Service rocks!!
Pour les plus observateurs, vous aurez également pu remarquer une nouvelle syntaxe de catch multiple : catch (InterruptedException|IOException e)
apportée par le projet Coin dont j'ai parlé dans cet article.
Note :
Ce code fonctionne correctement lors de la modification du fichier avec Notepad (de Windows). Mais dès que l'on essaie de modifier le fichier avec un autre éditeur (Notepad++ ou Eclipse), le WatchService réagit à deux évènements de modification. Je n'ai pas encore d'explication quant à ce comportement (comme expliqué ici), mais si quelqu'un a déjà pu approfondir les tests et trouvé une solution, tout commentaire est le bienvenu!
1 commentaires:
Cool !
Enregistrer un commentaire