22.12.2012

Java EE: Загрузка классов в Jboss Application Server 7.

Когда приложение Java EE запускается на сервере - происходит поиск и загрузка необходимых классов. Сторонние зависимости могут находится в JAR библиотеках, которые поставляются с программой; в библиотеках которые предоставляются сервером; а иногда - в других приложениях, запущенных на данном экземпляре сервера. Если приложение содержит множество зависимостей, есть вероятность столкнуться с разными неприятными ситуациями. Что будет, если сервер предоставляет библиотеку, а в это же время другая версия этой библиотеки присутствует в приложении? Можно убрать ее из приложения и перейти на версию, поставляемую с сервером. В принципе, если это не получится, можно убрать библиотеку с сервера и использовать свою версию. А если другим запускаемым программам нужна именно та версия, которая есть на сервере? Говоря в общем, если зависимостей много, одни и те же библиотеки доступны в разных местах (на сервере, в приложении, в другом приложении и т.п.), встречайте - JAR hell. Для того чтобы избавиться от подобных проблем при использовании Jboss AS 7, нужно понять каким образом организована загрузка классов и как можно с успехом манипулировать зависимостями приложения.

Jboss Modules.

По сравнению с ранними версиями Jboss AS, в Jboss AS 7 подход к загрузке классов изменился. При загрузке классов используются модули. Каждое запущенное приложение представляет собой изолированный модуль, которому присваивается имя. Если это WAR архив, то имя модуля будет следующим:
 
deployment.[deployment_name]
 
Например для веб-приложения webapp.war имя соответствующего модуля будет выглядеть как
 
deployment.webapp.wa
 
Для EAR архивов  модуль будет назван таким образом:
 
deployment.[ear_deployment_name].[sub_deployment_name]
 
То есть, если webapp.war находится в EAR архиве enterpriseapp.ear, то имя модуля будет выглядеть как
 
deployment.enterpriseapp.ear.webapp.war
 
Зависимости поставляемые с сервером также включены в модули. Помимо существующих на сервере модулей, с легкостью можно создать собственный. Например если какая-то библиотека требуется всем приложениям на сервере, возможно есть смысл не включать ее в каждое приложение, а добавить один модуль на сервер.
Итак, модули изолированы друг от друга. Запущенное приложение получает доступ к другим модулям (зависимостям) в следующих случаях:

1. Если зависимость добавляется сервером по умолчанию. 2. Если сервер самостоятельно обнаружит необходимость добавления той или иной зависимости к приложению (неявные зависимости).  3. Если  в настройках приложения явно указано, какие модули нужно использовать.  По умолчанию добавляются такие зависимости как javax.xml, javax.security и другие. Сервер самостоятельно добавляет некоторые зависимости, если обнаружит необходимость их использования. Например, если в программе есть JAX-RS аннотации, то будет добавлен модуль org.jboss.resteasy: Выше показаны некоторые зависимости по умолчанию, а также каким образом добавляются некоторые неявные зависимости, подробнее про последние можно посмотреть  в документации. Теперь посмотрим как настроить использование зависимостей. MANIFEST.MF Для добавления зависимостей можно использовать файл MANIFEST.MF, который должен находиться в в директории META-INF EAR или WAR архива. Предположим, что у нас есть веб-приложение WebApp.war, которое будет использовать Apache Xerces. Для того, чтобы приложению был доступен соответствующий модуль, поставляемый с Jboss 7, необходимо указать зависимость так:

 
Если зависимостей несколько, то названия можно указывать через запятую. Для того, чтобы зависимости WebApp.war могли быть доступны другим приложениям запущенным на сервере, достаточно после имени зависимости указать слово export:
 

Теперь другие запущенные приложения могут использовать модуль org.apache.xerces, который предоставляет им WebApp.war. Для этого, в зависимое приложение нужно добавить WebApp.war как зависимость:

