Professional Documents
Culture Documents
Cette article prsente les bases du dveloppement d'une application modulaire. Il prsente galement un exemple complet d'implmentation en Java.
1 - Bases......................................................................................................................................................................3 2 - Modules.................................................................................................................................................................. 5 2.1 - Extension par les modules............................................................................................................................ 5 2.2 - Services fournis aux modules....................................................................................................................... 6 2.3 - Types de module........................................................................................................................................... 6 2.4 - Dpendance entre modules.......................................................................................................................... 6 3 - Implmentation des modules................................................................................................................................. 8 4 - Chargement des modules....................................................................................................................................10 4.1 - Cration d'un nouveau ClassLoader........................................................................................................... 10 4.2 - Ajout des classes dans le ClassLoader systme........................................................................................12 5 - Sparation de l'application...................................................................................................................................14 6 - Exemple complet..................................................................................................................................................15 6.1 - Le core.........................................................................................................................................................15 6.1.1 - La classe Core.................................................................................................................................... 15 6.1.2 - Le chargement des modules...............................................................................................................17 6.1.3 - Les extensions et services..................................................................................................................19 6.2 - Un module d'exemple..................................................................................................................................22 6.3 - L'application................................................................................................................................................. 22 6.4 - Rsultat........................................................................................................................................................ 23 7 - Conclusion............................................................................................................................................................26 8.1 - Les sources................................................................................................................................................. 26 7.2 - Remerciements............................................................................................................................................ 26
-2Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
1 - Bases
Dans cet article, je vais commencer par voquer les bases de conception d'une application modulaire, c'est--dire, dfinir ce qu'est une application modulaire, ce qu'est un module et bien entendu ce que a apporte. Dans les prochains chapitres, je vais essayer de dcrire les diffrentes problmatiques inhrentes au sujet et leurs rsolutions. Les exemples de code seront en Java, mais les concepts dcrits dans cet article peuvent s'appliquer tous les langages. Bien entendu, je ne me considre pas comme un spcialiste dans les applications modulaires et les diffrentes informations que je vais donner dans cet article ne dcoulent que de ma faon de voir, il y en a certainement d'autres et des meilleures, donc si vous n'tes pas d'accord avec moi ou si vous pensez qu'on peut faire mieux, n'hsitez pas me contacter pour me donner votre avis. Toute l'exprience que j'ai rside dans le dveloppement d'une application modulaire comme projet perso. Pour commencer, qu'est-ce qu'une application modulaire ? Une application modulaire est constitue de 2 parties bien distinctes : Le coeur : Comme son nom l'indique, il s'agit de la partie centrale de l'application. Cette partie doit tre compltement indpendante des modules. Les modules : Il s'agit cette fois des parties qu'on va ajouter dynamiquement au cur de l'application pour lui rajouter des fonctionnalits. On leur donne d'autres noms : extensions, briques, plugins, addons, ..., mais le concept est toujours le mme.
Il y a mon avis 2 sortes d'applications modulaires. Le premier type est une application somme toute normale qui propose une srie de fonctionnalits et qui propose en plus d'tendre ces fonctionnalits par le biais de modules. Le second type est une application qui propose un coeur compltement dnu de fonctionnalits. Toutes les fonctionnalits sont proposes par les modules, c'est donc une application dans laquelle "tout est module".
La diffrence principale est que la premire peut tre utilise tout fait normalement sans aucun module, alors que la deuxime ne propose pas (ou presque pas) de fonctionnalits sans module. Au contraire d'une application normale, il faut donc prvoir des points d'extensions que les modules pourront utiliser pour ajouter des fonctionnalits l'application ou pour modifier l'existant. Je me suis bas sur le deuxime type raliser mon logiciel. Cela permet d'avoir un socle solide qu'on peut ventuellement rutiliser pour d'autres applications sous rserve de quelques modifications (le mieux serait bien entendu de penser ce core de manire tout fait gnrique ds le dbut). Comme application modulaire connue, on peut citer Eclipse qui est entirement modulaire et qui est du deuxime type. Maintenant, la grande question est : C'est bien beau tout a, mais a sert quoi ? Tout d'abord, du point de vue du dveloppeur, cela permet de sparer clairement les diffrentes parties de l'application. On a donc des modules distincts plus faciles maintenir qu'une grosse application. Cela permet galement d'tre trs souple pour rajouter des fonctionnalits l'application, en effet, pour cela, il suffit de crer un nouveau module, d'y coder la fonctionnalit et de rajouter ce module dans l'application. Du point de vue de l'utilisateur, cela ajoute de la souplesse au programme. En effet, l'utilisateur va pouvoir choisir quels modules il veut lancer, rajouter de nouveaux modules, voire mme en crer s'il en est capable. Il pourra donc personnaliser son application. Nanmoins, cela va peut-tre compliqu la tche de l'utilisateur. Par contre, cela va beaucoup simplifier le travail en quipe sur une application. En effet, si un module ne ncessite pas plus d'une personne, il sera trs ais de travailler chacun sur un module et de ne faire les tests qu'avec son module et ensuite de tester l'application avec les modules des autres, une fois l'application termine. Bien entendu, cela ne se fait pas tout seul et ce n'est pas des plus simples concevoir et implmenter. En effet, cela pose beaucoup de problmatiques qu'il faut rgler et cela implique beaucoup de questions qu'il faut se poser.
-3Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
C'est ce que nous allons voir maintenant dans les prochains chapitres.
-4Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
2 - Modules
Aprs avoir dcrit dans le premier chapitre en quoi consistait une application modulaire et ce qu'tait un module, nous allons maintenant nous pencher plus spcialement sur les modules. Nous avons dit qu'un module permettait de rajouter des fonctionnalits l'application principale. Mais avant de se lancer dans le moindre code, il va falloir dfinir exactement ce que seront nos modules, ce qu'ils pourront faire, s'il y aura plusieurs types de modules, ...
Dans ces deux cas, il faut donc dfinir certains points d'extension. Dans le cas de JTheque, voici les points d'extension que j'ai cr pour mes modules : Rajouter des onglets dans la vue principale Rajouter des composants dans la barre d'tat Rajouter des lments dans le menu de la vue principale Rajouter des onglets dans la vue de configuration
A partir de ces points d'extension, les modules peuvent faire beaucoup de choses. Par exemple, si on veut faire une calculette, on peut imaginer rajouter un onglet principal avec une calculette, ou alors faire une fentre dedie et rajouter un lment dans le menu qui ouvrirait cette fentre. Ceci est donc laiss au libre choix du dveloppeur, mais il faut y penser avant et bien rflchir ce que a implique.
-5Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
Vous pouvez bien sr ajouter autant de services que vous le dsirez. Mais pensez nanmoins ne par surcharger le core. Quitte le rendre modulaire au niveau des services. En effet, certaines applications n'auront peut-tre pas besoin de certains services, alors pourquoi les charger ?
mais ce peut tre des modifications, dans ce cas, il faut prvoir que le module pourra tre accd de l'extrieur et pas et ce qui sera faisable sur un module depuis un autre module. Bref, cela n'entre pas dans le cadre de cet article, mais dans le cas d'une application complexe, il est possible que vous ayiez considrer ce point.
-7Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
On pourrait donc crer un module trs simple affichant quelque chose sur la console : SimpleModule.java
package org.modules.simple; public class SimpleModule implements IModule { public void plug(){ System.out.println("Hello kernel !"); } public void unplug(){ System.out.println("Bye kernel !"); } public String getName(){ return "Simple module"; }
Nous allons donc crer un fichier Jar contenant notre classe. Il faut maintenant une solution pour que l'application principale connaisse cette classe pour la lancer. Il faut donc un moyen pour qu'elle trouve cette classe.
-8Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
On pourrait imaginer parcourir le fichier jar et tester pour chacun des classes si c'est un module ou non. Cette mthode bien que tout fait faisable et fonctionnelle n'est pas du tout efficace car elle implique de parcourir toute l'archive ce qui risque de prendre du temps dans le cas de gros module. Alors, on va utiliser les outils que nous offre Java et ajouter une mention dans le manifest du jar pour indiquer l'application principale quelle est la classe du module charger. Voil quoi ressemblerait notre Manifest pour notre petit module : MANIFEST.MF
Cela permettra l'application principale de savoir quelle classe charger. Une autre solution serait d'utiliser la notion de "services" introduit dans Java 6. Pour cela, on peut crer un fichier "/Meta-Inf/services/name" ou name est le nom complet (avec le package) de notre interface de module. Dans ce fichier, on va dclarer toutes les classes implmentant notre interface, par exemple notre SimpleModule. Lorsque Java va charger ces Jars, il va lire ces fichiers et garder une trace des classes concrtes. Ensuite, on peut utiliser la classe ServiceLoader pour rechercher et instancier tous nos modules. Par exemple : Utilisation des services de Java 6
for (IModule module : ServiceLoader.load(IModule.class)) { System.out.println( module.getName() ); }
Pour plus d'informations sur cette fonctionnalit, je vous invite consulter le site officiel. Je montrerai dans le prochain chapitre une manire de charger ces modules. Car il ne suffit pas de mettre ces fichiers jars dans le classpath pour les charger tant donn que l'application principale ne les connat pas.
-9Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
On va donc crer une classe ModuleLoader qui va nous permettre d'effectuer ces phases. Prenons maintenant la premire phase et crons une mthode qui retourne la liste des classes charger. ModuleLoader.java
public class ModuleLoader { private static List<URL> urls = new ArrayList<URL>(); private static List<String> getModuleClasses(){ List<String> classes = new ArrayList<String>(); //On liste les fichiers de module File[] files = new File("dossier").listFiles(new ModuleFilter()); for(File f : files){ JarFile jarFile = null; try { //On ouvre le fichier JAR jarFile = new JarFile(f); //On rcupre le manifest Manifest manifest = jarFile.getManifest(); //On rcupre la classe String moduleClassName = manifest.getMainAttributes().getValue("Module-Class"); classes.add(moduleClassName); urls.add(f.toURI().toURL()); } catch (IOException e) { e.printStackTrace(); } finally { if(jarFile != null){ try { jarFile.close(); - 10 Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
ModuleLoader.java
} }
return classes;
private static class ModuleFilter implements FileFilter { @Override public boolean accept(File file) { return file.isFile() && file.getName().toLowerCase().endsWith(".jar"); } }
Comme vous le voyez, ce n'est pas trs compliqu, on parcours les fichiers Jar existant dans le dossier des modules, on ouvre le fichier Jar, on rcupre le manifest et on rcupre la classe du module. Ensuite, on ajoute l'URL du fichier Jar la liste des URLs. Bien entendu ce code est perfectible, il faudrait traiter le cas o le fichier JAR n'a pas de manifest ou alors le cas ou le manifest n'a pas de classe de module et il faudrait traiter les erreurs correctement, mais ce n'est pas le but de ce billet. On peut maintenant passer la deuxime mthode qui va crer le ClassLoader et instancier les modules puis les retourner : loadModules()
private static ClassLoader classLoader; public static List<IModule> loadModules(){ List<IModule> modules = new ArrayList<IModule>(); List<String> classes = getModuleClasses(); AccessController.doPrivileged(new PrivilegedAction<Object>(){ @Override public Object run() { classLoader = new URLClassLoader( urls.toArray(new URL[urls.size()]), ModuleLoader.class.getClassLoader()); return null; } }); for(String c : classes){ try { Class<?> moduleClass = Class.forName(c, true, classLoader); if(IModule.class.isAssignableFrom(moduleClass)){ Class<IModule> castedClass = (Class<IModule>)moduleClass; IModule module = castedClass.newInstance(); } modules.add(module);
} catch (ClassNotFoundException e1) { e1.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); }
- 11 Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
loadModules()
} return modules;
On commence donc crer un nouveau ClassLoader partir des URLs qu'on a rcupr avec les fichiers JARs. On va utiliser un URLClassLoader qui permet de charger des classes depuis des emplacements dfinis par des URLs. On va lui donner comme parent le ClassLoader de la classe. Comme cela les modules qui utiliseront ce classloader pourront galement utiliser les classes de l'application, ce qui est le but d'une application modulaire. Une fois qu'on a cr notre ClassLoader, on va parcourir toutes nos classes et les instancier si elles implmentent bien la bonne interface. Ensuite, on va pouvoir les ajouter la liste et les retourner. Encore une fois, ce code est perfectible, il faudrait traiter les erreurs et ragir aux diffrents cas possibles, mais j'ai essay de faire au plus court. Notre chargeur de modules est donc termin. La technique prsente dans ce billet pose nanmoins un problme pour ce qui est du dploiement la vole de module. En effet, si on charge un module aprs le chargement des premiers modules, on devra recrer un nouveau ClassLoader et on aura donc une partie des modules dans le premier ClassLoader et une partie des modules dans le second ClassLoader. Nanmoins, si les modules n'ont aucune intraction entre eux, vous pouvez tout fait envisager cette mthode pour le dploiement la vole. Si ce n'est pas le cas, vous serez oblig de vous rabattre sur la mthode par rflction pour ajouter des modules dans votre ClassLoader. Je prsenterai peut-tre cette mthode dans un prochain billet. Le fait d'avoir un deuxime ClassLoader pose galement un problme pour les librairies qui chargent des classes la vole comme par exemple Spring IOC ou Hibernate. Il faut voir au cas par cas pour ces librairies comment on peut leur spcifier d'utiliser notre ClassLoader. Souvent ceci est faisable en spcifiant le contextClassLoader via la mthode Thread.currentThread().setContextClassLoader(ClassLoader cl).
- 12 Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
Comme vous le voyez, on ne fait qu'utiliser la Reflection pour ajouter une URL au ClassLoader. Cette mthode est valable pour tout URLClassLoader. Nanmoins, je vous dconseille d'utiliser cette mthode moins d'en avoir vraiment besoin. Il est plus propre d'utiliser son propre ClassLoader.
- 13 Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
5 - Sparation de l'application
Une autre chose qu'il est intressant de considrer quand on pense une application modulaire est l'application en elle-mme. Doit elle tre intgre au core ? Doit elle tre compltement indpendante de l'application qui l'emploie. L'une et l'autre de ses faons de voir ont leurs avantages et inconvnients : Le core est li l'application : Ce type de core est fait pour une application bien spcifique. C'est--dire qu'il n'est destin tre utilis que par cette application et des modules pour cette application. Si on prend un exemple tout bte, cela voudra dire que le core connat le nom de l'application et c'est lui qui a les informations sur les crdits de l'application. C'est peut tre simpliste comme exemple, mais imaginez que vous dveloppiez une nouvelle application et que vous vous basiez sur un Core de ce genre et que vous ne pouvez pas changer le nom de l'application ni l'auteur dans les crdits, ce n'est pas de plus pratiques. ce type de core peut tre une application modulaire de type 1 ou 2. Le core est compltement indpendant de l'application : Ce prcdent type de core est entirement gnrique et peut tre utilis par n'importe quelle application. Si on reprend l'exemple d'avant, cette fois-ci, le core ne connatra pas le nom de l'application, c'est cette dernire qui doit configurer le core pour qu'il affiche son nom. Donc vous n'tes plus embts si vous voulez l'utiliser avec votre application alors qu'il a t cr pour une autre. Ce core est obligatoirement de type 2. En effet, cela n'aurait pas de sens d'y mettre des fonctionnalits si on veut pouvoir utiliser ce core avec n'importe quelle application. Imaginez une application de jeux pour enfants qui contiendrait une calculatrice scientifique en anglais de base ainsi que les cours de la bourse. Pas vraiment pratique, non ? Ceci est donc encore un point qu'il faut dfinir avant de concevoir son application modulaire. Voici quelques questions qu'il faut se poser : Est-ce que mon core devra contenir des fonctionnalits ou non ? Est-ce que mon core est mon application ? Est-ce que mon core pourra tre utilise par plusieurs applications ?
En fonction des rponses, ce n'est pas trs difficile de s'orienter vers un choix entre les 2 types de Core. Il faut quand mme noter qu'il n'est pas trs lourd de sparer la partie application de la partie core, mme aprs coup.
- 14 Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
6 - Exemple complet
Maintenant que nous avons vu tous les concepts de base, ainsi que les points spcifiques de l'implmentation. Nous allons dvelopper une petite application modulaire exemple qui va utiliser tous les concepts prsents dans cet article. On va crer une application du type 2, c'est--dire sans aucune fonctionnalit de base, elle ne sert rien sans module. De plus, on va crer un core qui puisse tre utilis par n'importe quel application. Cette application sera des plus simples, une simple vue avec une zone de texte dans laquelle les modules pourront ajouter des lignes. On va ajouter un service permettant de logguer des messages. Et un autre service fournira une mthode pour ajouter du texte dans la vue, ce sera notre point d'extension.
6.1 - Le core
On va maintenant implmenter le Core de l'application.
ViewManager.getInstance().display();
Voil ce qu'on y fait : 1 2 3 4 5 Chargement des modules Chargement des services Utilisation d'un service pour logguer quelque chose Dmarrage des modules Affichage de la vue de l'application
exit()
public void exit(){ for(IModule module : modules){ module.unplug(); } ViewManager.getInstance().close(); } LogManager.getInstance().log("Fermeture de l'application");
Encore plus simple. Voil ce qu'on y fait : 1 2 3 Extinction des modules Fermeture de la vue Logge d'un message de fermeture
Et voici maintenant le code complet avec les getters/setters, les champs et la javadoc. Ca se passe de commentaire : Core.java
package org.dvp.core; import java.util.List; /** * Le coeur de notre applicaiton modulaire. * * @author Baptiste Wicht */ public class Core { private static final Core instance = new Core(); private String applicationFolder; private List<IModule> modules; private String applicationName; /** * Retourne l'instance unique du core. * * @return L'instance unique du core. */ public static Core getInstance() { return instance; } /** * Lance l'application et dmarre tous les modules. */ public void launch(){ modules = ModuleLoader.loadModules(); LogManager.getInstance().init(); ViewManager.getInstance().init(); LogManager.getInstance().log("Chargement des modules"); for(IModule module : modules){ module.plug(); } } LogManager.getInstance().log(module.getName() + " OK. ");
ViewManager.getInstance().display();
/** * Ferme l'application et stoppe tous les modules. - 16 Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
Core.java
*/ public void exit(){ for(IModule module : modules){ module.unplug(); } ViewManager.getInstance().close(); } LogManager.getInstance().log("Fermeture de l'application");
/** * Retourne le dossier dans lequel l'application se trouve. * * @return Le dossier de l'application. */ public String getApplicationFolder() { return applicationFolder; } /** * Modifie le dossier dans lequel l'application se trouve. * * @param applicationFolder Le dossier de l'application. */ public void setApplicationFolder(String applicationFolder) { this.applicationFolder = applicationFolder; } /** * Retourne le nom de l'application. * * @return Le nom de l'application. */ public String getApplicationName() { return applicationName; } /** * Modifie le nom de l'application. * * @param applicationName Le nom de l'application. */ public void setApplicationName(String applicationName) { this.applicationName = applicationName; }
package org.dvp.core; java.io.File; java.io.FileFilter; java.io.IOException; java.util.jar.Manifest; java.util.jar.JarFile; java.util.ArrayList; java.util.List; java.net.URL; java.net.URLClassLoader; java.security.AccessController; java.security.PrivilegedAction;
- 17 Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
ModuleLoader.java
/** * Classe responsable du chargement des modules. * * @author Baptiste Wicht */ public class ModuleLoader { private static List<URL> urls = new ArrayList<URL>(); private static ClassLoader classLoader; /** * Charge tous les modules et les retourne. * * @return Une List contenant tous les modules pralablement chargs. */ public static List<IModule> loadModules() { List<IModule> modules = new ArrayList<IModule>(); List<String> classes = getModuleClasses(); AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { classLoader = new URLClassLoader( urls.toArray(new URL[urls.size()]), ModuleLoader.class.getClassLoader()); } return null;
});
for (String c : classes) { try { Class<?> moduleClass = Class.forName(c, true, classLoader); if (IModule.class.isAssignableFrom(moduleClass)) { Class<IModule> castedClass = (Class<IModule>) moduleClass; IModule module = castedClass.newInstance(); modules.add(module); } } catch (ClassNotFoundException e1) { e1.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); }
} }
return modules;
/** * Retourne toutes les classes de modules charger. * * @return Une List contenant les noms des classes instancier. */ private static List<String> getModuleClasses() { List<String> classes = new ArrayList<String>(); //On liste les fichiers de module File[] files = new File(Core.getInstance().getApplicationFolder() + "/modules/").listFiles(new ModuleFilter()); for (File f : files) { JarFile jarFile = null; try { - 18 Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
ModuleLoader.java
//On ouvre le fichier JAR jarFile = new JarFile(f); //On rcupre le manifest Manifest manifest = jarFile.getManifest(); //On rcupre la classe String moduleClassName = manifest.getMainAttributes().getValue("Module-Class"); classes.add(moduleClassName);
} }
urls.add(f.toURI().toURL()); } catch (IOException e) { e.printStackTrace(); } finally { if (jarFile != null) { try { jarFile.close(); } catch (IOException e) { e.printStackTrace(); } } }
return classes;
/** * Un filtre de fichiers pour les modules. Ce filtre ne prend en compte que les fichiers .jar. * * @author Baptiste Wicht */ private static class ModuleFilter implements FileFilter { @Override public boolean accept(File file) { return file.isFile() && file.getName().toLowerCase().endsWith(".jar");
La seule diffrence est qu'on parcours le dossier "modules" du dossier de l'application. Pour plus d'explications, rfrez-vous au chapitre 4. ou ce code est expliqu.
package org.dvp.core; /** * Manager donnant aux modules la possibilit de logguer des messages. * * @author Baptiste Wicht */ public class LogManager { private static final LogManager instance = new LogManager(); /** * Retourne l'instance unique de LogManager. *
- 19 Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
LogManager.java
* @return L'instance unique de LogManager. */ public static LogManager getInstance() { return instance; } /** * Initialise le service. */ public void init(){ //Rien faire ici (c'est pour l'exemple) } /** * Loggue un message. * * @param message Le message logguer. */ public void log(String message){ System.out.println("Log : " + message); }
Comme vous pouvez le voir, il n'y a rien de compliqu dans cette classe. J'ai ajout une mthode init() pour l'exemple, car en pratique, vous aurez presque toujours quelque chose faire pour charger le service. On va passer maintenant, au service de vue. Ce service va simplement proposer d'afficher la vue, de la fermer et d'y ajouter du texte. Voici ce qu'il va donner : ViewManager.java
package org.dvp.core; /** * Manager permettant de grer la vue de l'application. * * @author Baptiste Wicht */ public class ViewManager { private static final ViewManager instance = new ViewManager(); private CoreView view; /** * Retourne l'instance unique de ViewManager. * * @return L'instance unique de ViewManager. */ public static ViewManager getInstance() { return instance; } /** * Initialise le service. */ public void init() { view = new CoreView(); } /** * Affiche la vue. */ public void display() { view.setVisible(true); } /** * Ferme la vue. */
- 20 Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
ViewManager.java
public void close() { view.dispose(); } /** * Affiche du texte sur la vue. * * @param text Le texte afficher. */ public void displayText(String text) { view.addText(text); }
L encore, rien de spcial redire. On va maintenant dfinir la vue. On va utiliser une JFrame contenant un JTextArea pour afficher le texte. Voici ce que a pourrait donner : CoreView.java
import import import import
/** * Vue principale de l'application. * * @author Baptiste Wicht */ public class CoreView extends JFrame { private final JTextArea textArea; /** * Construit la vue. */ public CoreView(){ super(); setSize(640, 480); setTitle(Core.getInstance().getApplicationName()); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); addWindowListener(new WindowCloseListener()); textArea = new JTextArea("Texte des modules : \n"); add(new JScrollPane(textArea), BorderLayout.CENTER); } setLocationRelativeTo(null);
/** * Ajoute un texte dans la vue. * * @param message Le message ajouter. */ public void addText(String message){ textArea.append('\t' + message + '\n'); } /** * Le listener pour fermer l'application complte lorsqu'on ferme la fentre. * * @author Baptiste Wicht */ private static class WindowCloseListener extends WindowAdapter { @Override public void windowClosing(WindowEvent e) { Core.getInstance().exit(); - 21 Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
CoreView.java
} } }
Ce qu'on peut noter, c'est qu'on rcupre le nom de l'application pour le titre de la fentre. Il faut aussi avertir le core de la fermeture de l'application. Dans notre cas, ce n'est pas des plus utiles tant donn qu'il n'y a aucune ressource librer. Mais en pratique, on aura toujours quelque chose librer dans une application.
@Override public void unplug() { LogManager.getInstance().log("I'm out !"); } @Override public String getName() { return "Module super simple"; }
6.3 - L'application
Maintenant qu'on a un core et un module, on va crer l'application permettant de configurer le core et de le lancer. ApplicationModulaire.java
- 22 Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
ApplicationModulaire.java
* @author Baptiste Wicht */ public class ApplicationModulaire { /** * Lance le core de l'application. * * @param args Les argument de ligne de commandes. Ignors. */ public static void main(String[] args) { Core.getInstance().setApplicationFolder(System.getProperty("user.dir")); Core.getInstance().setApplicationName("Application modulaire 1.0. "); Core.getInstance().launch(); } }
6.4 - Rsultat
On va donc lancer maintenant notre application. Pour cela, il va falloir dployer nos diffrentes parties sous forme de fichier .jar. Le core : On va exporter notre core dans le fichier Core.jar la racine du dossier de l'application. Rien de spcial mettre dans le manifest pour cette partie. Le module : On va exporter notre module dans le fichier SimpleModule.jar dans le sous-dossier modules du dossier de l'application. Il faut spcifier le nom de la classe de module dans le manifest : MANIFEST.MF
L'application : On va exporter notre application dans le fichier Application.jar dans le dossier de l'application. Ici, il faut spcifier la classe main dans le fichier manifest et il faut ajouter Core.jar dans le classPath : MANIFEST.MF
Maintenant que nos diffrents fichiers sont crs, on va lancer notre programme. Pour cela, on peut soit lancer Application.jar comme une application normale, soit utiliser la commande java -jar pour bnficier de la console. Avec cette deuxime option voici le rsultat :
- 23 Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
Vue de l'application
- 24 Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
Affichage console Comme nous le voyons, notre module a bien affich ses 2 lignes dans la vue et ses 2 messages dans la console. Notre test est concluant. Nous avons cr une application modulaire !
- 25 Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/
7 - Conclusion
Voil, vous avez maintenant les bases pour crer votre premire application modulaire. Les concepts restent globalement les mmes en passant une application plus grosse. Nanmoins, il faut faire plus attention du ct de la conception, ne pas surcharger les modules et les services. Il devient galement intressant d'utiliser des interfaces de spcifications pour les services. On peut ainsi donner accs aux modules un certain panel de fonctionnalit alors que le Core a accs la totalit des fonctionnalits. Mais aprs ce ne sont que des concepts de programmation gnraux qui ne se rattachent pas la programmation modulaire.
7.2 - Remerciements
Merci dgouyette pour sa correction orthographique ainsi qu' Mikrob pour ses commentaires.
- 26 Les sources prsentes sur cette pages sont libres de droits, et vous pouvez les utiliser votre convenance. Par contre la page de prsentation de ces sources constitue une oeuvre intellectuelle protge par les droits d'auteurs. Copyright 2009 - Baptiste Wicht. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' 3 ans de prison et jusqu' 300 000 E de dommages et intrts.
http://baptiste-wicht.developpez.com/tutoriel/java/modularisation/application/