我们在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;
}
NAMESPACE
和PREFIX
只是一些常量,对于这个例子来说并不重要。 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注入错误我
答案 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
{
...
}