java - Camel 2.14.0/CXF 3.0.1 jetty 配置 : Protocol mismatch error

标签 java jetty cxf apache-camel

我们有几个 Web 服务(REST+SOAP)在基于 CXF 2.7.10 版的 Apache Camel 2.13.0 中运行,它们一直使用 SSL 和基本身份验证,运行良好。

由于 Camel 的版本升级到版本 2.14.0,现在内部使用 CXF 3.0.1,我们的服务现在停止工作 端口 x 的协议(protocol)不匹配:引擎的协议(protocol)是 http,url 协议(protocol)是 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 keystore 相关的东西。请注意,CXF 将在其初始化过程中使用 jetty 配置 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 - 但如上所述,升级后由于某种原因存在协议(protocol)不匹配(希望可以从我链接的 github 项目中看出;克隆项目后,您需要执行 generate-sources 然后启动 ServicesApp 作为 Java 独立应用程序)。

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

任何人都知道为什么在版本升级之前有效的 Jetty 配置现在返回此协议(protocol)不匹配错误?我是否遗漏了任何我尚未弄清楚的更新库?还是我一开始就配置错了?


@编辑:

经过进一步测试后,我现在确信 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 中配置 Jetty 服务器以创建返回 JettyHTTPServerEngineFactory 实例的 Spring bean,如上面链接的 github 项目的主分支中所示。 CXF 在配置服务器实例时使用了这个 bean,因此设置了 SSL 安全 Jetty 服务器。但是,在 CXF 3.0.1 中不再调用此 bean - 只有 JettyDestinationFactory 我不知道如何设置 SSL 安全服务器。 XML 示例还预装了 in the docs没有提供有关如何使用目标工厂设置带有 SSL 的 Jetty 的线索。

由于文档中 XML 示例中的 engine-factory 实际上映射到 JettyHTTPServerEngineFactory 并且基于 XML 的 Jetty 配置工作正常,这似乎精确定位了一个 Spring bean给我 CXF 3.0.1 中的注入(inject)错误。

最佳答案

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

CxfEndpointConfig 中删除 extends SoapSSLConfig 并使用 @Import(SoapSSLConfig.class) 注入(inject)此配置类时,bean 初始化,因此 Jetty服务器配置像以前一样执行。

以前的代码是:

@Configuration
@ImportResource({ "classpath:META-INF/cxf/cxf.xml" })
public class CxfEndpointConfig extends SoapSSLConfig
{
    ...
}

导致注入(inject)失败。用下面的代码替换上面的代码解决了这个问题。

@Configuration
@ImportResource({ "classpath:META-INF/cxf/cxf.xml" })
@Import(SoapSSLConfig.class)
public class CxfEndpointConfig
{
    ...
}

关于java - Camel 2.14.0/CXF 3.0.1 jetty 配置 : Protocol mismatch error,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26508701/

相关文章:

java - 如何使用java读取位文件mpeg视频

java - 嵌入式 Jetty 8.x/Spring MVC/WebApplicationInitializer

javascript - 从 angular/javascript 应用程序进行 http2 ajax 调用

java - 如何向 JAX-WS 添加 HTTP 代理?

java - 如何使用 Java 返回部分 JSON 响应?

c# - CXF 与 .Net 不能很好地配合?

java - 如何将 JENA Sparql 查询结果集保存为 JSON?

java - 它不要求输入,直接通过

java - 使用 BufferedInputStream 从服务器读取音频

java - 当使用 Google guice ServletModule 在代码中加载 servlet 时,如何在 Jetty 9.3 中使 _asyncSupported = true