Статьи

Модули JBoss отстой, невозможно использовать пользовательские Resteasy / JAX-RS под JBoss 7

Поскольку JBoss EAP 6.1 / AS 7.2.0 является модульным и вы можете исключить, какие модули видны вашему веб-приложению, можно ожидать, что будет легко игнорировать встроенную реализацию JAX-RS (Rest Easy 2.3.6) и использовать пользовательский (3.0.6). Однако, к сожалению, это не так. Вы застряли на том, что предлагает официальное руководство, то есть глобальном обновлении Rest Easy — при условии, что никакое другое веб-приложение, работающее на сервере, не будет повреждено при обновлении.

Этого должно быть достаточно, чтобы исключить встроенный Rest Easy и иметь возможность использовать версию, включенную в веб-приложение:

1
2
3
4
5
6
7
8
9
<!-- jboss-deployment-structure.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
   <deployment>
       <exclude-subsystems>
           <subsystem name="resteasy"/>
       </exclude-subsystems>
   </deployment>
 </jboss-deployment-structure>

Однако это далеко не работает. Это почти делает работу (хотя некоторые исключения могут быть ненужными):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!-- jboss-deployment-structure.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
   <deployment>
       <exclude-subsystems>
           <subsystem name="resteasy"/>
       </exclude-subsystems>
     <exclusions>
       <module name="org.apache.log4j" />
       <module name="org.apache.commons.logging"/>
       <module name="org.jboss.as.jaxrs"/>
       <module name="org.jboss.resteasy.resteasy-jaxrs"/>
       <module name="org.jboss.resteasy.resteasy-cdi"/>
       <module name="org.jboss.resteasy.jackson-provider"/>
       <module name="org.jboss.resteasy.resteasy-atom-provider"/>
       <module name="org.jboss.resteasy.resteasy-hibernatevalidator-provider"/>
       <module name="org.jboss.resteasy.resteasy-jaxb-provider"/>
       <module name="org.jboss.resteasy.resteasy-jettison-provider"/>
       <module name="org.jboss.resteasy.resteasy-jsapi"/>
       <module name="org.jboss.resteasy.resteasy-multipart-provider"/>
       <module name="org.jboss.resteasy.resteasy-yaml-provider"/>
       <module name="org.codehaus.jackson.jackson-core-asl"/>
       <module name="org.codehaus.jackson.jackson-jaxrs"/>
       <module name="org.codehaus.jackson.jackson-mapper-asl"/>
       <module name="org.codehaus.jackson.jackson-xc"/>
       <module name="org.codehaus.jettison"/>
       <module name="javax.ws.rs.api"/>
     </exclusions>
   </deployment>
 </jboss-deployment-structure>

Однако только почти. Проблема в том, что исключение javax.ws.rs.api не имеет никакого эффекта. Кажется, что основные API Java EE не могут быть исключены. Тупик.

Кстати, это мои последние зависимости, связанные с jax-rs:

1
2
3
4
5
6
// resteasyVersion = '3.0.6.Final'
compile group: 'org.jboss.resteasy', name: 'jaxrs-api', version: resteasyVersion
compile group: 'org.jboss.resteasy', name: 'resteasy-jaxrs', version: resteasyVersion
compile group: 'org.jboss.resteasy', name: 'resteasy-jackson2-provider', version: resteasyVersion // JSONP
compile group: 'org.jboss.resteasy', name: 'async-http-servlet-3.0', version: resteasyVersion // Required at runtime
compile group: 'org.jboss.resteasy', name: 'resteasy-servlet-initializer', version: resteasyVersion // Required at runtime

Примерная история неудачных попыток

Я уже не помню точно все тупики, через которые я прошел, но вот примерный обзор исключений, которые я получил при развертывании или во время выполнения.

1
java.lang.ClassNotFoundException: org.jboss.resteasy.plugins.server.servlet.HttpServlet30Dispatcher

— исправлено скорее всего путем добавления org.jboss.resteasy:async-http-servlet-3.0:3.0.6.Final зависимостей

1
java.lang.ClassCastException: myapp.rs.RestApplication cannot be cast to javax.servlet.Servlet

— исправлено, скорее всего, путем добавления org.jboss.resteasy:resteasy-servlet-initializer:3.0.6.Final зависимостей

1
java.lang.NoSuchMethodError: org.jboss.resteasy.spi.ResteasyProviderFactory.<init>(Lorg/jboss/resteasy/spi/ResteasyProviderFactory;)V

— исправлено, вероятно, путем добавления большего количества модулей RestEasy / Jackson в список исключений

1
java.lang.NoSuchMethodError: org.jboss.resteasy.specimpl.BuiltResponse.getHeaders()Ljavax/ws/rs/core/MultivaluedMap;

— это то, что невозможно исправить; проблема в том, что BuiltResponse из resteasy-jaxrs наследуется от javax.ws.rs.core.Response однако версия этого класса из jaxrs-api-3.0.6.Final.jar игнорируется в пользу Response от JAX-RS 1.1 от модуль /jboss-eap-6.1.0/modules/system/layers/base/javax/ws/rs/api/main/jboss-jaxrs-api_1.1_spec-1.0.1.Final-redhat-2.jar ( /jboss-eap-6.1.0/modules/system/layers/base/javax/ws/rs/api/main/jboss-jaxrs-api_1.1_spec-1.0.1.Final-redhat-2.jar ), в котором отсутствует метод getHeaders и, как уже упоминалось, его нельзя исключить. (Спасибо allprog за намеки на этот конфликт !)

Вывод

Единственный способ использовать более новый JAX-RS — это обновить модули JBoss. Если это сломает некоторые другие веб-приложения, вы застряли.

Извлеченные уроки: серверы приложений с множеством готовых, хорошо интегрированных (?) Функций кажутся привлекательными, но когда вы сталкиваетесь с конфликтующими библиотеками и проблемами загрузки классов, их ценность быстро уменьшается. Начиная с чего-то простого, что вы полностью контролируете, такого как Jettty, возможно, в долгосрочной перспективе будет лучшим решением. Кроме того, запуск нескольких веб-приложений на одном сервере, возможно, был разумным в 2000 году, но в настоящее время не стоит усилий. У нас достаточно дискового пространства и памяти, поэтому повторное использование библиотек неважно, и возможность управлять глобальными настройками для всех приложений в одном месте, безусловно, имеет лучшие альтернативы. Микросервисы FTW!