Статья и сопровождающий код проект проходит по методу, который для преодоления препятствий, мигрирующих в приложения Spring 5 и Spring Boot 2 в контейнере приложения WebSphere 8.5 (IS). Проблемы возникают, поскольку Spring использует обновленные валидационные банки и по умолчанию использовал родительскую стратегию загрузки первого класса, которая будет стоять на пути обновления.
В частности, представлены несколько параметров о том, как изменить загрузчик класса, чтобы использовать родителей в последний раз. Кроме того, мы вызовываем конкретные банки, необходимые для весенней и весенней загрузки в образце проекта JSP в вашем Maven pom.xml.
Ожидается, что с этими изменениями вы можете перейти на поддерживаемую версию Spring, сохраняя при этом ваши инвестиции в 8,5. Это до тех пор, пока эти продукты не достигнут конца жизни.
По умолчанию WebSphere Application Server 8.5.x (WAS8) использует стратегию загрузчика класса Parent_First. В общем, это означает, что сначала загрузит свою версию банок Server (EE) и расстанет приоритет над тем, что находится в вашем распределении.
Например, у вас может быть одна версия API Validation в вашем каталоге Web-Inf Lib, но путь класса будет способствовать тому, чтобы он был первым. Эффективно тени в пользу вашей версии в пользу версии JEE, которая пришла. Это имеет смысл, IBM потратил много времени на сертификацию и тестирование своего сервера приложений с известным набором Javax.* Jars, и он хочет сохранить его таким образом по умолчанию.
RUB происходит, когда вы хотите использовать более новую версию Spring 5.x и Spring Boot 2.x, и эти версии используются и полагаются на более новую версию Javax Valtidation и Hibernate Validation для их основной функции. Что вы делаете?
Вариант 1 - обновить ваш сервер приложений. Это довольно прямо с Apache Tomcat, Open Liberty, JBoss и многими другими реализациями с открытым исходным кодом. Это потому, что отличная задача была. Многие критические и устаревшие заявки работали, было 8,5 с JDK 8.x в течение многих лет, и у бизнеса мало желания оплатить некоторое дорогое регрессионное тестирование. Конечно, Spring 4.x - это конец жизни, но все еще работает, так зачем обновлять? Лучший ответ не в том, что 5.x прохладнее и помогает моему резюме. Реальный ответ - уязвимости. Вы больше не поддерживаются, и это проблема, когда, если не если, в дикой природе обнаружены новые уязвимости. Вы хотите опередить этот сценарий.
Что не было 9? Что ж, я оставляю это до вас. Лично, если вы мигрируете от 8. Если у вас нет какой -то умирающей потребности в обычаях, была 8 функциональных возможностей, приведенные выше реализации с открытым исходным кодом подойдут очень хорошо. Вы можете развернуть столько, сколько вы хотите в столько местах, сколько хотите в любой среде, Cloud. контейнер или в прут. Ваш выбор и ваш финансовый директор не заботятся.
Вариант, который мы собираемся обратиться здесь, - это просто переключение класса -загрузчика с родителя на первое место на родину в последний раз. Это не долгосрочное решение. Это просто приводит вас к поддержке весны, и ваш бизнес может «воспользоваться» для этих изменений. Вы получаете это «весна», я пыл. Также это не серебряная пуля. Я уверен, что ваши инфраструктурные команды инвестировали в свои сценарии и имеют хорошо бегущие узлы в стабильных кластерах. Развертывание нового узла с родителем в последний раз может повлиять на другие приложения, которые не мигрируют, но находятся в той же ячейке. Что ты там делаешь?
Есть много способов выполнить эту задачу. Мы не будем углубиться в эти специфики. Я дам вам три (3) решения высокого уровня и позволю вам выбрать.
Это самый рискованный и наименее задокументированный. Здесь вы обновляете какой -то неясный XML -файл в ухо с конкретными аннотациями IBM и надеетесь на лучшее. Плюс в том, что вам не нужно изменять свои сценарии. Недостаток? Я не смог доказать, что это работает в производственных средах. Ниже приведены некоторые статьи переполнения стека по теме. Покупатель остерегается
Этот работает и отлично работает с версиями разработчиков WAS или, если у вас есть доступ к Admin Console. Этот вариант - отличный способ доказать ваши изменения. Основная проблема, конечно же, заключается в том, что эти изменения не являются масштабируемыми и не могут быть сценария. Вам может понравиться этот вариант, но вряд ли ваши инфраструктурные команды с радостью обновят ваше ухо после каждого развертывания модуля. Это не Scable Option.
Это действительно ваш единственный вариант для производства. Вам нужно будет работать рука об руку с вашими инфраструктурными командами, чтобы обновить свои сценарии развертывания, чтобы изменить загрузку класса во время развертывания и перед началом приложения. Я включил файл Jython (PY) образца разработчика (что означает, что он не тестируется) Jython (PY), чтобы донести точку зрения на ваши партнеры.
Вы можете увидеть мое вдохновение для сценария Jython отсюда
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" )Это изменение полностью на вас. Вам понадобится сервер разработчиков или локальный сервер, чтобы увидеть и проверить ваши изменения, но вам необходимо обновить свой POM.xml с конкретными изменениями для проверки и спячки.
После первого вы развертываете, и после изменения загрузчика класса вы увидите ошибку ниже в журналах Systemout:
Вызвано: java.lang.classnotfoundexception: javax.validation.parameternameprovider
Spring 5.x полагается на версию 2.x версии-API , поэтому вам нужно будет четко обновить API в вашем POM. Опять же, это возможно только потому, что вы изменили загрузчик класса. Без этого изменения вы застряли по загрузке версии 1.x с пути класса. Там нет работы. Есть и другие изменения, если вы используете страницы JSP. Смотрите Pom.xml в проекте WAS8-WAR.
Специальное примечание , если вы используете Tiles 2.x, вам нужно будет перейти на Tiles 3.x. Это будет еще один пост.
< dependency >
< groupId >javax.validation</ groupId >
< artifactId >validation-api</ artifactId >
< version >2.0.1.Final</ version >
</ dependency >Хотя это не было конкретным, нам нужно включить зависимость Tomcat-embed-jasper, чтобы позволить наше приложение компилировать и отображать страницы JSP для локального бега. Не применение установлено на предоставление
< dependency >
< groupId >org.apache.tomcat.embed</ groupId >
< artifactId >tomcat-embed-jasper</ artifactId >
< version >${tomcat-embed-jasper.version}</ version >
< scope >provided</ scope >
</ dependency >См. Spring Boot 2.x readme.md для получения дополнительных банок.
Вы используете Java Config, если вы зашли так далеко. Забудьте о конфигурации старого стиля XML. Это было так весна 4.x. Вы лучше, чем это сейчас.
Обратите внимание на местоположение для страниц JSP: /web-inf/views/
@ 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 ;
}
}Мы расширяем AbstractAnnotationConfigDispatcherServletinitializer, чтобы иметь доступ к конфигурации ключей. Почему? Мы можем использовать удобные классы, предоставленные Spring, вместо ручной настройки DispatcherServlet и/или 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 [] {
"/"
};
}