lazha
lazha

Reputation: 78

How to build a SOAP WS with Apache CXF + Spring Boot in Gradle?

The assignment was simple: A SOAP web service implemented with spring boot, JDBC using Gradle.

After some time looking around the discovery was made that "Spring-WS" only works with a contract-first development style.

And we didn't want that, so we dig a little further and found out what we already know, we had to use Apache CXF for a Contract Last development style.

So off we went to search, code and test; but once the data access and facades were done we couldn’t figure out how to wire the Apache CXF WS with the Spring Boot service Façade.

So… how is it done?

Upvotes: 1

Views: 4321

Answers (1)

lazha
lazha

Reputation: 78

This is more of a rhetorical question, because after looking around we could not find an example of Spring Boot & Apache CXF working seamlessly together, so for anyone who may be searching, here is a simple example.

First the dependencies used by the Gradle project

build.gradle file

buildscript {
        ext {
            springBootVersion = '2.0.1.RELEASE'
        }
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        }
    }

    apply plugin: 'java'
    apply plugin: 'eclipse-wtp'
    apply plugin: 'org.springframework.boot'
    apply plugin: 'io.spring.dependency-management'
    apply plugin: 'war'

    group = 'com.telcel'
    version = '0.0.1-RC'
    sourceCompatibility = 1.8

    repositories {
        mavenCentral()
    }

    configurations {
        providedRuntime
    }

    dependencies {
        // Apache CXF
        compile(group: 'org.apache.cxf', name: 'cxf-spring-boot-starter-jaxws', version: '3.1.15') {
            exclude(module: 'spring-boot-starter-tomcat')
        }

        // JDBC support
        compile('org.springframework.boot:spring-boot-starter-jdbc')

        // embedded servlet container
        compile group: 'org.springframework.boot', name: 'spring-boot-starter-undertow', version: '1.5.4.RELEASE'

        runtime group: 'com.ibm.informix', name: 'jdbc', version: '4.10.10.0'

        testCompile('org.springframework.boot:spring-boot-starter-test')
        testRuntime group: 'com.ibm.informix', name: 'jdbc', version: '4.10.10.0'
    }

Then, we need some basic things for the CXF config.

application.properties file:

cxf.path=/service
server.address=0.0.0.0

We needed Spring Boot to create a CXF Endpoint, and we also needed that Endpoint to use our Spring aware Facade... this is where the wiring magic happened.

WebServiceConfig.java

package com.telcel.validaserie;

import com.telcel.validaserie.ui.ValidaSerieEndpoint;
import org.apache.cxf.Bus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.xml.ws.Endpoint;

@Configuration
public class WebServiceConfig {

    @Autowired
    private Bus bus;

    @Autowired
    private ValidaSerieEndpoint validaSerieEndpoint;

    @Bean
    public Endpoint endpoint() {
        EndpointImpl endpoint = new EndpointImpl(bus, validaSerieEndpoint);
        endpoint.publish("/");
        return endpoint;
    }
}

Notice the autowired ValidaSerieEndpoint that goes as a parameter into the EndpointImpl constructor, that's the trick, plain simple.

Finally just a simple web service implementation exposed as a Spring Bean (notice the Spring @Service stereotype)

ValidaSerieEndpoint.class

package com.telcel.validaserie.ui;

import com.telcel.validaserie.servicios.ValidaSeriesFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

@Service
@WebService
public class ValidaSerieEndpoint {

    @Autowired
    private ValidaSeriesFacade validaSeriesFacade;

    @WebMethod
    public String validaTelefonoIccid(@WebParam(name = "iccid") String iccid) {
        return validaSeriesFacade.validaTelefonoIccid(iccid);
    }

    @WebMethod
    public String validaTelefonoImei(@WebParam(name = "imei") String imei) {
        return validaSeriesFacade.validaTelefonoImei(imei);
    }

    @WebMethod
    public int validaFacturaIccid(@WebParam(name = "iccid") String iccid, @WebParam(name = "fuerza-venta") String fuerzaVenta) {
        return validaSeriesFacade.validaFacturaIccid(iccid, fuerzaVenta);
    }

    @WebMethod
    public int validaFacturaImei(@WebParam(name = "imei") String imei, @WebParam(name = "fuerza-venta") String fuerzaVenta) {
        return validaSeriesFacade.validaFacturaImei(imei, fuerzaVenta);
    }

}

And that's it quite simple after you look at it... hope this helps.

Upvotes: 1

Related Questions