Comment modulariser une application JSF/Facelets/Spring avec OSGi?
je travaille avec de très grandes applications JSF / Facelets qui utilisent le ressort pour la gestion DI/bean. Mes applications ont une structure modulaire et je suis actuellement à la recherche d'approches pour standardiser la modularisation.
mon but est de composer une application web à partir d'un certain nombre de modules (peut-être en fonction l'un de l'autre). Chaque module peut contenir les éléments suivants:
- Classes;
- ressources statiques (images, CSS, les scripts);
- modèles de Facelets;
- haricots gérés-contextes D'application de printemps, avec demande, session et application-haricots scoped (alternative est JSF managed beans);
- Servlet API trucs - les servlets, les filtres, les auditeurs (c'est facultatif).
ce que je voudrais éviter (presque à tout prix) est la nécessité de copier ou d'extraire des ressources de module (comme des modèles de Facelets) à la guerre ou d'étendre le web.xml
pour les servlets de module, les filtres, etc. Il doit être suffisant pour ajouter le module (pot, paquet, artefact, ...) à l'application web (WEB-INF/lib
,bundles
, plugins
,...) pour étendre l'application web avec ce module.
actuellement Je résous cette tâche avec une solution de modularisation personnalisée qui est fortement basée sur l'utilisation des ressources classpath:
- ressources spéciales servlet sert les ressources statiques à partir des ressources classpath (JARs).
- Spécial Facelets ressources de résolution permet de chargement Modèles Facelet des ressources classpath.
- Printemps des charges de l'application des contextes via le modèle
classpath*:com/acme/foo/module/applicationContext.xml
- ceci charge les contextes d'application définis dans les jarres de module. - enfin, une paire de servlets et de filtres délègue le traitement des requêtes aux servlets et aux filtres configurés dans des contextes D'application de printemps à partir de modules.
les derniers jours J'ai lu beaucoup de choses sur OSGi et je pensais, comment (et si) je pourrais utiliser OSGi comme un standardisé approche de la modularisation. Je réfléchissais à la façon de résoudre des tâches individuelles avec OSGi:
- ressources Statiques - ensembles OSGi qui veulent exporter des ressources statiques, inscrivez un
ResourceLoader
instances avec le contexte bundle. Une centrale d'ResourceServlet
utilise ces chargeurs de ressources pour charger des ressources à partir de faisceaux. - modèles Facelet-similaire à ci-dessus, un
ResourceResolver
utilise des services enregistrés par bundles. - Managed beans - Je n'ai pas idée comment utiliser une expression comme
#{myBean.property}
simyBean
est défini dans l'un des faisceaux. - API des servlets - utilisez quelque chose comme WebExtender/Pax Web pour enregistrer les servlets, les filtres et ainsi de suite.
Mes questions sont:
- est-ce que j'invente un vélo ici? Y a-t-il des solutions standard pour cela? J'ai trouvé une mention de tranches de ressort mais n'ai pas pu trouver beaucoup de documentation à ce sujet.
- pensez-vous OSGi est la technologie qui convient à la tâche décrite?
- est-ce que mon croquis de L'application OSGI est plus ou moins correct?
- comment devrait-on traiter les haricots gérés (en particulier la demande/portée de la session)?
je serais généralement reconnaissants de vos commentaires.
5 réponses
ce que vous avez l'intention de faire semble faisable, avec quelques mises en garde:
La Couche De La Vue: tout d'abord, votre couche de vue semble un peu exagérée. Il y a d'autres façons de modulariser les composants JSF en utilisant des composants personnalisés qui éviteront les maux de tête liés à essayer de créer quelque chose d'aussi dramatique que les fèves gérées tardivement.
Les Modules Eux-Mêmes: Deuxièmement, vos modules ne semblent pas particulièrement modulaires. Votre première balle-liste cela donne l'impression que vous essayez de créer des applications web interopérables, plutôt que des modules en soi. Mon idée d'un module est que chaque composant a un but bien défini, et plus ou moins discret. Comme la façon dont ex sous-tend vi. Si vous suivez la voie OSGi, alors nous devrions définir modulaire comme ceci: modulaire, pour les besoins de cette discussion, signifie que les composants sont échangeables à chaud -- c'est-à-dire qu'ils peuvent être ajoutés et supprimé sans les casser App.
Dépendances: je suis un peu préoccupé par votre description des modules comme "peut-être dépendant les uns des autres."Vous le savez probablement (j'espère) déjà, mais vos dépendances devraient former un graphe acyclique dirigé. Une fois que vous introduisez une dépendance circulaire, vous demandez un monde de blessures en termes de maintenabilité éventuelle de l'application. Une des plus grandes faiblesses D'OSGi est qu'il ne pas prévenir les dépendances circulaires, de sorte c'est à vous de les appliquer. Sinon, vos dépendances se développeront comme des kudzu et étoufferont progressivement le reste de l'écosystème de votre système.
Servlets: Fuhgeddaboudit. Vous ne pouvez pas lier tardivement des servlets dans une application web, pas avant que la spécification Servlet 3.0 ne soit en production (comme Pascal L'a souligné). Pour lancer un servlet utilitaire séparé, vous aurez besoin de le mettre dans sa propre application.
OK, voilà pour les mises en garde. Réfléchissons à la façon dont cela pourrait travail:
Vous avez défini votre propre module JSF à faire... quoi, exactement? Donnons lui un but défini, assez trivial: un écran de connexion. Ainsi, vous créez votre écran de connexion, liez-le tardivement en utilisant OSGi dans votre application et... alors quoi? Comment fonctionne l'application de la fonctionnalité de connexion est là, si vous n'avez pas défini dans votre .jspx page? Comment l'application sait-elle naviguer vers quelque chose qu'elle ne peut pas savoir?
Il y a des moyens de contourner cela en utilisant les inclusions conditionnelles et les comme (par exemple, <c:if #{loginBean.notEmpty}>
), mais, comme vous l'avez dit, les choses deviennent un peu agitées quand votre loginBean géré existe dans un autre module qui n'a peut-être même pas encore été introduit à l'application. En fait, vous obtiendrez une exception de servlet à moins que ce loginBean existe. Alors que faites-vous?
vous définissez une API dans l'un de vos modules. toutes les fonctionnalités gérées que vous avez l'intention de partager entre les modules doivent être spécifiées en tant qu'interfaces dans cette couche API. Et tous vos modules doivent avoir par défaut les implémentations de ces interfaces qu'ils ont l'intention d'utiliser. Et cette API doit être partagée entre tous les modules interopérables. Ensuite, vous pouvez utiliser OSGi et Spring pour relier les haricots spécifiés avec leur mise en œuvre.
j'ai besoin de prendre un moment pour souligner que ce n'est pas ainsi que j'aborderais ce problème. Pas du tout. Étant donné quelque chose comme aussi simple qu'une page de connexion, ou même aussi compliqué qu'un diagramme de stock, je préfère personnellement créer un JSF personnalisé composant. Mais si l'exigence est "je veux que mes haricots managés soient modulables (c.-à-d., chaud-échangeable, etc), c'est la seule façon que je sais pour le faire fonctionner. Et je ne suis même pas tout à fait sûr que c' travail. cet échange de courriel suggère que c'est un problème sur lequel les développeurs de JSF ne font que commencer à travailler.
je considère normalement que les haricots managés font partie de la couche de vue, et en tant que tel je les utilise seulement pour la logique de vue, et délègue tout le reste pour la couche de service. Faire gérés fèves de liaison tardive est, à mon sens, la promotion de la couche de la vue et dans la logique d'affaires. Il ya une raison pour laquelle tous ces tutoriels sont tellement axés sur les services: parce que la plupart du temps, vous voulez considérer ce qu'il faudrait pour votre application pour exécuter "headless," et comment il serait facile de "peau" votre vue si, par exemple, vous vouliez qu'il fonctionne, avec toutes ses fonctionnalités, sur un téléphone Android.
mais cela ressemble à beaucoup de ce que vous êtes travailler avec est lui-même la logique de vue -- par exemple, le besoin de changer dans un modèle de vue différent. OSGi / Spring devrait être en mesure d'aider, mais vous aurez besoin de quelque chose dans votre application pour choisir entre les implémentations disponibles: à peu près ce que le Registre de Service D'OSGi a été construit pour faire.
cela laisse des ressources statiques. Vous pouvez modulariser ceux - ci, mais rappelez-vous, vous aurez besoin de définir une interface pour récupérer ces ressources, et vous aurez besoin de fournir une implémentation par défaut afin que votre application ne s'étouffer s'ils sont absents. Si i18n est une considération, cela pourrait être une bonne façon de faire. Si vous voulez être vraiment aventureux, alors vous pourriez pousser vos ressources statiques dans JNDI. Cela les rendrait complètement permutables, et vous éviterait la peine d'essayer de déterminer quelle implémentation utiliser programmatiquement, mais il y a quelques inconvénients: toute recherche ratée entraînera votre application à lancer une NamingException. Et c'est exagéré. JNDI est normalement utilisé dans les applications web pour app configuration.
en ce qui concerne vos questions restantes:
Est-ce que j'invente un vélo ici? Y a-t-il des solutions standard pour cela?
Vous êtes, un peu. J'ai vu des applications qui font ça!--14-->genre de chose, mais vous semblez avoir trébuché dans un assez unique ensemble d'exigences.
pensez-vous Qu'OSGi est la bonne technologie pour la tâche décrite?
Si vous avez besoin des modules échangeable à chaud, alors vos choix sont OSGi et l'interface plus léger ServiceLocator.
est-ce que mon croquis de L'application OSGI est plus ou moins correct?
Je ne peux pas vraiment le dire sans en savoir plus sur les limites de vos composants. Pour le moment, on dirait que vous poussez OSGi à faire plus que ce qu'elle est capable de faire.
mais ne me croyez pas sur parole. Iautres lecture de documents dans ces endroits.
Et depuis que vous vous posez sur le Printemps Tranches, cela devrait être suffisant pour vous aider à démarrer. Vous aurez besoin d'un client Git, et il semble que vous allez vous entraîner sur l'application en regardant à travers le code source. Et c'est le premier prototype de code.
je suis confronté aux mêmes problèmes dans mon projet actuel. À mon avis, OSGi est la solution la meilleure et la plus propre en termes de normes et de support futur, mais actuellement vous pouvez rencontrer quelques problèmes si vous essayez de l'utiliser dans une application web:
- il n'y a pas encore de solution bien intégrée entre un conteneur Web et la plateforme OSGi.
- OSGi peut être trop pour une application web de construction personnalisée qui est à la recherche d'une architecture modularisée simple. Je voudrais considérez OSGi si mon projet a besoin de supporter des extensions de tiers qui ne sont pas à 100% sous notre contrôle, si le projet a besoin de redéploiements à chaud, des règles d'accès strictes entre plugins, etc.
une solution personnalisée basée sur des chargeurs de classe et des filtres de ressources me semble très appropriée. Comme un exemple, vous pouvez étudier les code source de Hudson ou Plug-in Java Framework (JPF) Projet(http://jpf.sourceforge.net/).
comme étendre le web.xml, nous pouvons soyez chanceux avec le Servlet 3.0 specification(http://today.java.net/pub/a/today/2008/10/14/introduction-to-servlet-3.html#pluggability-and-extensibility).
le "web module deployment descriptor fragment" (alias web-fragment.xml) introduit par le Servlet 3.0 spécification serait bien ici. La spécification définit comme:
un fragment web est un fragment logique partitionnement de l'application web dans un tel façon que les cadres utilisés dans l'application web peut définir tous les artéfacts sans demander à devlopers modifier ou ajouter des informations dans le Web.XML.
Java EE 6 n'est peut-être pas une option pour vous maintenant. Ce serait pourtant la solution standardisée.
L'OSGi D'entreprise est un domaine assez nouveau donc ne pensez pas que vous obtiendrez une solution qui satisfait directement votre besoin. Cela dit, l'une des choses que j'ai trouvé manquant de Equinox (osgi moteur derrière eclipse et donc un avec la plus grande base d'utilisateurs!) est un service de configuration / DI cohérent. Dans mon projet récent, nous avions des besoins similaires et avons fini par construire un service osgi de configuration simple.
L'un des problèmes inhérents aux applications modulaires serait d'ordre, comme la visibilité du module pourrait empêcher l'accès de classe dans certains cas. Nous avons contourné cela en utilisant une politique de jumelage enregistré, qui n'est pas trop idéal, mais fonctionne.
outre la configuration, vous pouvez consulter le livre Equinox récemment publié pour obtenir des conseils sur L'utilisation D'OSGi comme base pour la création d'applications modulaires. Les exemples peuvent être spécifiques à Equinox, mais les principes fonctionneraient avec n'importe quel cadre OSGi. Lien - http://equinoxosgi.org/
vous devriez regarder dans le serveur DM de printemps (il est en transition à Eclipse Virgo mais qui n'a pas encore été publié). Il y a beaucoup de bonnes choses dans la récente spécification OSGi enterprise qui vient également d'être publiée.
certains des tutoriels de DM du printemps aideront, j'imagine. Mais oui, il est possible d'avoir des ressources et des classes chargées depuis l'extérieur du faisceau web en utilisant la modularité standard. En cela, c'est un bon ajustement.
comme pour le contexte de session - il obtient comme vous vous y attendiez dans une session. Cependant, vous pourriez rencontrer des problèmes avec le partage de cette session entre les faisceaux de sites Web dans la mesure où dans pas sûr si c'est même possible.
vous pouvez également chercher à avoir un seul paquet web et ensuite utiliser par exemple le Registre D'extension Eclipse pour étendre les capacités de votre application web.