Последние несколько дней я работал над переносом приложения с JBoss 4 на Wildfly 8 . В приложении используются разные технологии, но мы сосредоточимся здесь на XML Web Services, JAX-WS . Да, я знаю, что они больше не модные, но они были разработаны давно и должны быть сохранены для проблем совместимости.
В любом случае, путь для миграции этих сервисов был не так прост. Я делюсь некоторыми проблемами и исправлениями с надеждой, что они могут помочь другим разработчикам, столкнувшимся с такими же проблемами.
Пример определения
Вот пример определения Web-сервиса в старой системе, JBoss 4:
1
2
3
4
5
6
|
@javax .jws.WebService(endpointInterface = "some.pack.age.WebService" ) @javax .jws.soap.SOAPBinding(style = SOAPBinding.Style.DOCUMENT) @org .jboss.ws.annotation.EndpointConfig(configName = "Standard WSSecurity Endpoint" ) @javax .jws.HandlerChain(file = "handlers.xml" ) @org .jboss.ws.annotation.SchemaValidation(enabled = true , errorHandler = CustomErrorHandler. class ) public class WebServiceImpl implements WebService { |
К счастью, большая часть определения использует стандартные аннотации Java EE. Только @org.jboss.ws.annotation.EndpointConfig
и @org.jboss.ws.annotation.SchemaValidation
взяты из старых библиотек JBossWS.
Мы можем легко избавиться от @org.jboss.ws.annotation.EndpointConfig
так как он нам не понадобится в новом приложении. Для справки: он используется для установки дополнительных данных конфигурации, которые должны быть предварительно определены с конечной точкой. Проверьте документацию Предопределенные конфигурации клиента и конечной точки .
Мы хотим сохранить @org.jboss.ws.annotation.SchemaValidation
. Для справки, эта аннотация проверяет входящие и исходящие сообщения SOAP по соответствующей схеме в контракте wsdl конечной точки. Поскольку аннотации больше не существует в JBossWS, мы должны использовать Apache CXF , который является базовой реализацией для JAX-WS на Wildfly .
Проблемы
Вот несколько проблем, с которыми я столкнулся:
СхемаВалидация Аннотация
Аннотация @org.jboss.ws.annotation.SchemaValidation
больше не существует. Вы должны использовать аннотацию org.apache.cxf.annotations.SchemaValidation
из Apache CXF .
Добавьте следующую зависимость Maven для использования аннотации Apache CXF :
1
2
3
4
5
6
|
< dependency > < groupId >org.apache.cxf</ groupId > < artifactId >cxf-api</ artifactId > < version >2.7.11</ version > < scope >provided</ scope > </ dependency > |
Также обратите внимание, что в исходной аннотации мы можем определить свойство errorHandler
. Старое приложение использовало пользовательский обработчик ошибок для установки пользовательского сообщения об ошибках проверки схемы. В новой аннотации нет эквивалента, поэтому нам нужно сделать это по-другому. Для воспроизведения старого поведения я использовал Apache CXF Interceptors . Создайте класс-перехватчик и расширьте AbstractPhaseInterceptor
. Вот образец:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
public class SchemaValidationErrorInterceptor extends AbstractPhaseInterceptor<Message> { public SchemaValidationErrorInterceptor() { super (Phase.MARSHAL); } @Override public void handleMessage(Message message) throws Fault { Fault fault = (Fault) message.getContent(Exception. class ); Throwable cause = fault.getCause(); while (cause != null ) { if (cause instanceof SAXParseException) { fault.setMessage( "Invalid XML: " + fault.getLocalizedMessage()); break ; } cause = cause.getCause(); } } } |
И вы можете использовать это так:
1
2
3
|
@org .apache.cxf.interceptor.OutFaultInterceptors( classes = SchemaValidationErrorInterceptor. class ) |
Перехватчики используются как клиентами CXF, так и серверами CXF . Существуют входящие и исходящие цепочки перехватчиков, выполняемые для регулярной обработки, а также при возникновении ошибки. В этом случае мы хотим переопределить сообщение проверки схемы, поэтому нам нужно связать наш перехватчик в цепочке исходящих перехватчиков с ошибкой. Вы можете использовать аннотацию @OutFaultInterceptors
для этого поведения. Каждая цепочка разбита на фазы. Вы определяете этап, на котором вы хотите, чтобы перехватчик запускался, передавая Phase.MARSHAL
в конструктор. Существуют и другие фазы, но поскольку мы хотим изменить сообщение об ошибке, мы делаем это на этапе MARSHAL
.
Разные WSDL
В старых веб-службах файл WSDL создавался автоматически во время развертывания. К сожалению, в некоторых ситуациях WSDL, сгенерированный JBoss 4 и Wildfly 8 , отличается. Это может вызвать проблемы с вашими внешними абонентами. В этом случае основная проблема заключалась в проверке схемы. Запросы, которые были действительны в JBoss 4, больше не действовали, когда выполнялись в Wildfly 8 .
Причина такого поведения была в целевых пространствах имен. Если вы используете аннотации @XmlRootElement
pojos в своих параметрах веб-службы без определения свойства namespace
в аннотации, JBoss 4 WS сгенерировал целевой элемент WSDL с черным пространством имен. Apache CXF будет использовать пространство имен по умолчанию веб-службы для привязки элементов WSDL, если они пустые. Для справки это делается в коде CXF: org.apache.cxf.jaxws.support.JaxWsServiceConfiguration#getParameterName
.
Это можно исправить, изменив код CXF , но мы решили поместить старый сгенерированный файл WSDL в перенесенные источники приложений и включить его в дистрибутив. Это больше не генерируется автоматически, это означает, что нам нужно вручную генерировать WSDL, если мы изменим API. Мы должны быть осторожны, чтобы убедиться, что мы ничего не нарушаем в WSDL. Этот подход казался лучше, чем поддержка собственной версии CXF . Возможно, мы могли бы также исправить это, но мы считаем, что поведение JBoss 4 не было предназначено.
Запустить CXF
Чтобы использовать конкретные API из CXF , недостаточно иметь зависимость проекта от него. Фактически, первые несколько раз, когда я пытался внести изменения, казалось, ничего не связанного с CXF . Это происходит потому, что Wildfly ищет только стандартные аннотации Java EE JAX-WS . Чтобы все поведение CXF работало, мы должны сообщить Wildfly, что наше приложение зависит от CXF , даже если библиотеки уже находятся на сервере. Да, это немного сбивает с толку.
Приложение развернуто в файле EAR. Поэтому вам нужно создать jboss-deployment-structure.xml
и добавить следующее содержимое:
1
2
3
4
5
6
7
8
9
|
< jboss-deployment-structure > < sub-deployment name = "application.war" > < dependencies > < module name = "org.apache.cxf" /> </ dependencies > </ sub-deployment > </ jboss-deployment-structure > |
Использование файла MANIFEST.MF
в файле WAR, очевидно, не работает, если он развернут в файле EAR. Для получения дополнительной информации, пожалуйста, проверьте Class Loading в WildFly .
Если вы хотите использовать другие функции CXF , особенно те, которые связаны с Spring, все может быть немного сложнее. Загляните в этот пост: разные факты о JBoss. Факт 6: JBoss и CXF: матч, заключенный на небесах .
Окончательное определение
Это должно быть нашим окончательным определением для нашего веб-сервиса:
1
2
3
4
5
6
7
8
9
|
@WebService ( wsdlLocation = "WebService.wsdl" , endpointInterface = "some.pack.age.WebService" ) @SOAPBinding (style = SOAPBinding.Style.DOCUMENT) @HandlerChain (file = "/handlers.xml" ) @SchemaValidation (type = SchemaValidation.SchemaValidationType.IN) @OutFaultInterceptors (classes = SchemaValidationErrorInterceptor. class ) public class WebServiceImpl implements BDNSWebService { |
Как видите, необходимые изменения для переноса веб-службы с JBoss 4 на Wildfly — это всего лишь несколько. Тем не менее, есть несколько мелких деталей, которые могут блокировать вас на долгое время, если вы не знаете детали. Может быть, у вас другая настройка и проблемы, с которыми вы сталкиваетесь, другие. Это также может помочь, если вы просто пытаетесь настроить CXF с Wildfly. Надеюсь, этот пост будет вам полезен.
Ссылка: | Wildfly, Apache CXF и @SchemaValidation от нашего партнера по JCG Роберто Кортеса в блоге |