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

Java Camel 2.14.0/CXF 3.0.1 Jetty配置:协议不匹配错误,java,jetty,cxf,apache-camel,Java,Jetty,Cxf,Apache Camel,我们有两个web服务(REST+SOAP)在ApacheCamel 2.13.0中运行,它基于CXF版本2.7.10,一直使用SSL和基本身份验证,运行得非常好 由于Camel的版本升级到2.14.0版,该版本内部使用现在的CXF 3.0.1,我们的服务现在停止工作,因为端口x的协议不匹配:引擎的协议是http,url协议是https-但是在版本更新期间,配置未被更改 ... Caused by: java.io.IOException: Protocol mismatch for port 8

我们有两个web服务(REST+SOAP)在ApacheCamel 2.13.0中运行,它基于CXF版本2.7.10,一直使用SSL和基本身份验证,运行得非常好

由于Camel的版本升级到2.14.0版,该版本内部使用现在的CXF 3.0.1,我们的服务现在停止工作,因为端口x的
协议不匹配:引擎的协议是http,url协议是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
因此,我创建了一个(只是一个简单的SOAP服务,有两个端点,都使用HTTP或HTTPS)

可以看到Jetty服务器的配置

实际服务被配置为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;
}
以及其他与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项目中可以看出;克隆项目后,需要执行generate sources,然后作为Java独立应用程序启动
ServicesApp

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

有人知道为什么在版本升级之前工作的Jetty配置现在返回这个协议不匹配错误吗?我是否错过了任何我还没有弄清楚的更新库?还是我首先配置了一些错误的东西


@编辑:

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

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


@编辑#2:

我设法让一个SSL安全的Jetty服务器在Camel 2.14.0/CXF 3.0.1中运行,但仅通过。由于我们更喜欢Java配置而不是XML,因此我们仍在寻找一种在CXF 3.0.1中使用SSL配置Jetty的方法——不过,跳过JettyssEngineeFactory Springbean对我来说似乎是另一个CXF错误

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


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

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

在删除
CxfEndpointConfig
中的
扩展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
{
    ...
}
@Configuration
@ImportResource({ "classpath:META-INF/cxf/cxf.xml" })
@Import(SoapSSLConfig.class)
public class CxfEndpointConfig
{
    ...
}