Управление зависимостями при миграции приложений и в новых приложениях для WebSphere Application Server V8Источник: IBM
В данной статье рассматриваются действия по эффективному управлению корпоративными приложениями с использованием IBM Rational Application Developer V8.0 для IBM WebSphere Application Server V8.0. В ней также предоставляется подробная информация об исследовании поведения WebSphere Application Server при загрузке классов посредством Class Loader Viewer (программа просмотра загрузчика классов). Материал был опубликован в журнале IBM WebSphere Developer Technical Journal. С помощью IBM WebSphere Application Server компании могут предложить своим пользователям более богатые возможности за счет быстрого внедрения инновационных приложений. Разработчики могут быстро приступить к созданию приложений и использовать свой опыт, выбрав из обширного набора поддерживаемых программных моделей, основанных на открытых стандартах, ту, которая позволит им лучше согласовать требования к проекту с возможностями программной модели и опытом разработки. Кроме того, WebSphere Application Server ускоряет доставку приложений, стимулируя повторное использование и увеличивая продолжительность жизни существующих прикладных активов. IBM Rational Application Developer предоставляет единую универсальную среду разработки, удовлетворяющую разнообразным требованиям, - от Web-интерфейсов до серверных приложений, от индивидуальной разработки до коллективной, от Java™-разработки до интеграции приложений. Rational Application Developer является частью платформы IBM Rational Software Development Platform, серии продуктов, основанных на платформе с открытыми исходными кодами Eclipse, предназначенной для создания инструментов разработки приложений. Все продукты семейства Rational для настольных ПК предоставляют единую интегрированную среду разработки (IDE). Эти продукты отличаются плагинами, имеющимися в каждой конфигурации. Управление зависимостями играет важную роль в сценариях после миграции и при разработке приложений с очень большим количеством JAR-файлов для WebSphere Application Server. Возможны ситуации, когда, например, выполняется миграция кода приложения с конкурирующей платформы, совместимой со спецификациями Java 1.4, на WebSphere Application Server V8, который основан на самых последних спецификациях Java. Если при этом зависимости не упорядочены, могут возникать исключительные ситуации, связанные с классами. Хотя каждый сервер приложений имеет свой собственный способ хранения JAR-файлов приложений, лучше упорядочить эти JAR-файлы, используя возможности, предоставляемые Rational Application Developer и WebSphere Application Server. В данной статье рассматривается управление зависимостями посредством Rational Application Developer V8.0 и WebSphere Application Server V8.0. Основное внимание уделяется сценариям настройки приложений после их миграции, однако большая часть представленной информации применима и в других ситуациях. EAR-файл, сгенерированный инструментарием Rational (рисунок 1), содержит EJB-модуль и Web-модуль с необязательным клиентом приложения, модулем-коннектором и т.д., а также дескрипторы развертывания, идентифицирующие каждый модуль:
Рисунок 1. Структура EAR-файла приложения Поскольку EAR-файл может иметь более одного EJB- и Web-модуля, существует вероятность следующих ситуаций:
Примерами таких зависимостей являются регистраторы событий, XML-анализаторы и т.д. В следующем разделе рассматривается эффективное управление такими ситуациями. Во время развертывания приложения или после его миграции, когда EAR-файл перенесен в рабочую область Rational Application Developer, важным шагом является анализ архитектуры приложения для идентификации используемых им библиотек. Приложение может состоять из инфраструктур с открытыми исходными кодами, таких как Struts, Spring, Hibernate и т.д., не считая обычных JSP-страниц, сервлетов и EJB-компонентов. Во многих случаях зависимости этих инфраструктур размещаются только в Web-модуле. Некоторые зависимости, такие как регистратор событий (например, log4j), будут использоваться обоими модулями - EJB и Web. Как упоминалось выше, при этом может происходить дублирование классов в EJB- и Web-модулях, поскольку они используются в обоих. Кроме того, приложение может иметь много JAR-зависимостей для поддержки JAR-файлов инфраструктуры. Эти зависимости имеют внутренние ссылки друг на друга и могут быть важны для выполнения приложения. Некоторые серверы приложений с открытыми исходными кодами объединяют свои JAR-файлы в EAR-файлы, добавляя лишние зависимости. Одним из примеров является j2ee.jar, который определяет J2EE-классы. Количество этих JAR-файлов можно уменьшить за счет компоновки кода приложения с использованием среды времени исполнения WebSphere Application Server V8.0, предоставляемой с инструментарием Rational. Это можно сделать путем настройки среды времени исполнения сервера приложений в аспектах проекта. Одним из вариантов является использование для разрешения зависимостей приложения JAR-файлов {APPSERVER_ROOT}/plugins с префиксом javax.j2ee.* и org.apache.*. Это потребует единовременных затрат на перекомпоновку исходного кода. (Имейте в виду, что javax.j2ee.servlet.jar и com.ibm.ws.runtime.jar загружаются во время начальной загрузки сервера.) После идентификации зависимостей можно приступить к распределению JAR-файлов. Управление JAR-файлами для Web-модуля Web-модуль состоит из JSP-страниц и сервлетов, которые могут быть расширены стандартными библиотеками шаблонов (JSTL и т.д.), инфраструктурами MVC и ORM (Struts, Hibernate и т.д.), XML-инфраструктурами, Web-сервисами и т.д. В зависимости от способа использования библиотек количество JAR-файлов может увеличиваться экспоненциально, поэтому требуются специальные меры по управлению. Эти JAR-файлы обычно хранятся в каталоге WEB-INF/lib (рисунок 2) и загружаются загрузчиком классов WAR по умолчанию. JAR-файлы можно поместить в эту папку при помощи Rational Application Developer. Позднее мы обсудим, сколькими JAR-файлами можно управлять. Рисунок 2. Каталог WEB-INF/lib Управление зависимостями для EJB-модулей Java-архивы, на которые ссылаются классы в EJB-модулях, могут храниться в общей библиотеке EAR-уровня, которую можно создать при помощи Rational Application Developer. Для импорта внешних JAR-файлов как общей библиотеки EAR-уровня необходимо импортировать их как Java EE-файлы Utility Jar. Для этого:
Зависимости на EAR-уровне видимы как для EJB-, так и для Web-модуля. Поэтому JAR-файлы пользовательского приложения, которые совместно используются несколькими модулями, можно вместе со сторонними JAR-файлами поместить в это место, следуя описанным выше инструкциям. Совместное использование классов приложения несколькими модулями Возможны сценарии, когда EAR-файл приложения имеет дублирующиеся Java-классы в EJB- и Web-модулях. Эти дублирующиеся классы могут храниться в отдельном общем модуле, т.е. Utility-модуле (вспомогательный Java-модуль). В Rational Application Developer можно создать Utility-модуль внутри EAR, выбрав File > New > Other... > Java EE > Utility Project (см. рисунок 7). Рисунок 7. Выбор проекта Utility-модуля Присвойте имя проекту Utility Project и свяжите его с существующим EAR-файлом (см. рисунок 8). При этом в EAR создастся папка lib. Если папка lib уже существует (например, после импорта JAR-файлов описанным выше способом), Utility-модуль будет скопирован как JAR-файл в эту папку после экспорта EAR. Рисунок 8. Присвоение имени проекту Utility Project Для совместного использования классов несколькими модулями скопируйте все Java-классы вместе со всей иерархией в папку src данного проекта Utility-модуля (см. рисунок 9). Рисунок 9. Классы в общем проекте Utility-модуля Рисунок 11. Содержимое папки lib Рисунок 12. Классы в jar-файле SharedClassesUtility Для компоновки кода в других модулях (Web и EJB), ссылающихся на общий Utility-модуль, можно добавить ссылку на него в каждый модуль, из которого нужно обращаться к его классам (рисунок 13). Рисунок 13. Ссылка на общий Utility-модуль в других модулях На рисунках 14 и 15 показан порядок загрузки классов сервером WebSphere Application Server для конкретного EAR. Рисунок 14. Классы, видимые для Web-модуля Рисунок 15. Классы, видимые для EJB-модуля Управление дополнительными зависимостями вне EAR Если количество приложений с несколькими JAR-зависимостями приводит к чрезмерному увеличению размера EAR, лучше хранить эти JAR-файлы во внешней папке и связывать их с приложением как общие библиотеки. Для создания общей библиотеки создайте папку где-нибудь в файловой системе (желательно в {APPSERVER_ROOT}) и укажите ее местоположение в поле Classpath Environment > Shared libraries (рисунок 16). Рисунок 16. Настройка общей библиотеки После настройки можно связать общую библиотеку с приложением, выбрав Applications > Enterprise Applications > {Application Name} > Shared library references и связав ее с либо EAR-, либо с Web-модулем (рисунок 17). Рисунок 17. Связывание общей библиотеки с EAR Теперь посмотрим, как можно использовать программу просмотра загрузчика классов, доступную в консоли администратора WebSphere Application Server, для исследования поведения загрузчика классов во время исполнения. Эта информация полезна при решении проблем, связанных с загрузкой классов. Есть два вида загрузчиков классов, играющих важную роль на сервере WebSphere Application Server. Загрузчик классов приложения группирует EJB-модули (Enterprise JavaBean™), общие библиотеки, архивы адаптера ресурсов (RAR-файлы) и JAR-файлы зависимостей, связанные с приложением. JAR-файлы зависимостей - это JAR-файлы, содержащие код, который могут использовать корпоративные bean-компоненты и сервлеты. Загрузчик классов приложения является родителем загрузчика классов архива Web-приложения (WAR). По умолчанию Web-модуль имеет свой собственный загрузчик WAR-классов, который используется для загрузки содержимого Web-модуля. Значение политики загрузчика WAR-классов загрузчика классов приложения определяет, используется ли для загрузки содержимого Web-модуля загрузчик WAR-классов или загрузчик классов приложения. Рисунок 18. Диаграмма иерархии загрузчиков классов По умолчанию в качестве политики загрузчика классов на уровне сервера, связанной с WebSphere Application Server V8.0, используется Multiple with parent class loader first (несколько, сначала родительский загрузчик классов). Это означает, что каждый EAR получает свой собственный загрузчик классов и в каждом приложении библиотеки EAR-уровня загружаются первыми, а за ними следуют Web-библиотеки. Для анализа поведения загрузчика классов при помощи Class Loader Viewer мы будем использовать библиотеку log4j и проследим его поведение для политик загрузки классов при загрузке в EJB-модуль, Web-модуль или в оба модуля. Class Loader Viewer можно вызвать в консоли администратора, выбрав Troubleshooting > Class loader viewer > server1 > {ВАШЕ ПРИЛОЖЕНИЕ}. Поведение загрузчика классов с PARENT_FIRST Сначала загружаются библиотеки приложения, а затем Web-библиотеки. JAR-зависимости помещаются в WEB-INF/lib, если будут использоваться только классами Web-модуля, тогда как созданные разработчиком откомпилированные Java-классы помещаются в WEB-INF/classes. Рассмотрим два случая:
Обнаружение дублирующихся и имеющих несколько версий JAR-файлов Две версии одной и той же библиотеки, помещенные в одни и те же или разные места EAR, могут привести к конфликтам классов, таким как проблемы разных версий. Предположим, например, что на EAR-уровне имеется версия 1 JAR-файла, содержащая метод f(), а на Web-уровне имеется версия 3 этого же JAR-файла, содержащая метод f(String), а метод f() удален за ненужностью. Если класс приложения пытается обратиться к f(String), он получает ошибку java.lang.NoSuchMethodError, поскольку классы в Web-модуле могут видеть только JAR-файлы, загруженные загрузчиком классов приложения, который не имеет метода f(String). Для контроля этой ситуации на уровнях EAR- и Web-модуля хранятся и проверяются при помощи Class Loader Viewer две версии log4j (см. рисунок 21). Рисунок 21. Обнаружение дублирующихся JAR-файлов Поведение загрузчика классов с PARENT_LAST Если настройки загрузки классов меняются на PARENT_LAST, загрузчику Web-классов дается приоритет перед загрузчиками классов приложения. В этом случае Web-приложения не могут видеть классы, доступные на EAR-уровне. Рисунок 22 показывает, что ../WEB-INF/lib/log4j.jar загружается до ../TestApp.ear/lib/log4j-1.2.16.jar (сравните с рисунком 21). Рисунок 22. Политика загрузчика классов Parent Last Тестирование сценариев приложения Контрольный тест, содержащийся в материалах для загрузки, демонстрирует конфигурацию библиотеки log4j и общего Utility-модуля, который может вызываться из классов приложений, основанных как на EJB-, так и на Web-модулях. Для записи отдельных log-файлов из EJB- и Web-модулей создаются два файла свойств log4j. Эти файлы свойств хранятся в специальной папке {PROFILE_ROOT}/log4jProperty (см. рисунки 23 и 24). Чтобы log4j.jar был виден классам во всех модулях EAR, он хранится в библиотеке EAR-уровня. Рисунок 23. Папка файлов свойств log4j Рисунок 24. Файлы свойств log4j Соответствующие файлы свойств загружаются в соответствующие модули, как показано на рисунках 25 и 26. Рисунок 25. Загрузка файла свойств в EJB Рисунок 26. Загрузка файла свойств в сервлет Поскольку библиотеки log4j используются в обоих модулях (EJB и Web), зависимости должны храниться так, чтобы быть видимыми в обоих модулях (рисунок 27). Рисунок 27. Сгенерированные log-файлы Этот тест демонстрирует совместное использование общих классов приложения в нескольких модулях. Для тестирования мы разработали класс TestSharedUtility, который можно успешно вызвать из EJB и Web-модулей и зарегистрировать ответ (см. рисунки 28, 29 и 30). Рисунок 28. Класс Shared Utility Рисунок 29. Вызов класса из EJB-модуля Рисунок 30. Вызов класса из Web-модуля Для тестирования конфликтов классов создаются две JAR-зависимости с двумя методами, имеющими одинаковое название, но разные параметры. Предполагается, что метод зависимости 1 устарел и был удален из зависимости 2. Хотя может быть несколько вариантов хранения этих зависимостей, в данном случае зависимость 1 хранится как вспомогательный JAR-файл на EAR-уровне, а зависимость 2 хранится в каталоге WEB-INF/lib. Зная, что зависимость 1 загружается загрузчиком классов приложения, а зависимость 2 загружается загрузчиком Web-классов, рассмотрим поведение при вызове из сервлета (см. рисунки 31 и 32). Рисунок 31. Сигнатура метода класса Version1 Рисунок 32. Сигнатура метода класса Version2 В случае Version2 метод f() был удален. Более старый JAR-файл version1test.jar хранится на EAR-уровне, тогда как более новый JAR-файл version2test.jar хранится в WEB-INF/lib (см. рисунок 33). Рисунок 33. Местоположение скопированных JAR-файлов Результаты, показанные на рисунке 34, предполагают, что тестовый сервлет хочет вызвать метод более нового JAR-файла и что предыдущий JAR-файл хранится на EAR-уровне по ошибке. Рисунок 34. Вызов новой версии метода При выполнении теста классы файла version1test.jar будут видимы сервлету и потому сгенерируют исключительную ситуацию, приведенную в листинге 1. Трассировка исключительной ситуации
Устранить исключительную ситуацию можно либо путем удаления файла version1test.jar из EAR и сохранения другого в WEB-INF/lib, либо путем замены version1test.jar на version2test.jar и удаления последнего из WEB-INF/lib, если его классы также нужно вызывать из EJB. Планирование зависимостей при проектировании нового приложения или выполнении миграции всегда является хорошим подходом. Оно не только помогает лучше управлять приложением, но и уменьшает сложность разрешения проблем, связанных с классами.
|