【问题标题】:Camel 2.14.0/CXF 3.0.1 Jetty configuration: Protocol mismatch errorCamel 2.14.0/CXF 3.0.1 Jetty 配置:协议不匹配错误
【发布时间】:2014-12-17 23:26:23
【问题描述】:

我们有几个基于 CXF 版本 2.7.10 在 Apache Camel 2.13.0 中运行的 Web 服务 (REST+SOAP),它们一直使用 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

因此,我创建了一个new eclipse project which simplifies things to its bare minimum(只是一个简单的 SOAP 服务,有两个端点,都使用 HTTP 或 HTTPS)。

Jetty服务器的配置可以看here

实际的服务被配置为 bean 以便稍后在 Camel 的路由中使用这个 bean:

@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;
}

NAMESPACEPREFIX 只是一些常量,对于这个例子没有什么重要的。 bean 从属性文件中获取某些值,例如服务的基地址,该属性文件仅包含以下值:

services.address = http://0.0.0.0:8080/
services.address.ssl = https://0.0.0.0:8081/

和其他 ssl 密钥库相关的东西。请注意,CXF 将在其初始化过程中使用码头配置 bean,因此为 HTTPS 调用的 URL 创建 SSL 安全连接 - 至少在版本升级之前是这样。

该路由现在可以使用这个非常简单的路由访问服务:

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-project 中看出;克隆项目后,您需要执行 generate-sources 然后将ServicesApp作为Java独立应用程序启动。

我还为版本升级创建了一个新分支,以简化两个版本之间的切换。

任何人都知道为什么在版本升级之前工作的 Jetty 的配置现在返回此协议不匹配错误?我是否错过了我还没有弄清楚的任何更新的库?还是我一开始就配置错了?


@编辑:

经过进一步测试,我现在确信 CXF 内部的一些 API 更改导致了问题,因为配置 SSL 安全 Jetty 服务器的 bean 在启动时不再执行,而在 2.7.10 版本中,bean 被执行。

这将实际问题更改为“如何在 Apache CXF 3.0.1 中配置 SSL 安全的 Jetty 服务器”


@编辑#2:

我设法获得了在 Camel 2.14.0/CXF 3.0.1 中运行的 SSL 安全 Jetty 服务器,但只能通过XML configuration。由于我们更喜欢 Java 配置而不是 XML,因此我们仍在寻找一种在 CXF 3.0.1 中使用 SSL 配置 Jetty 的方法 - 不过,跳过 jettySSLEngineFactory Spring bean 对我来说似乎是另一个 CXF 错误。

为了澄清,在 CXF 2.7.x 中,可以在 Java 中配置一个码头服务器,以创建一个返回 JettyHTTPServerEngineFactory 实例的 Spring bean,如上面链接的 github 项目的主分支中所示。 CXF 在配置服务器实例时使用了这个 bean,因此设置了 SSL 安全的 Jetty 服务器。但是,在 CXF 3.0.1 中不再调用此 bean - 只有 JettyDestinationFactory 我不知道如何设置 SSL 安全服务器。此外,in the docs 的 XML 示例也没有提供有关如何使用目标工厂使用 SSL 设置 Jetty 的任何线索。

由于文档中 XML 示例中的 engine-factory 实际上映射到 JettyHTTPServerEngineFactory 并且基于 XML 的 Jetty 配置工作正常,这似乎向我指出了 CXF 3.0.1 中的 Spring bean 注入错误。

【问题讨论】:

    标签: java jetty cxf apache-camel


    【解决方案1】:

    由于CXF跳过jetty配置bean的bean初始化导致协议不匹配错误。然而,事实证明,通过 CXF 中的内部 Spring 版本更改扩展 Spring 配置类会导致某些问题。

    在删除CxfEndpointConfig 中的extends SoapSSLConfig 并使用@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
    {
        ...
    }
    

    【讨论】:

      猜你喜欢
      • 2021-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-09
      相关资源
      最近更新 更多