【发布时间】: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;
}
NAMESPACE 和PREFIX 只是一些常量,对于这个例子没有什么重要的。 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