No description or website provided.
Java
Permalink
Failed to load latest commit information.
src #6 Added Test for "Endpoint auto initialization is now deactivatable"… Jan 16, 2017
.gitignore
.rultor.yml another try with rultor Apr 29, 2016
.travis.yml Initial commit - moving everything out of the soap-weather-service Apr 6, 2016
README.md #12 Sleuth added to the README Jan 5, 2017
pom.xml Apache CXF 3.1.8 --> 3.1.9 & Jacoco 0.7.xxx --> 0.7.8 Jan 17, 2017
pubring.gpg.asc
secring.gpg.asc Badge and prepare release with rultor Apr 29, 2016
settings.xml.asc settings-xml user-directory fixed for rultor Apr 29, 2016

README.md

Enterprise-ready production-ready SOAP-Webservices powered by Spring Boot & Apache CXF

Build Status Maven Central Dependency Status License

!! This document applies to the next version under development.

    See here for documentation on the latest released version.

Features include:

  • Generating all necessary Java-Classes using JAX-B from your WSDL/XSDs (using the complementing Maven plugin cxf-spring-boot-starter-maven-plugin
  • Booting up Apache CXF within Spring Context with 100% pure Java-Configuration
  • Complete automation of Endpoint initialization - no need to configure Apache CXF Endpoints, that´s all done for you automatically based upon the WSDL and the generated Java-Classes (bringing up a nice Spring Boot 1.4.x Failure Message if you missed something :) )
  • Customize SOAP service URL and the title of the CXF generated Service site
  • Configures CXF to use slf4j and serve Logging-Interceptors, to log only the SOAP-Messages onto console
  • Extract the SoapMessages for processing in ELK-Stack, like docker-elk
  • Tailor your own custom SOAP faults, that comply with the exceptions defined inside your XML schema
  • SOAP Testing-Framework: With XmlUtils to easy your work with JAX-B class handling & a SOAP Raw Client to Test malformed XML against your Endpoints

Documentation

There´s also an blog post describing this project: Spring Boot & Apache CXF – SOAP on steroids fueled by cxf-spring-boot-starter

Initial Setup

  • Create a Spring Boot maven project. Use the spring-boot-starter-parent as a parent and the spring-boot-maven-plugin as a build plugin (you could speed that up, if you use the Spring Initializr).
  • Then append cxf-spring-boot-starter as dependency and the cxf-spring-boot-starter-maven-plugin as build-plugin (see the example cxf-boot-simple):
<dependencies>
    <dependency>
        <groupId>de.codecentric</groupId>
        <artifactId>cxf-spring-boot-starter</artifactId>
        <version>1.0.7.RELEASE</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>de.codecentric</groupId>
            <artifactId>cxf-spring-boot-starter-maven-plugin</artifactId>
            <version>1.0.7.RELEASE</version>
            <executions>
                <execution>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

only temporarily!

 <properties>
    <!-- Overriding SpringBoot 1.3.4ff´s logback 1.1.7, because of http://jira.qos.ch/browse/LOGBACK-1164 which is only fixed in the unreleased 1.1.8  -->
    <logback.version>1.1.6</logback.version>
</properties>
  • place your .wsdl-File (and all the imported XSDs) into a folder somewhere under src/main/resources (see cxf-spring-boot-starter-maven-plugin for details)
  • run mvn generate-sources to generate all necessary Java-Classes from your WSDL/XSD
  • Implement the javax.jws.WebService annotated Interface (your generated Service Endpoint Interface (SEI) ) - it is the starting point for your development and is needed to autoconfigure your Endpoints. See the WeatherServiceEndpoint class inside the cxf-boot-simple project.
  • That´s it

Additional Configuration Options

Customize URL, where your SOAP services are published

  • create a application.properties and set the BaseURL of your Webservices via soap.service.base.url=/yourUrlHere

Customize title of generated CXF-site

  • place a cxf.servicelist.title=Your custom title here in application.properties

