lundi 30 avril 2012

Détection de modifications sur un fichier ou un dossier: Le FileWatcher

Sur les systèmes Windows, il est possible de récupérer des évenements liés au système de fichier tel que la création d'un fichier, sa modification, sa suppression, ...

Le framework .Net fourni une classe, le FileSystemWatcher, qui permet de récupérer ces événements. Cette classe peut-être utilisée pour, par exemple, récupérer l'événement de modification d'un fichier de configuration afin de le recharger sans devoir redémarrer l'application concernée. Le FileSystemWatcher peut récupérer les évenements liés à un dossier et ses sous-dossiers ou un fichier déterminé.

Les principales propriétés définissant le watcher sont les suivantes :
  • Filter (string) : Permet de filtrer les fichiers par extensions. Utilise les wildchars (exemple *.xml pour les fichiers avec l'extension xml). Si on specifie un nom de fichier les évenements ne seront déclenchés que pour ce fichier.
  • IncludeSubdirectories (bool) : Permet d'inclure ou non les sous dossier du dossier défini dans la propriété Path
  • NotifyFilter (enum NotifyFilters) : Permet de filtrer les évenements qui doivent déclencher le watcher.
  • Path (string) : Le chemin du dossier sur lequel il faut écouter les évenements.
  • EnableRaisingEvents (bool) : Démarre ou arrête le déclenchement des évenements par le watcher
  • InternalBufferSize (int) : la taille du buffer contenant les évenements non encore traité. Une taille trop faible risque de provoquer de nombreux dépassements. La taille par défaut est de 8192.
Et les évenements écoutables sont :
  • Changed : Un fichier ou un dossier a été modifé
  • Created : Un fichier ou un dossier a été créé
  • Deleted : Un fichier ou un dossier a été supprimé
  • Renamed : Un fichier ou un dossier a été renommé
  • Error : La limite du buffer du watcher a été dépassée
Voici un petit exemple permettant d'afficher dans une console si un fichier a été modifié :
Et voici le handler de l'évenement :


En fonction de l'éditeur que vous utilisez, il est possible que 2 évenements soient déclenchés lorsque vous sauvez votre fichier. Il existe plusieurs solutions permettant de résoudre ce problème (je vous invite à lire la source 3). Celle que je vous propose ici consiste à déterminer la date de dernière modification du fichier et de voir si le second évenement n'a pas été déclenché en même temps. Je stocke donc la date de dernière modification dans une variable et je la teste avant de réaliser la tâche à faire :
Ainsi, l'évenement ne sera déclenché qu'une seule fois.

La documentation de la MSDN (source 1) est, comme d'habitude, très explicite, n'hésitez donc pas à y jeter un oeil pour en savoir plus.

Sources :
  1. http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx
  2. http://weblogs.asp.net/ashben/archive/2003/10/14/31773.aspx
  3. http://stackoverflow.com/questions/1764809/filesystemwatcher-changed-event-is-raised-twice

vendredi 27 avril 2012

Transformation des fichiers de configuration

Lorsque l'on déploie son application sur plusieurs environnements différent, il est nécessaire de modifier le fichier de configuration(web.config dans le cas des applications web, app.config sinon). Il est donc nécessaire de conserver ces fichiers de configurations et ne pas les écraser lors des déploiements.

Il est possible avec Visual Studio 2010 de générer des fichiers de configuration propre à l'environnement considéré avec la fonctionnalité Web.config Transform. Par défaut, cette fonctionnalité est automatiquement gérée par visual studio pour les projets web. Pour avoir le même comportement avec les fichiers app.config (projets non web) il existe un plug-in qui fera tout le travail pour vous : SlowCheetah - XML Transforms.

Comment ca marche ? Tout d'abord il est nécessaire d'ajouter un fichier de configuration dans votre projet(si cela n'est déja fait). Ensuite, avec un click droit sur votre fichier de configuration séléctionner l'option "Add Transform" ce qui va généré un fichier par configuration défine dans votre projet.
Ajouter les fichiers de transformations

Il est à présent possible de définir ce qui doit être changé dans le fichier de configuration en fonction de l'environnement/configuration cible. Pour l'exercice, je voudrais avoir une paramètre de mon application qui change en fonction de l'environnement. Voici mon fichier de configuration :

Un exemple de fichier de configuration

Je voudrais avoir la valeur "Hey this is the debug file" lorsque je suis dans mon environnement de debug. Pour ce faire, je modifie le fichier App.Debug.config comme suit :

Un exemple de transformation de configuration

Dans mon projet, je référénce la configuration et je récupère le paramètre de configuration comme on le fait habituellement, par exemple (Une référence vers l'assembly System.Configuration est nécessaire) :


En fonction de la configuration choisie lors du build, le résultat retourné sera différent ! Il est possible de faire d'autres actions que simplement modifier le fichier de configuration. Pour plus d'informations, je vous invite à lire la document de la MSDN (voir sources)

Pour générer des fichiers de configuration propre à chaque environnement, il est possible de créer des configurations de build supplémentaires via le configuration manager (accessible via le menu Build/Configuration Manager). Une fois vos environnements définis, il suffit de recréer les fichiers de transformation en répétant l'opération "Add Transform" comme nous l'avons vu plutôt.

Sources et références:

mardi 17 avril 2012

Client WCF asynchrone


Pour réaliser des clients Wcf asynchrone, il existe de nombreuses solutions. Cela peut se faire via la génération automatique du client via le ServiceModel Metadata Utility Tool (Svcutil.exe) ou via l'outil fourni avec visual studio comme montré ci dessous.

Génération d'un client Wcf avec Visual Studio 2010

Le problème de ces 2 solutions, c'est que le client généré n'est pas directement lié à l'interface du service (le contrat)
Il est possible de réaliser son propre client asynchrone en héritant de la classe ClientBase ou en utilisant un contrat de services proposant des méthodes asynchrones (ce qui demande de les développer manuellement)

Une autre solution que je trouve fort sympathique est d'utiliser le WCF Facility fourni avec la librairie Castle Windsor. Cette solution permet, à partir d'un contrat non asynchrone de créer dynamiquement un client asynchrone.

Pour ce faire, il suffit d'enregistrer le proxy dans un container et définir le contrat qu'il implémente lors de l'enregistrement:

Il est nécessaire d'ajouter le Wcf Facility dans les facilities Castle pour activer la fonctionnalité
Ensuite, il suffit de récupérer l'objet dans le container et d'appeler la fonction BeginWcfCall :

BeginWcfCall prend en paramètre une fonction de callback. la signature de cette fonction est la suivante :
Ainsi, vous pouvez avoir rapidement un proxy Wcf asynchrone en quelques lignes.

La fonction BeginWcfCall est une extension méthode il est donc nécessaire d'inclure le namespace Castle.Facilities.WcfIntegration.Async dans les usings du code.

Sources:
  • http://msdn.microsoft.com/en-us/library/ms730059.aspx
  • http://msdn.microsoft.com/en-us/library/aa347733.aspx
  • http://www.castleproject.org/castle/projects.html
  • http://www.castleproject.org/container/facilities/trunk/wcf/index.html
  • http://docs.castleproject.org/Windsor.WCF-Facility-Async-Calls.ashx
  • http://msdn.microsoft.com/en-us/library/aa347733.aspx

jeudi 5 avril 2012

Timer en Javascript (Timing events)


Il est possible en javascript de réaliser des timers qui exécutent une fonction de manière répetée après un certain interval de temps ou tout simplement programmer un appel de fonction dans le futur.

Pour ce faire, il existe 2 fonctions :
  • setInterval([string expression],[interval en ms]) returns [timerID]
  • setTimeout([string expression],[interval en ms]) returns [timerID] 
Ces 2 fonctions disposent chacune d'une autre fonction permettant d'annuler la programmation :
  • clearInterva([timerID])
  • clearTimeout([timerID])
La fonction setInterval défini une expression à exécuter périodiquement tant que la fenetre n'est pas fermée ou que l'on appelle la fonction clearInterval.

La fonction setTimeout défini une expression à exécuter après un certain interval de temps. Cette expression ne sera pas automatiquement réexécutée mais libre a vous de refaire un setTimeout pour reprogrammer l'exécution de l'expression! Un appel à clearTimeout ou la fermeture de la fenetre annulera le timer et l'expression ne sera pas réexécutée.

Ci dessous un petit exemple en javascript qui permet de faire clignoter le caractère '_' à la fin du titre :

Sources

mercredi 4 avril 2012

Paramètre OUT dans une procédure Oracle en Java

Comme vous le savez sans doute, il est possible de développer ses propres procédures/fonctions en Java dans une base de données Oracle. Les procédures Oracle écrites Java référencent des méthodes statiques dans les classes compilées dans la base de données.

Les procédures en Java sont souvent utilisées pour développer les manipulations sur le système de fichier (move, copy, remove, list) car ces actions ne sont pas aisément réalisable avec le package UTL_FILE.

Mon objectif, est de retourner en paramètre OUT de ma procédure le contenu d'un dossier sur mon système de fichier. Le contenu est retourné sous la forme d'un tableau. Voici la procédure à suivre :

1. Définir le type tableau de chaînes de caractères qui contiendra les noms des fichiers
2. Compiler le code Java sur la base de données

Notez l'utilisation d'un array descriptor pour spécifier à Oracle comment transformer l'array de string en sortie.

3. Compiler le package/procédure qui appelle la méthode statique Java


Ainsi, vous pouvez profiter des fonctions de manipulation de fichier disponible dans le package java.io.

Notez que si vous souhaiter mettre un paramètre de type scalaire en sortie (OUT) il est nécessaire que votre méthode statique retourne un tableau de type scalaire étant donné que Java ne gère pas les paramètres passé en sortie.