Кроме того, если экспортировать зависимостьиз EAR архива, то она будет доступна всем содержащимся в EAR архиве приложениям по умолчанию (без добавления экспортированной зависимости в каждое из этих приложений). jboss-deployment-structure.xml Для более гибкой настройки использования зависимостей  используется специфичный для Jboss файл конфигурации  jboss-deployment-structure.xml. Он должен быть расположен в директории META-INF для EAR архивов и в WEB-INF для WAR архивов. При этом надо учитывать, что если WAR архив расположен внутри EAR, то  jboss-deployment-structure.xml из WAR архива будет игнорироваться. Предположим, наше веб-приложение WebApp.war использует Apache Xerces, а также реализацию JSF 1.2. Однако с Jboss 7 по умолчанию поставляется библиотека реализации JSF 2. Так как JSF является неявной зависимостью предоставляемой сервером, нужно вручную исключить использование JSF 2. А в качестве зависимости укажем org.apache.xerces и реализацию JSF 1.2 (с Jboss поставляется не одна версия JSF):

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
    <deployment>
        <exclusions>
           <module name="com.sun.jsf-impl"/>
        </exclusions>
        <dependencies>
           <module name="org.apache.xerces"/>
           <module name="com.sun.jsf-impl" slot="1.2"/>
        </dependencies>
    </deployment>
</jboss-deployment-structure>

Добавив в список зависимостей org.apache.xerces мы добились того же, чего можно достигнуть добавлением зависимостей в MANIFEST.MF. Исключать неявно добавляемые зависимости тоже бывает полезно - например, чтобы избежать конфликта, если в приложении необходимо использовать свою версию библиотеки, которая есть и на сервере. Аналогично, как и в MANIFEST.MF, можно экспортировать зависимости:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
    <deployment>
        <dependencies>
           <module name="org.apache.xerces" export="true"/>
        </dependencies>
    </deployment>
</jboss-deployment-structure>

Как упомянуто выше,  jboss-deployment-structure.xml должен быть расположен в архивах верхнего уровня. Для управления зависимостями вложенных архивов, используется секция sub-deployment. Если WebApp.war находится внутри EAR архива, то зависимости нужно указывать в jboss-deployment-structure.xml EAR.

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>    
  <sub-deployment name="WebApp1.war">
    <dependencies>
    </dependencies>
  </sub-deployment>
  <sub-deployment name="WebApp2.war">
    <dependencies>
    </dependencies>
  </sub-deployment>
</jboss-deployment-structure>

Все приложения внутри одного EAR архива "видят" друг друга. Если нужно изолировать их друг от друга, то следует поставить значение true для параметра ear-subdeployments-isolated:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
  <ear-subdeployments-isolated>true</ear-subdeployments-isolated>     
  <sub-deployment name="WebApp1.war">
    <dependencies>
    </dependencies>
  </sub-deployment>
  <sub-deployment name="WebApp2.war">
    <dependencies>
    </dependencies>
  </sub-deployment>
</jboss-deployment-structure>

Таким образом, с помощью jboss-deployment-structure.xml доступно достаточно много возможностей для управления зависимостями - добавление и экспорт зависимостей, исключение неявных зависимостей, изоляция вложенных в EAR архивов друг от друга. Создание модулей с зависимостями. Если несколько приложений используют какую-то библиотеку и вы хотите добавить зависимость в виде одного модуля на сервер - это сделать просто, необходимо просто создать свой модуль, аналогичный тем, которые уже имеются на сервере. Модули с зависимостями находятся в каталоге [SERVER_HOME]/modules. Имя модуля может не совпадать с названием библиотеки, которую он предоставляет, и определено в конфигурационном файле для каждого модуля - module.xml, который выглядит примерно так:

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.apache.xerces">

    <resources>
        <resource-root path="xercesImpl-2.9.1-jbossas-1.jar"/>
        <!-- Insert resources here -->
    </resources>

    <dependencies>
        <module name="javax.api"/>
    </dependencies>

</module>

По материалам из книги Francesco Marchioni - JBoss AS 7 Configuration, Deployment and Administration



Теги: jboss javaEE java

comments powered by Disqus