How to properly integrate a CXF client into Spring Boot

Viewed 13067

I was looking at various ways how to build a SOAP client with CXF into a Spring Boot application. In particular I'm interested in configuring request/response logging.

Precondition: the CXF Maven plugin is used to generate Java stubs from the WSDL files.

I studied a number of tutorials [1][2][3] and they all do that slightly differently. The question is whether there's an "officially endorsed" way of integrating a CXF client with Spring Boot. The CXF documentation doesn't seem to say.

Option 1: BindingProvider

The existing code I'm working with (not mine) does it like that:

@Bean
public PartnerServicePortType partnerServicePortType() {
  PartnerServicePortType partnerServicePortType = new PartnerServiceV0().getPartnerService();
  configureService((BindingProvider) partnerServicePortType, Services.PARTNER_SERVICE.serviceName());
  return partnerServicePortType;
}

private void configureService(BindingProvider bindingProvider, String path) {
  bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, baseUrl + path);
  if (!StringUtils.isEmpty(username)) {
    bindingProvider.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, username);
    bindingProvider.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);
  }

  /* add logging interceptors
  Client client = ClientProxy.getClient(bindingProvider);
  Endpoint cxfEndpoint = client.getEndpoint();

  cxfEndpoint.getInInterceptors().add(new PayloadExtractingLoggingInInterceptor());
  cxfEndpoint.getInFaultInterceptors().add(new PayloadExtractingLoggingInInterceptor());
  cxfEndpoint.getOutInterceptors().add(new PayloadExtractingLoggingOutInterceptor());
  cxfEndpoint.getOutFaultInterceptors().add(new PayloadExtractingLoggingOutInterceptor());
  */
}

PartnerServiceV0 is generated class that extends javax.xml.ws.Service and looks like this:

@WebServiceClient(name = "PartnerService_v0", 
                  wsdlLocation = "classpath:some.wsdl",
                  targetNamespace = "urn:some-namespace") 
public class PartnerServiceV0 extends Service {

As you can see I added the code to enable request/response logging to the configureServcie method. While this does work it feels somewhat odd that we'd have to go through all of that for every service.

Option 2: JaxWsProxyFactoryBean

For verification purposes I ported the above code to using JaxWsProxyFactoryBeans:

@Bean(name = "partnerService")
public PartnerServicePortType generateProxy() {

  JaxWsProxyFactoryBean proxyFactory = new JaxWsProxyFactoryBean();
  proxyFactory.setServiceClass(PartnerServicePortType.class);
  proxyFactory.setAddress(baseUrl + Services.PARTNER_SERVICE.serviceName());
  if (!StringUtils.isEmpty(username)) {
    proxyFactory.setUsername(username);
    proxyFactory.setPassword(password);
  }
  return (PartnerServicePortType) proxyFactory.create();
}

Adding logging config is something I'd still have to figure out with this strategy.

Tutorials I checked

  1. https://blog.codecentric.de/2016/07/spring-boot-apache-cxf-logging-monitoring-logback-elasticsearch-logstash-kibana/
  2. http://www.baeldung.com/apache-cxf-with-spring
  3. http://www.littlebigextra.com/consume-secure-soap-web-service-spring-boot-application/
2 Answers
Related