We have a couple of web services (REST+SOAP) running in Apache Camel 2.13.0 based on CXF version 2.7.10 which use SSL and basic authentication all the way, which worked pretty fine.
Due to a version upgrade of Camel to version 2.14.0, which internally uses now CXF 3.0.1, our services now stoped working as of a Protocol mismatch for port x: engine's protocol is http, the url protocol is https - the configuration however was untouched during the version-update.
...
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
I therefore created a new eclipse project which simplifies things to its bare minimum (just a simple SOAP service with two endpoints which both use either HTTP or HTTPS).
The configuration of the Jetty server can be seen here
The actual service is configured as bean to later on use this bean within Camel's route:
@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 and PREFIX are just some constants, nothing important for this example. The bean gets certain values like the service's base address from a property file which just contains values like:
services.address = http://0.0.0.0:8080/
services.address.ssl = https://0.0.0.0:8081/
and other ssl keystore related stuff. Note that CXF will use the jetty configuration beans during its initialization process and therefore create a SSL secured connection for HTTPS invoked URLs - at least it did before the version-upgrade.
The route now can access the service using this very simple route:
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");
}
}
This worked well with CXF 2.7.10 and Camel 2.13.0 - but as already stated above, after the upgrade there is a protocol mismatch for some reason (as hopefully can be seen from the github-project I've linked; after cloning the project, you need to execute generate-sources and then start ServicesApp as Java standalone application).
I've also created a new branch for the version-upgrade to simplify the switch between both versions.
Anyone has any idea why the configuration of Jetty, which worked before the version upgrade, now returns this protocol mismatch error? Am I missing any updated libraries I haven't figured out yet? Or am I configuring something wrong in first place?
@Edit:
After further testing I am now sure that some API changes inside CXF led to the problems as the bean which configures the SSL secured Jetty server is no longer executed on startup, while with version 2.7.10 the bean gets executed.
This changes the actual question to "How to configure a SSL secured Jetty Server in Apache CXF 3.0.1"
@Edit #2:
I managed to get a SSL secured Jetty server running in Camel 2.14.0/CXF 3.0.1 but only via XML configuration. As we prefer Java config over XML, we are still looking for a method to configure Jetty with SSL in CXF 3.0.1 - The skip of the jettySSLEngineFactory Spring bean, though, seems like a further CXF bug to me.
To clarify, in CXF 2.7.x a jetty server could get configured in Java on creating a Spring bean which returns a JettyHTTPServerEngineFactory instance, as showcased in the master-branch of the github project linked above. This bean was used by CXF while configuring the server instance and therefore set up the SSL secured Jetty server. However, in CXF 3.0.1 this bean no longer is invoked - only JettyDestinationFactory which I have no clue on how to set up a SSL secured server with. Also the XML example prestended in the docs gives no clue on how to set up Jetty with SSL using a destination factory.
As the engine-factory inside the XML example in the docs actually maps to a JettyHTTPServerEngineFactory and Jetty configuration over XML is working fine, this seems to pinpoint a Spring bean injection bug inside CXF 3.0.1 to me.
As the protocol mismatch error was caused due to CXF skipping the bean initialization of the jetty configuration bean. However, it turned out that through the internal Spring version change in CXF extending a Spring configuration class leads to certain issues.
On removing extends SoapSSLConfig in CxfEndpointConfig and injecting this configuration class using @Import(SoapSSLConfig.class) the bean initialization and therefore the Jetty server configuration is executed as before.
The code used to be:
@Configuration
@ImportResource({ "classpath:META-INF/cxf/cxf.xml" })
public class CxfEndpointConfig extends SoapSSLConfig
{
...
}
which lead to injection failures. Replacing the above code with the below solved the problem.
@Configuration
@ImportResource({ "classpath:META-INF/cxf/cxf.xml" })
@Import(SoapSSLConfig.class)
public class CxfEndpointConfig
{
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With