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
{
    ...
}
Другие вопросы по тегам