El artículo y el proyecto de código acompañante superan el método que para superar los obstáculos que migran a aplicaciones Spring 5 y Spring Boot 2 en un contenedor de aplicaciones WebSphere 8.5 (WAS). Los problemas surgen como Spring está utilizando frascos de validación actualizados y, por defecto, usó una estrategia de carga de primera clase principal que se interpondría en el camino de una actualización.
Específicamente, se presentan varias opciones sobre cómo cambiar el cargador de clases para usar el último padre. Además, llamamos a los frascos específicos necesarios para el arranque de primavera y primavera en un proyecto de muestra JSP en su maven pom.xml.
Se espera, con estos cambios, puede migrar a una versión compatible de Spring mientras mantiene su inversión en 8.5. Eso es hasta que esos productos llegan al final de la vida.
De manera predeterminada, WebSphere Application Server 8.5.x (WAS8) utiliza la estrategia de cargador de clase Parent_First. En general, este medio fue cargará su versión de los frascos de Application Server (EE) primero y se priorizará sobre lo que está en su distribución.
Por ejemplo, puede tener una versión de la API de validación en su directorio web-Inf lib, pero la ruta de clase favorecerá la primera. Efectivamente, Baneando Shadow-Banning a su versión a favor de la versión JEE que vino fue. Esto tiene sentido, IBM pasó mucho tiempo certificando y probando su servidor de aplicaciones con un conjunto conocido de Javax.* Jars y quiere mantenerlo así de manera predeterminada.
El RUB se produce cuando desea usar una versión más nueva de Spring 5.x y Spring Boot 2.x y esas versiones están utilizando y confían en una versión más nueva de Javax Valtidation y Validación de Hibernate para su funcionalidad central. ¿A qué te dedicas?
La opción 1 es actualizar su servidor de aplicaciones. Esto bastante sencillo con Apache Tomcat, Open Liberty, JBoss y muchas otras implementaciones de código abierto. Esto porque un gran desafío fue. Muchas aplicaciones críticas y heredadas se han ejecutado fue de 8.5 con JDK 8.x durante años, y el negocio tiene poco deseo de pagar algunas pruebas de regresión costosas. Seguro que Spring 4.x es el final de la vida, pero todavía funciona, entonces, ¿por qué actualizar? La mejor respuesta no es que 5.x sea más genial y que me ayuda a mi reanudación. La verdadera respuesta son las vulnerabilidades. Ya no se le apoya y eso es un problema cuando, no si, las nuevas vulnerabilidades se encuentran en la naturaleza. Desea adelantarse a ese escenario.
¿Qué no era 9? Bueno, te dejo eso. Personalmente, si está migrando lejos de las 8. A menos que tenga alguna necesidad moribunda de personalización fue 8 funcionalidad, las implementaciones de código abierto anteriores funcionarán bien. Puede implementar tantos como desee en tantos lugares como desee en cualquier entorno, Cloud. contenedor o en preparación. Su elección y su CFO no le importará.
La opción que vamos a abordar aquí es simplemente cambiar el cargador de clases de los primeros a los padres al final. Esta no es una solución a largo plazo. Esto solo lo lleva al apoyo de la primavera y su negocio puede "brotar" para esos cambios. Lo consigues "primavera", estoy siendo Punny. Además, esto no es una bala de plata. Estoy seguro de que sus equipos de infraestructura han invertido en sus secuencias de comandos y tienen nodos bien ejecutados en grupos estables. La implementación de un nuevo nodo con el último último puede afectar a otras aplicaciones que no están migrando pero que están en la misma celda. ¿Qué haces allí?
Hay muchas formas de lograr esta tarea. No profundizaremos en esos detalles. Te daré tres (3) soluciones de alto nivel y te dejaré elegir.
Este es el más riesgoso y menos documentado. Aquí actualiza algunos archivos XML oscuros en su oído con anotaciones específicas de IBM y espera lo mejor. La ventaja es que no necesita alterar sus scripts. El inconveniente? No he podido demostrar que esto funciona en entornos de producción. A continuación se presentan algunos artículos de desbordamiento de pila sobre el tema. Comprador Cuidado
Este funciona y funciona muy bien con las versiones de desarrolladores de WAS o si tiene acceso a la consola de administración. Esta opción es una excelente manera de probar sus cambios. El principal problema, por supuesto, es que estos cambios no son escalables ni se pueden escribir. Es posible que le guste esta opción, pero es poco probable que sus equipos de infraestructura actualicen felizmente su oído después de cada implementación del módulo. Esta no es una opción Scable.
Esta es realmente su única opción para la producción. Deberá trabajar de la mano con sus equipos de infraestructura para actualizar sus scripts de implementación para cambiar el cargador de clases durante la implementación y antes de comenzar la aplicación. He incluido el archivo de Jython (PY) de un desarrollador de muestra (que significa altamente probado) para transmitir el punto a sus socios.
Puedes ver mi inspiración para el guión de Jython desde aquí
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" )Este cambio es totalmente en ti. Necesitará un servidor de desarrollador o un servidor local para ver y validar sus cambios, pero debe actualizar su pom.xml con cambios específicos para la validación y hibernar.
Después de su primera implementación, y después de cambiar el cargador de clase verá el siguiente error en los registros de SystemOut:
Causado por: java.lang.classnotfoundException: javax.validation.parameternameprovider
Spring 5.x se basa en la versión 2.x de la validación-API, por lo que deberá actualizar explícitamente la API en su POM. Nuevamente, esto solo es posible porque cambió el cargador de clase. Sin ese cambio, está atascado Cargando la versión 1.x desde la ruta de clase WAS. No hay solución al trabajo. Hay otros cambios si está utilizando páginas JSP. Vea el pom.xml en el proyecto WAS8-WAR.
Nota especial Si está utilizando Tiles 2.x, deberá actualizar a Tiles 3.x. Esa será otra publicación.
< dependency >
< groupId >javax.validation</ groupId >
< artifactId >validation-api</ artifactId >
< version >2.0.1.Final</ version >
</ dependency >Si bien no fue específico, debemos incluir la dependencia de Tomcat-Embed-Jasper para permitir que nuestra aplicación compile y represente las páginas JSP para la ejecución local. No se establece el alcance proporcionado
< dependency >
< groupId >org.apache.tomcat.embed</ groupId >
< artifactId >tomcat-embed-jasper</ artifactId >
< version >${tomcat-embed-jasper.version}</ version >
< scope >provided</ scope >
</ dependency >Consulte el Spring Boot 2.x Readme.md para los frascos adicionales requeridos.
Estás utilizando la configuración de Java si ha llegado tan lejos. Olvida la configuración XML de estilo antiguo. Eso fue tan primavera 4.x. Eres mejor que eso ahora.
Tenga en cuenta la ubicación de las páginas JSP: /Web-Inf/Vistas/
@ 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 ;
}
}Estamos extendiendo el abstractAnnotationConfigDispatcherServletinitializer para tener acceso a la configuración de clave. ¿Por qué? Podemos usar las clases de conveniencia proporcionadas por Spring en lugar de configurar manualmente el desplazamiento y/o 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 [] {
"/"
};
}