Camel 2.14.0 / CXF 3.0.1 Jetty配置:协议不匹配错误

时间:2014-10-22 13:33:22

标签: java jetty cxf apache-camel

我们在Apache Camel 2.13.0中运行了几个基于CXF 2.7.10版本的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将在其初始化过程中使用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 - 但如上所述,升级后由于某种原因存在协议不匹配(希望可以从github项目中看到我&#39; ve链接;克隆项目后,您需要执行generate-sources,然后启动ServicesApp作为Java独立应用程序。)

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

任何人都知道为什么在版本升级之前工作的Jetty配置现在会返回此协议不匹配错误?我错过了尚未找到的任何更新的库吗?或者我在第一时间配置错误了吗?


@Edit:

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

这会将实际问题更改为&#34;如何在Apache CXF 3.0.1中配置SSL安全Jetty服务器&#34;


@Edit#2:

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

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

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

1 个答案:

答案 0 :(得分:1)

由于协议不匹配错误是由于CXF跳过了jetty配置bean的bean初始化而引起的。但是,事实证明,通过内部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
{
    ...
}