L'article et le projet de code accompagnant passent en revue la méthode qui pour surmonter les obstacles migrant vers les applications Spring 5 et Spring Boot 2 dans un conteneur d'applications WebSphere 8.5 (était). Les problèmes surviennent lorsque Spring utilise des pots de validation mis à jour et a par défaut une stratégie de chargement de première classe de Parent qui ferait obstacle à une mise à niveau.
Plus précisément, plusieurs options sont présentées sur la façon de modifier le chargeur de classe pour utiliser Parent Last. De plus, nous appelons les pots spécifiques requis pour le démarrage du printemps et du ressort dans un exemple de projet JSP dans votre maven pom.xml.
On s'attend à ce que, avec ces modifications, vous pouvez migrer vers une version prise en charge du printemps tout en maintenant votre investissement était de 8,5. C'est jusqu'à ce que ces produits atteignent la fin de la vie.
Par défaut, WebSphere Application Server 8.5.x (Was8) utilise la stratégie de chargeur de classe Parent_First. En général, cela signifie que sa version des pots de serveur d'applications (EE) se chargera d'abord et se privilégiera ce qui est dans votre distribution.
Par exemple, vous pouvez avoir une version de l'API de validation dans votre répertoire Web-Inf lib, mais le chemin de classe favorisera le premier. Bannant efficacement votre version en faveur de la version JEE qui est venue avec. Cela a du sens, IBM a passé beaucoup de temps à certifier et à tester son serveur d'applications avec un ensemble connu de Javax. * JARS et il veut le garder par défaut.
Le RUB survient lorsque vous souhaitez utiliser une version plus récente de Spring 5.x et Spring Boot 2.x et que ces versions utilisent et s'appuient sur une version plus récente de Javax Valtidation et Hibernate Validation pour leur fonctionnalité de base. Que fais-tu?
L'option 1 consiste à mettre à niveau votre serveur d'applications. Cet assez simple avec Apache Tomcat, Open Liberty, JBoss et de nombreuses autres implémentations open source. Ceci parce qu'un grand défi avec était. De nombreuses applications critiques et héritées fonctionnaient de 8,5 avec JDK 8.x depuis des années, et l'entreprise a peu de désir de payer des tests de régression coûteux. Bien sûr, le printemps 4.x est la fin de la vie, mais cela fonctionne toujours, alors pourquoi mettre à niveau? La meilleure réponse n'est pas que 5.x est plus cool et qu'il aide mon CV. La vraie réponse est les vulnérabilités. Vous n'êtes plus soutenu et c'est un problème lorsque, pas si, de nouvelles vulnérabilités se trouvent dans la nature. Vous voulez prendre de l'avance sur ce scénario.
Qu'est-ce que non 9? Eh bien, je vous laisse ça. Personnellement, si vous migrez de 8 ans. À moins que vous ayez un besoin de moule mourant, il était de 8 fonctionnalités, les implémentations open source ci-dessus feront très bien. Vous pouvez en déployer autant que vous le souhaitez dans autant d'endroits que vous le souhaitez sur n'importe quel environnement, cloud. conteneur ou sur site. Votre choix et votre directeur financier ne s'en soucieront pas.
L'option que nous allons aborder ici est de simplement passer le Classloader de Parent First to Parent dernier. Ce n'est pas une solution à long terme. Cela vous amène simplement à soutenir le printemps et votre entreprise peut "ressortir" pour ces changements. Vous comprenez "printemps", je suis punny. Ce n'est pas non plus une solution miracle. Je suis sûr que vos équipes d'infrastructure ont investi dans leurs scripts et ont des nœuds bien en cours dans des grappes stables. Le déploiement d'un nouveau nœud avec Parent peut affecter une autre application qui ne migrerait pas mais qui sont dans la même cellule. Que faites-vous là-bas?
Il existe de nombreuses façons d'accomplir cette tâche. Nous ne nous plongerons pas dans ces détails. Je vais vous donner trois (3) solutions de haut niveau et vous laisser choisir.
C'est le plus risqué et le moins documenté. Ici, vous mettez à jour un fichier XML obscur dans votre oreille avec des annotations spécifiques IBM et espérez le meilleur. L'avantage est que vous n'avez pas besoin de modifier vos scripts. L'inconvénient? Je n'ai pas pu prouver que cela fonctionne dans les environnements de production. Vous trouverez ci-dessous quelques articles de débordement de pile sur le sujet. Acheteur Bénéficiant
Celui-ci fonctionne et fonctionne très bien avec les versions des développeurs de WA ou si vous avez accès à la console Admin Was. Cette option est un excellent moyen de prouver vos modifications. Le problème majeur est bien sûr que ces changements ne sont pas évolutifs et ne peuvent pas être scénarisés. Vous aimerez peut-être cette option, mais peu probable que vos équipes d'infrastructure mettent joyeusement à jour votre oreille après chaque déploiement du module. Ce n'est pas une option scable.
C'est vraiment votre seule option pour la production. Vous devrez travailler main dans la main avec vos équipes d'infrastructure pour mettre à jour leurs scripts de déploiement pour modifier le Classloader pendant le déploiement et avant de démarrer l'application. J'ai inclus un fichier Jython (PY) d'un exemple de développeur (qui ne signifie pas très testé) pour faire passer le point à vos partenaires.
Vous pouvez voir mon inspiration pour le script Jython d'ici
print ( "Get Deployments : " )
deployments = AdminConfig . getid ( '/Deployment:' + APP_NAME + '/' )
print deployments
print ( "" )
print ( "Deployment Object" )
deploymentObject = AdminConfig . showAttribute ( deployments , 'deployedObject' )
print deploymentObject
myModules = AdminConfig . showAttribute ( deploymentObject , 'modules' )
myModules = myModules [ 1 : len ( myModules ) - 1 ]. split ( " " )
print myModules
for module in myModules :
if ( module . find ( 'WebModuleDeployment' ) != - 1 ):
AdminConfig . modify ( module , [[ 'classloaderMode' , 'PARENT_LAST' ]])
AdminConfig . save ()
print ( "Set module to PARENT_LAST" )Ce changement est totalement sur vous. Vous aurez besoin d'un serveur de développeurs ou d'un serveur local pour voir et valider vos modifications, mais vous devez mettre à jour votre pom.xml avec des modifications spécifiques pour la validation et l'hibernate.
Après votre premier déploiement, et après avoir modifié le chargeur de classe, vous verrez l'erreur ci-dessous dans les journaux Systemout:
Causé par: java.lang.classnotfounonxception: javax.validation.Parameternameprovider
Spring 5.x s'appuie sur la version 2.x de la validation-API , vous devrez donc mettre à niveau explicitement l'API dans votre POM. Encore une fois, cela n'est possible que car vous avez changé le chargeur de classe. Sans ce changement, vous êtes coincé à charger la version 1.x à partir du chemin de classe WAS. Il n'y a pas de travail. Il y a d'autres modifications si vous utilisez des pages JSP. Voir le POM.xml dans le projet Was8-War.
Remarque spéciale Si vous utilisez des carreaux 2.x, vous devrez passer à des carreaux 3.x. Ce sera un autre poste.
< dependency >
< groupId >javax.validation</ groupId >
< artifactId >validation-api</ artifactId >
< version >2.0.1.Final</ version >
</ dependency >Bien que ne soit pas spécifique, nous devons inclure la dépendance au jastre Tomcat-Embed pour permettre à notre application de compiler et de rendre les pages JSP pour l'exécution locale. Pas la portée n'est définie que
< dependency >
< groupId >org.apache.tomcat.embed</ groupId >
< artifactId >tomcat-embed-jasper</ artifactId >
< version >${tomcat-embed-jasper.version}</ version >
< scope >provided</ scope >
</ dependency >Voir le Spring Boot 2.x Readme.md pour les pots supplémentaires requis.
Vous utilisez Java Config si vous êtes allé aussi loin. Oubliez la configuration XML à l'ancienne. C'était tellement printemps 4.x. Vous êtes meilleur que ça maintenant.
Veuillez noter l'emplacement des pages JSP: / web-inf / vues /
@ Configuration
@ EnableWebMvc
@ ComponentScan ( basePackages = { "org.scavino" })
public class AppConfig {
/**
* ViewResolver allows setting properties such as
* prefix (/WEB-INF/views/) or suffix (*.jsp) to the view name to generate
* the final view page URL. In our case this is how
* we will configure JSP pages.
*
* @return JSP resolver with prefix set to /WEB-INF/views/
*/
@ Bean
public InternalResourceViewResolver resolver () {
InternalResourceViewResolver resolver = new InternalResourceViewResolver ();
resolver . setPrefix ( "/WEB-INF/views/" );
resolver . setSuffix ( ".jsp" );
return resolver ;
}
}Nous étendons l'abstractannotationConfigDispatcherservleTitializer pour avoir accès à la configuration de clé. Pourquoi? Nous pouvons utiliser les classes de commodité fournies par Spring au lieu de configurer manuellement DispatcherServlet et / ou ContextLoaderListener
public class SpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@ Override
protected Class <?> [] getRootConfigClasses () {
return null ;
}
@ Override
protected Class <?> [] getServletConfigClasses () {
return new Class [] {
AppConfig . class
};
}
@ Override
protected String [] getServletMappings () {
return new String [] {
"/"
};
}