SOAP-Message-Logging

Activate SOAP-Message-Logging just via Property soap.messages.logging=true in application.properties (no more configuration on the Endpoint needed)

SOAP-Messages will be logged only and printed onto STOUT/Console for fast analysis in development.

Extract the SoapMessages for processing in ELK-Stack

If you want to use this Logging feature to extract the SoapMessages for processing in ELK-Stack, there are two possible ways: stick to Spring Boot 1.3.3.RELEASE, due to problems in the logstash-logback-encoder, which is itself a bug in logback 1.1.7, which again is delivered with SpringBoot. This is only, till the SpringBoot guys update to logback 1.1.8 - but this is not released yet. Or as an alternative way - and if you want to use newer SpringBoot versions - you have to override the logback-version with a <logback.version>1.1.6</logback.version> in your Maven´s properties-tag.

The cxf-spring-boot-starter brings some nice features, you can use with an ELK-Stack to monitor your SOAP-Service-Calls:

  • Extract SOAP-Service-Method for Loganalysis (based on WSDL 1.1 spec, 1.2 not supported for now - because this is read from the HTTP-Header field SoapAction, which isn´ mandatory in 1.2 any more)
  • Dead simple Calltime-Logging
  • Correlate all Log-Messages (Selfmade + ApacheCXFs SOAP-Messages) within the Scope of one Service-Consumer`s Call in Kibana via logback´s MDC, placed in a Servlet-Filter
HowTo use
  • Activate via Property soap.messages.extract=true in application.properties
  • Add a logback-spring.xml file to src/main/resources (otherwise the feature will not be activated) and configure the logstash-logback-encoder, like:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
    <logger name="org.springframework" level="WARN"/>
    <!-- more logging config here -->


    <!-- Logstash-Configuration -->
    <!-- For details see https://github.com/logstash/logstash-logback-encoder/tree/logstash-logback-encoder-4.5 -->
    <appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <!-- You may want to configure a default instance, this could be done like
        <destination>${LOGANALYSIS_HOST:-192.168.99.100}:5000</destination> as discribed here:
        http://logback.qos.ch/manual/configuration.html#defaultValuesForVariables
        Set the SystemProperty with
        env LOGANALYSIS_HOST={{ loganalysis.host }}
        e.g. in a service.upstart.conf.j2, when using Ansible and deploying to Ubuntu -->
        <destination>192.168.99.100:5000</destination>
        <!-- encoder is required -->
        <encoder class="net.logstash.logback.encoder.LogstashEncoder">
            <includeCallerData>true</includeCallerData>
            <customFields>{"service_name":"WeatherService_1.0"}</customFields>
            <fieldNames>
                <message>log-msg</message>
            </fieldNames>
        </encoder>
        <keepAliveDuration>5 minutes</keepAliveDuration>
    </appender>

    <root level="INFO">
        <appender-ref ref="logstash" />
    </root>
</configuration>
  • Now some fields will become available in your kibana dashboard (in other words in your elasticsearch index), e.g. soap-message-inbound contains the Inbound Message
  • see all of them here ElasticsearchField.java
  • Additionally Spring Cloud Sleuth will provide detailed tracing information of your services. Sleuth will populate the Logback MDC automatically with the tracing information.
  • The default is to use the ELK stack for log analysis. With further configuration you can even extend the tracing infrastructure to use more tailored tracing tools like Zipkin.

Custom SOAP faults for XML Schema Validation Errors

The standard behavior of Apache CXF with XML validation errors (non schema compliant XML or incorrect XML itself) is to return a SOAP fault including the corresponding exception in CXF:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <soap:Fault>
         <faultcode>soap:Server</faultcode>
         <faultstring>wrong number of arguments while invoking public de.codecentric.namespace.weatherservice.general.ForecastRequest de.codecentric.cxf.WeatherServiceEndpoint.getCityForecastByZIP(de.codecentric.namespace.weatherservice.general.ForecastRequest) throws net.bipro.namespace.BiproException with params null.</faultstring>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

Many SOAP based standards demand a custom SOAP-Fault, that should be delivered in case of XML validation errors. To Implement that behavior, you have to:

  • Implement the Interface CustomFaultBuilder as Spring @Component
  • Override Method createCustomFaultMessage(FaultType faultContent) an give back appropriate Messages you want to see in faultstring: soap:FaultYOUR CUSTOM MESSAGE HERE
  • Override Method createCustomFaultDetail(String originalFaultMessage, FaultType faultContent) and return the JAX-B generated Object, that represents your WebService´ Fault-Details (be really careful to take the right one!!, often the term 'Exception' is used twice... - e.g. with the BiPro-Services)
  • Configure your Implementation as @Bean - only then, XML Schema Validation will be activated

Testing SOAP web services

Create a WebService Client
  • If you instantiate a JaxWsProxyFactoryBean, you need to set an Adress containing your configured (or the standard) soap.service.base.url. To get the correct path, just autowire the CxfAutoConfiguration like:
@Autowired
private CxfAutoConfiguration cxfAutoConfiguration;

and obtain the base.url and the serviceUrlEnding (this one is derived from the wsdl:service name attribute of your WSDL) by calling

cxfAutoConfiguration.getBaseAndServiceEndingUrl()
Integrate real XML test files into your Unit-, Integration- or SingleSystemIntegrationTests

As described in this blogpost the best gut feeling one could get while writing SOAP Tests, is the usage of real XML test files. To easily marshall these into your Java classes with JAX-B, this starter brings a utility class de.codecentric.cxf.common.XmlUtils with lots of useful methods like readSoapMessageFromStreamAndUnmarshallBody2Object(java.io.InputStream fileStream, Class jaxbClass). Then you could do things inside your testcases like:

@Value(value="classpath:requests/GetCityForecastByZIPTest.xml")
private org.springframework.core.io.Resource GetCityForecastByZIPTestXml;

@Test
public void getCityForecastByZIP() throws WeatherException, BootStarterCxfException, IOException {
    GetCityForecastByZIP getCityForecastByZIP = XmlUtils.readSoapMessageFromStreamAndUnmarshallBody2Object(GetCityForecastByZIPTestXml.getInputStream(), GetCityForecastByZIP.class);
...
}
SOAP Raw client

Enables automatic testing of malformed XML Requests (e.g. for Testing your Custom SOAP faults) with the de.codecentric.cxf.soaprawclient.SoapRawClient. To use it in your Testcases, initialize the SoapRawClient inside a @Configuration annotated Class like this:

@Bean
public SoapRawClient soapRawClient() throws BootStarterCxfException {
    return new SoapRawClient(buildUrl(), YourServiceInterface.class);
}

public String buildUrl() {
    // return something like http://localhost:8084/soap-api/WeatherSoapService
    return "http://localhost:8084" + cxfAutoConfiguration.getBaseAndServiceEndingUrl();
}

@Autowired
private CxfAutoConfiguration cxfAutoConfiguration;

Concepts

How does Complete automation of Endpoint initialization work?

If you start your Spring Boot application and everything went fine, then you should see some of those log messages inside your console:

[...] INFO 83684 --- [ost-startStop-1] d.c.c.a.WebServiceAutoDetector           : Found WebServiceClient class: 'de.codecentric.namespace.weatherservice.Weather'
[...] INFO 83684 --- [  restartedMain] d.c.c.a.WebServiceAutoDetector           : Found Service Endpoint Interface (SEI): 'de.codecentric.namespace.weatherservice.WeatherService'
[...] INFO 83684 --- [  restartedMain] d.c.c.a.WebServiceAutoDetector           : Found SEI implementing class: 'de.codecentric.soap.endpoint.WeatherServiceEndpoint'

Contribution

If you want to know more or even contribute to this Spring Boot Starter, maybe you need some information like: