Camel 2.14.0/CXF 3.0.1 Конфигурация Jetty: ошибка несоответствия протокола
У нас есть несколько веб-сервисов (REST+SOAP), работающих в Apache Camel 2.13.0 на основе CXF версии 2.7.10, которые используют SSL и базовую аутентификацию, которые работали довольно хорошо.
Из-за обновления версии Camel до версии 2.14.0, в которой теперь используется CXF 3.0.1, наши службы перестали работать с Protocol mismatch for port x: engine's protocol is http, the url protocol is https
- однако конфигурация не была затронута во время обновления версии.
...
Caused by: java.io.IOException: Protocol mismatch for port 8081: engine's protocol is http, the url protocol is https
at org.apache.cxf.transport.http_jetty.JettyHTTPServerEngineFactory.createJettyHTTPServerEngine(JettyHTTPServerEngineFactory.java:271)
at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.retrieveEngine(JettyHTTPDestination.java:121)
at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.finalizeConfig(JettyHTTPDestination.java:154)
... 48 more
Поэтому я создал новый проект eclipse, который упрощает все до минимума (просто простой сервис SOAP с двумя конечными точками, которые используют либо HTTP, либо HTTPS).
Конфигурацию сервера Jetty можно посмотреть здесь
Фактическая служба настроена как bean-компонент, чтобы впоследствии использовать этот bean-компонент в маршруте Camel:
@Bean(name="endpoint1ServiceSSL")
public CxfSpringEndpoint endpoint1ServiceSSL() throws Exception
{
final CxfSpringEndpoint factoryBean = new CxfSpringEndpoint();
factoryBean.setServiceClass(EnhancedEndpoint1Endpoint.class);
factoryBean.setWsdlURL("classpath:/wsdl/test.wsdl");
factoryBean.setEndpointName(new QName(NAMESPACE, "Endpoint1ServicePort", PREFIX));
factoryBean.setServiceName(new QName(NAMESPACE, "Endpoint1_Service", PREFIX));
factoryBean.setAddress(env.getProperty("services.address.ssl")+"/endpoint1");
factoryBean.setDataFormat(DataFormat.POJO);
final Map<String, Object> properties = new HashMap<>();
properties.put("schema-validation-enabled", "true");
properties.put("allowStreaming", true);
factoryBean.setProperties(properties);
factoryBean.getInInterceptors().add(new LoggingInInterceptor());
factoryBean.getOutInterceptors().add(new LoggingOutInterceptor());
return factoryBean;
}
NAMESPACE
а также PREFIX
только некоторые константы, ничего важного для этого примера. Бин получает определенные значения, такие как базовый адрес сервиса, из файла свойств, который просто содержит такие значения, как:
services.address = http://0.0.0.0:8080/
services.address.ssl = https://0.0.0.0:8081/
и другие вещи, связанные с хранилищем ключей ssl. Обратите внимание, что CXF будет использовать компоненты конфигурации Jetty во время процесса инициализации и, следовательно, создаст защищенное соединение SSL для URL, вызываемых по протоколу HTTPS - по крайней мере, до обновления версии.
Теперь маршрут может получить доступ к сервису по этому очень простому маршруту:
public class Endpoint1Route extends RouteBuilder
{
@Override
public void configure() throws Exception
{
from("cxf:bean:endpoint1Service")
.to("log:endpoint1Service");
from("cxf:bean:endpoint1ServiceSSL")
.to("log:endpoint1ServiceSSL");
}
}
Это хорошо работало с CXF 2.7.10 и Camel 2.13.0 - но, как уже говорилось выше, после обновления по какой-то причине возникает несоответствие протокола (как мы надеемся, это видно из проекта github, который я связал; после клонирования проект, вам нужно выполнить generate-sources и затем запустить ServicesApp
как отдельное приложение Java).
Я также создал новую ветку для обновления версии, чтобы упростить переключение между обеими версиями.
У кого-нибудь есть идеи, почему конфигурация Jetty, которая работала до обновления версии, теперь возвращает эту ошибку несоответствия протокола? Я скучаю по обновленным библиотекам, которые еще не разобрались? Или я настраиваю что-то не так?
@Редактировать:
После дальнейшего тестирования я теперь уверен, что некоторые изменения API внутри CXF привели к проблемам, так как bean-компонент, который настраивает защищенный SSL-сервер Jetty, больше не запускается при запуске, в то время как с версией 2.7.10 bean-компонент выполняется.
Это меняет фактический вопрос на "Как настроить защищенный SSL сервер Jetty в Apache CXF 3.0.1"
@ Ред. № 2:
Мне удалось получить защищенный SSL сервер Jetty, работающий в Camel 2.14.0/CXF 3.0.1, но только через конфигурацию XML. Поскольку мы предпочитаем конфигурацию Java над XML, мы все еще ищем способ настройки Jetty с SSL в CXF 3.0.1 - однако пропуск компонента JettySSLEngineFactory Spring, тем не менее, кажется мне еще одной ошибкой CXF.
Для пояснения, в CXF 2.7.x a сервер Jetty может быть настроен на Java при создании bean-компонента Spring, который возвращает JettyHTTPServerEngineFactory
Например, как показано в master-ветке проекта github, указанного выше. Этот bean-компонент использовался CXF при настройке экземпляра сервера и, следовательно, настройки защищенного SSL-сервера Jetty. Однако в CXF 3.0.1 этот компонент больше не вызывается - только JettyDestinationFactory
который я понятия не имею о том, как настроить защищенный сервер SSL с. Также пример XML, представленный в документации, не дает подсказки о том, как настроить Jetty с SSL с использованием фабрики назначения.
Как engine-factory
внутри примера XML в документах фактически отображается на JettyHTTPServerEngineFactory
и конфигурация Jetty через XML работает нормально, мне кажется, это точно указывает на ошибку внедрения bean-компонента Spring в CXF 3.0.1.
1 ответ
Поскольку ошибка несоответствия протокола была вызвана из-за пропуска CXF инициализации bean-компонента bean-конфигурации конфигурации Jetty. Однако оказалось, что благодаря внутреннему изменению версии Spring в CXF расширение класса конфигурации Spring приводит к определенным проблемам.
На удаление extends SoapSSLConfig
в CxfEndpointConfig
и вводить этот класс конфигурации с помощью @Import(SoapSSLConfig.class)
инициализация bean-компонента и, следовательно, конфигурация сервера Jetty выполняется, как и раньше.
Код раньше был:
@Configuration
@ImportResource({ "classpath:META-INF/cxf/cxf.xml" })
public class CxfEndpointConfig extends SoapSSLConfig
{
...
}
которые приводят к отказам впрыска. Замена вышеприведенного кода на приведенный ниже решила проблему.
@Configuration
@ImportResource({ "classpath:META-INF/cxf/cxf.xml" })
@Import(SoapSSLConfig.class)
public class CxfEndpointConfig
{
...
}