Giter Club home page Giter Club logo

cxf-spring-boot-starter's Introduction

Enterprise & production ready SOAP webservices powered by Spring Boot & Apache CXF

Build Status Maven Central License renovateenabled codecov versionspringboot versionjava versionapachecxf versionspringcloudsleuth versionlogstashlogbackencoder Deployed on Heroku

spring-boot-starter-cxf-logo

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 Elastic-Stack (ELK), 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
  • Works with JDK 8, 9 & 11ff

Documentation

This starter is part of the Community Contributions list of the official Spring Boot Starters: https://github.com/spring-projects/spring-boot/tree/master/spring-boot-project/spring-boot-starters (see SOAP Web Services support with Apache CXF)

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

The following documentation tries to get you started fast. There are also sample projects, if you'd like to see some code instead:

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>2.4.1</version>
	</dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>de.codecentric</groupId>
            <artifactId>cxf-spring-boot-starter-maven-plugin</artifactId>
            <version>2.3.0.RELEASE</version>
            <executions>
                <execution>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
  • 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 STDOUT/Console for fast analysis in development.

Extract the SoapMessages for processing in ELK-Stack

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 (which is delivered with this spring-boot-starter), 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. You can for example retrieve the Trace-Id of the current call via MDC.get("X-B3-TraceId").
  • 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

Apache CXF & JAX-WS with JDK11+ together with the JavaEE/JakartaEE chaos

Since JDK8 isn't the way to go anymore, the underlying cxf-spring-boot-starter-maven-plugin had to be rebuild to support JDK11+ (but also 8, 9, 10, ...) - have a look at JDK 11 support in the docs there.

Also the JavaEE libraries were mostly deprecated in the JDK - and also moved from Oracle to JakartaEE projects on GitHub/MavenCentral. This has also already been adressed in Moved from "OLD" jaxb to "NEW" jaxb.

But there's a third point so far: Apache CXF isn't going to work fully without another dependency. I stumbled upon it, while completing the cxf-boot-simple - a sample project, which should show the usage of this cxf-spring-boot-starter in client-only mode much much better than before (see #8).

The problem is, ApacheCXF uses classes from com.sun.activation package (see new Jakarta sources on GitHub here or on Maven Central), which lead to errors when the dependecy isn't provided (see stackoverflow):

Caused by: java.lang.NoClassDefFoundError: com/sun/activation/registries/LogSupport
	at javax.activation.MailcapCommandMap.<init>(MailcapCommandMap.java:179) ~[javax.activation-api-1.2.0.jar:1.2.0]
	at javax.activation.CommandMap.getDefaultCommandMap(CommandMap.java:85) ~[javax.activation-api-1.2.0.jar:1.2.0]
	at org.apache.cxf.attachment.AttachmentUtil.<clinit>(AttachmentUtil.java:70) ~[cxf-core-3.3.2.jar:3.3.2]
	at org.apache.cxf.interceptor.AttachmentOutInterceptor.handleMessage(AttachmentOutInterceptor.java:53) ~[cxf-core-3.3.2.jar:3.3.2]
	at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) ~[cxf-core-3.3.2.jar:3.3.2]
	at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:531) ~[cxf-core-3.3.2.jar:3.3.2]
	at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:440) ~[cxf-core-3.3.2.jar:3.3.2]
	at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:355) ~[cxf-core-3.3.2.jar:3.3.2]
	at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:313) ~[cxf-core-3.3.2.jar:3.3.2]
	at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96) ~[cxf-rt-frontend-simple-3.3.2.jar:3.3.2]
	at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:140) ~[cxf-rt-frontend-jaxws-3.3.2.jar:3.3.2]
	at com.sun.proxy.$Proxy155.getCityForecastByZIP(Unknown Source) ~[na:na]
	at de.codecentric.soap.endpoint.WeatherServiceSoapClient.getCityForecastByZIP(WeatherServiceSoapClient.java:36) ~[classes/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:567) ~[na:na]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	... 58 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.sun.activation.registries.LogSupport
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583) ~[na:na]
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) ~[na:na]
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
	... 82 common frames omitted

As we provide the correct dependency with this starter here, you don't need to bother about that:

    <dependency>
        <groupId>com.sun.activation</groupId>
        <artifactId>jakarta.activation</artifactId>
        <version>${jakarta.activation.version}</version>
    </dependency>

Testing SOAP web services

Create a WebService Client
  • If you instantiate a JaxWsProxyFactoryBean, you need to set an Address 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;

Running Client-only mode

If you´d like to run Apache CXF only to call other SOAP web services but don´t want to provide one for yourself, than booting up a complete server is a bit to much for you. Therefore you´re also able to deactivate the Complete automation of Endpoint initialization feature, which only makes sense if you have an Endpoint to fire up. You can deactivate it with the following propery in your application.propteries:

endpoint.autoinit=false

Concepts

Complete automation of Endpoint initialization

100% contract first approach

Taking into account a 100% contract first development approach there shouldn´t be a single reason, why one has to manually configure Endpoints in Apache CXF - because pretty much every piece of information that is necessary to configure them should be available through the WSDL. Since the start of this spring-boot-starter project, this was a thought that didn´t let me go.

To understand, how the complete automation of Endpoint initialization is implemented in the cxf-spring-boot-starter, let´s first have a look on how the initialization works without the help of the starter. To instantiate & publish a org.apache.cxf.jaxws.EndpointImpl, we need the SEI implementing class and the generated WebServiceClient annotated class. In a non-automated way to use Apache CXF to fire up JAX-WS endpoints, this is done with code like this:

	@Bean
	public WeatherService weatherService() {
	    return new WeatherServiceEndpoint();
	}

    @Bean
    public Endpoint endpoint() {
        EndpointImpl endpoint = new EndpointImpl(springBus(), weatherService());
        endpoint.setServiceName(weather().getServiceName());
        endpoint.setWsdlLocation(weather().getWSDLDocumentLocation().toString());
        endpoint.publish(serviceUrlEnding());
        return endpoint;
    }

	@Bean
	public Weather weather() {
	    // Needed for correct ServiceName & WSDLLocation to publish contract first incl. original WSDL
	    return new Weather();
	}

The easier parts are the SpringBus, which we already have instantiated in our CxfAutoConfiguration, and the serviceUrlEnding, which is constructed from the configurable base url and the WSDL tag´s service name content. To instantiate the EndpointImpl, set the service name and the WSDL location correctly, we need the SEI implementing class (which you have to write yourself, because it´s the starting point for your implementation) and the generated WebServiceClient annotated class.

Scanning...

Because a spring-boot-starter is a generic thing everybody can use just via including it in the pom, these two classes are not fixed - they are always generated or derived from generated classes. Therefore we have to search for them - according to some things we know. The search is done with the help of Spring´s ClassPathScanningCandidateComponentProvider (instead of using the really nice fast-classpath-scanner, which didn´t work well in this use case).

Either scanning framework you use, self written or library - any of them will be much faster, if you have the package names of the searched classes. In some scenarios -escpecially with the ClassPathScanningCandidateComponentProvider used here - you have to know the packages, otherwise scanning will fail (because it tries to double-scan the package org.springframework itself). So to search for the WebServiceClient annotated class and the SEI itself (which we need to scan for the SEI implementation, which is only characterized due to the fact of implementing the SEI), we need to somehow know their package beforehand.

Here cxf-spring-boot-starter-maven-plugin comes to our rescue. With the new 1.0.8´s feature Extract the targetNamespace from the WSDL, generate the SEI and WebServiceClient annotated classes´ package names from it & write it together with the project´s package name into a cxf-spring-boot-maven.properties the package names are extracted into a cxf-spring-boot-maven.properties file inside your project.buildpath while a mvn generate-sources` is ran. The package name of the WebServiceClient annotated class and the SEI are derived from the WSDL:

To get this 100% right, we need to use the same mechanism as the jaxws-maven-plugin, which itself uses WSimportTool of the JAXWS-RI implementation, to obtain the package-Name from the WSDL file, where the classes are generated to. The WSDL´s targetNamespace is used to generate the package name. If you have targetNamespace="http://www.codecentric.de/namespace/weatherservice/" for example, your package will be de.codecentric.namespace.weatherservice. One can find the code used to generate the package name in the WSDLModeler at line 2312 (This algorithm is specified in the JAXB spec. So we rely onto it):

    String wsdlUri = document.getDefinitions().getTargetNamespaceURI();
    return XJC.getDefaultPackageName(wsdlUri);

The package name of the SEI implementing class is a bit more of a guesswork, because this class could literally reside everywhere. BUT: If you start a project to use a spring-boot-starter, the 99,9% case will be to start with a Maven pom - and even faster through the usage of the Spring initializr. It should be safe to rely on that and just guess the package name from your project´s pom. This will in 99,9% of all cases contain your SEI implementing class, which is you´re entry point to develop a SOAP web service with this starter and CXF.

Auto initialize the Endpoint!

Complete automation of endpoint initialization

Now having the package names of every needed class residing in the cxf-spring-boot-maven.properties file after a run of mvn generate-sources, using Spring´s ClassPathScanningCandidateComponentProvider to scan for the WebServiceClient annotated class is easy - just adding a new AnnotationTypeFilter and voila we´ve got the class. Obtaining the class of an interface which has some annotation isn´t possible with the Spring scanner at first sight (and therefore we had a long experimenting phase with the fast-classpath-scanner). But looking a bit deeper, this is also possible - just via a really small hack :) , which only means to override the ClassPathScanningCandidateComponentProvider:

ClassPathScanningCandidateComponentProvider scanningProvider = new ClassPathScanningCandidateComponentProvider(false) {
    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return true;
    }
};  

Now we´re able to scan for the SEI. And with that and adding the AssignableTypeFilter we also get the needed SEI implementing class.

Having all the three necessary classes at hand, we can easiely and automatically fire up a org.apache.cxf.jaxws.EndpointImpl!

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: 'WeatherServiceEndpoint'
Deactivate autoinitialization

Although it should be a great feature to be able to work 100% contract first, there might be situations, where one wants to deactivate it. E.g. while running in client-only mode.

Because there is (& sadly will be) no @ConditionalOnMissingProperty in Spring Boot, we need to use a workaround:

     @Bean
     @ConditionalOnProperty(name = "endpoint.autoinit", matchIfMissing = true)
     public Endpoint endpoint() throws BootStarterCxfException ...

To get the desired deactivation flag nevertheless, we need to use the @ConditionalOnProperty in an interesting way :) With the usage of matchIfMissing = true and name = "endpoint.autoinit" the autoinitialization feature is activated in situations, where the property is missing or is set to true. Only, if endpoint.autoinit=false the feature is disabled (which is quite ok in our use-case).

Setting the URL of the endpoint

You can manually specify the url of the Service Endpoint using the spring property: soap.service.publishedEndpointUrl. This can be handy if your application is behind a reverse proxy and the resulting WSDLs don't reflect that.

Known limitations

Using devtools with mvn spring-boot:run

If you want to use the well known Spring Boot Developer Tools (devtools) - no problem. As long as you don´t want to use mvn spring-boot:run. Because of the devtools make usage of the 2 separate classloaders the scanned, found and instantiated classes aren´t valid inside the other classloader and you could get into trouble. This is only in combination with the Complete automation of Endpoint initialization feature and the starting method mvn spring-boot:run. All the other starting mechanisms of Spring Boot will work as expected (java -jar service.jar, Starting inside the IDE via Run as... or in mvn test).

Sample projects

For better documentation and usability overview of the cxf-spring-boot-starter, this project now also provides sample projects.

  • cxf-boot-simple: Full example incl. Endpoint implementation, Tests, WSDL files with XSD includes, Custom Faults etc.
  • cxf-boot-simple-client: Client example, using the cxf-spring-boot-starter in Client only mode

That we are able to test the second project in client-only mode, we should somehow run the first sample project on a Cloud provider like Heroku.

Deploying cxf-boot-simple on Heroku

On Heroku the current Java environment supports JDKs newer than JDK8, which is needed to successfully build our cxf-spring-boot-starter (which now has build in JDK8, 9, 11 & 12 support).

The default JDK in Heroku is currently version 8, according to the docs we have to create a system.properties file inside the root of our application to configure this:

# Heroku configuration file
# by default, Heroku uses JDK8, which isn't able to build our cxf-spring-boot-starter (although it can be used with JDK8)
# see https://devcenter.heroku.com/articles/java-support#specifying-a-java-version
java.runtime.version=12
# we also need to specify the Maven version (see https://github.com/codecentric/cxf-spring-boot-starter/issues/48)
# maven.version=3.6.0
# but as there is no support for Maven >3.3.9 on Heroku, we need to switch to https://github.com/takari/maven-wrapper
# which is also the recommended way to use Maven on Heroku https://devcenter.heroku.com/articles/java-support#specifying-a-maven-version

But then we'll soon find ourselfs in the hell of an old Maven version! Currently Heroku only supports Maven <=3.3.9, which leads to the following build exception on Heroku (see #48 also):

Error injecting: org.jvnet.jax_ws_commons.jaxws.MainWsImportMojocom.google.inject.ProvisionException: Unable to provision

Changing the Maven version inside the system.properties file doesn't help much, since Heroku doesn't support newer versions. Also a provided mvnw maven-wrapper configuration isn't picked up successfully (which should have helped us get out of this help):

-----> Java app detected

-----> Installing JDK 12... done

-----> Installing Maven 3.3.9... done

-----> Executing: mvn -DskipTests clean dependency:list install

       [INFO] Scanning for projects...

Deploying cxf-boot-simple on Heroku with Docker

Now that we don't have a current Maven version, we need to have a look for alternatives. But hey, there's also this alternative way of deploying to Heroku: Docker!

According to the docs, we only need a Dockerfile inside our sample project:

# Docker multi-stage build

# 1. Building the App with Maven
FROM maven:3-jdk-11

ADD . /cxfbootsimple
WORKDIR /cxfbootsimple

# Just echo so we can see, if everything is there :)
RUN ls -l

# Run Maven build
RUN mvn clean install


# Just using the build artifact and then removing the build-container
FROM openjdk:11-jdk

MAINTAINER Jonas Hecht

VOLUME /tmp

# Add Spring Boot app.jar to Container
COPY --from=0 "/cxfbootsimple/target/cxf-boot-simple-*-SNAPSHOT.jar" app.jar

# Fire up our Spring Boot app by default
CMD [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]

And we need a heroku.yml inside the root of our project:

build:
  docker:
    web: /cxf-spring-boot-starter-samples/cxf-boot-simple/Dockerfile

Now we need to set the Heroku stack to container (we should do that maybe better inside a app.yml?!):

heroku stack:set container

The next push should start our sample app inside a Docker container running on Heroku :)

Error R14 (Memory quota exceeded)

To prevent a Memory quota exceeded error:

2019-07-24T02:58:48.253177+00:00 heroku[web.1]: Process running mem=836M(163.4%)
2019-07-24T02:58:48.253243+00:00 heroku[web.1]: Error R14 (Memory quota exceeded)
2019-07-24T02:58:55.236933+00:00 heroku[web.1]: State changed from starting to crashed
2019-07-24T02:58:55.111947+00:00 heroku[web.1]: Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
2019-07-24T02:58:55.111947+00:00 heroku[web.1]: Stopping process with SIGKILL
2019-07-24T02:58:55.217642+00:00 heroku[web.1]: Process exited with status 137

we should configure our JVM running inside the Docker container to not base it's memory allocation on the OS reports, since we do run inside a container now! See https://devcenter.heroku.com/articles/java-memory-issues#configuring-java-to-run-in-a-container

But as https://aboullaite.me/docker-java-10/ points out, the Java 9 configuration with -XX:+UseContainerSupport is now defaulting to true.

If we would run on Java 9 on, we would have to tweak our java -jar command:

# Fire up our Spring Boot app by default
CMD [ "sh", "-c", "java $JAVA_OPTS -XX:+UseContainerSupport -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]

As I like explicitely setting things we rely on, let's also leave this option set for JDK 10+.

But hey, we switched our Heroku environment from web! The web stack type automatically detects Java apps - and provides the correct Xms JAVA_OPTS configuration - see https://devcenter.heroku.com/articles/java-memory-issues#heroku-memory-limits:

The default support for most JVM-based languages sets -Xss512k and sets Xmx dynamically based on dyno type. These defaults enable most applications to avoid R14 errors.

But as we are using Heroku stack type container now, these options might not be provided anymore?!

Let's double check the configuration of our Heroku container dyno! Execute heroku run printenv to see all environment variables inside:

$ heroku run printenv
Running printenv on ⬢ cxf-boot-simple... up, run.7988 (Free)
JAVA_URL_VERSION=11.0.4_11
HEROKU_EXEC_URL=https://exec-manager.heroku.com/a3ea58e6-d7b3-4fa8-8148-5567be41e46f
PORT=13303
JAVA_BASE_URL=https://github.com/AdoptOpenJDK/openjdk11-upstream-binaries/releases/download/jdk-11.0.4%2B11/OpenJDK11U-jdk_
HOME=/
PS1=\[\033[01;34m\]\w\[\033[00m\] \[\033[01;32m\]$ \[\033[00m\]
JAVA_VERSION=11.0.4
TERM=xterm-256color
COLUMNS=160
PATH=/usr/local/openjdk-11/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
JAVA_OPTS=
LANG=C.UTF-8
JAVA_HOME=/usr/local/openjdk-11
PWD=/
LINES=32
DYNO=run.7988

And THERE WE ARE: JAVA_OPTS is empty!

If you have a look at the default web stack configuration on Heroku, this variable should have the following configuration:

JAVA_OPTS=-Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8

So let's tweak our cxf-boot-simple Dockerfile:

# Fire up our Spring Boot app by default
CMD [ "sh", "-c", "java -Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8 -XX:+UseContainerSupport -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]

Now we should have configured our Java app running inside Docker according to the standard web Heroku stack (see https://devcenter.heroku.com/articles/java-memory-issues#heroku-memory-limits).

Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch

Our original Heroku Procfile did contain the setting of the $PORT variable so that Spring Boot is able to launch it's internal Tomcat accordingly:

web: java -Dserver.port=$PORT -jar cxf-spring-boot-starter-samples/cxf-boot-simple/target/cxf-boot-simple-*-SNAPSHOT.jar

And this configuration is also needed inside our Dockerfile! Because https://devcenter.heroku.com/articles/container-registry-and-runtime#dockerfile-commands-and-runtime states:

The web process must listen for HTTP traffic on $PORT, which is set by Heroku. EXPOSE in Dockerfile is not respected, but can be used for local testing. Only HTTP requests are supported.

So let's tweak our cxf-boot-simple Dockerfile again:

# Fire up our Spring Boot app by default
CMD [ "sh", "-c", "java -Dserver.port=$PORT -Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8 -XX:+UseContainerSupport -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]

Now the $PORT environment variable should be used to fire up our Spring Boot app. To verify this, execute the Docker container locally:

docker build . --tag cxfbootsimple
docker run -e "PORT=8095" cxfbootsimple
# look for container id
docker ps 
docker exec -it containerId bash
curl localhost:8095/my-foo-api -v

Finally our cxf-boot-simple app is accessible at https://cxf-boot-simple.herokuapp.com/my-foo-api

Contribution

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

cxf-spring-boot-starter's People

Contributors

bjansen avatar erikpetzold avatar jonashackt avatar marcopaga avatar pascalschumacher avatar renovate-bot avatar renovate[bot] avatar todvora avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cxf-spring-boot-starter's Issues

REST-Healthstatus-Endpoints, that check whether the soap-Services (dynamic?!) are available (e.g. something like Swagger/Springfox)

The great (http://springfox.github.io/springfox/) for automatic documentation of REST-APIs should be used to either have an Healthstatus-REST-Endpoint (which calls the SOAP service itself and check´s, if it´s working) or (harder, but cooler) supports a springfox like web UI, that shows all SOAP web service methods including the possibility to try them inside the browser.

java.lang.NoClassDefFoundError: com/sun/activation/registries/LogSupport JDK11 Apache CXF in client-only mode

With JDK11 and Apache CXF in client-only mode, I get the following ClassNotFound exceptions:

Caused by: java.lang.NoClassDefFoundError: com/sun/activation/registries/LogSupport
	at javax.activation.MailcapCommandMap.<init>(MailcapCommandMap.java:179) ~[javax.activation-api-1.2.0.jar:1.2.0]
	at javax.activation.CommandMap.getDefaultCommandMap(CommandMap.java:85) ~[javax.activation-api-1.2.0.jar:1.2.0]
	at org.apache.cxf.attachment.AttachmentUtil.<clinit>(AttachmentUtil.java:70) ~[cxf-core-3.3.2.jar:3.3.2]
	at org.apache.cxf.interceptor.AttachmentOutInterceptor.handleMessage(AttachmentOutInterceptor.java:53) ~[cxf-core-3.3.2.jar:3.3.2]
	at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) ~[cxf-core-3.3.2.jar:3.3.2]
	at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:531) ~[cxf-core-3.3.2.jar:3.3.2]
	at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:440) ~[cxf-core-3.3.2.jar:3.3.2]
	at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:355) ~[cxf-core-3.3.2.jar:3.3.2]
	at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:313) ~[cxf-core-3.3.2.jar:3.3.2]
	at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96) ~[cxf-rt-frontend-simple-3.3.2.jar:3.3.2]
	at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:140) ~[cxf-rt-frontend-jaxws-3.3.2.jar:3.3.2]
	at com.sun.proxy.$Proxy155.getCityForecastByZIP(Unknown Source) ~[na:na]
	at de.codecentric.soap.endpoint.WeatherServiceSoapClient.getCityForecastByZIP(WeatherServiceSoapClient.java:36) ~[classes/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:567) ~[na:na]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	... 58 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.sun.activation.registries.LogSupport
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583) ~[na:na]
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) ~[na:na]
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
	... 82 common frames omitted

Running cxf-boot-simple on Heroku (using Docker)

See https://dashboard.heroku.com/apps/cxf-boot-simple/activity/builds/6c9fd9e9-d27f-459a-b43a-7a77baf71338

       [INFO] Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/resolver/maven-resolver-util/1.1.1/maven-resolver-util-1.1.1.jar (156 KB at 471.7 KB/sec)

       [INFO] Downloaded: https://repo.maven.apache.org/maven2/org/apache/commons/commons-lang3/3.5/commons-lang3-3.5.jar (469 KB at 1291.0 KB/sec)

       [INFO] Downloaded: https://repo.maven.apache.org/maven2/com/google/guava/guava/20.0/guava-20.0.jar (2386 KB at 6008.5 KB/sec)

       [WARNING] Error injecting: org.jvnet.jax_ws_commons.jaxws.MainWsImportMojo

       com.google.inject.ProvisionException: Unable to provision, see the following errors:

       

       1) Error injecting: private org.eclipse.aether.spi.log.Logger org.apache.maven.repository.internal.DefaultVersionRangeResolver.logger

         while locating org.apache.maven.repository.internal.DefaultVersionRangeResolver

         while locating java.lang.Object annotated with *

         at org.eclipse.sisu.wire.LocatorWiring

         while locating org.eclipse.aether.impl.VersionRangeResolver

           for parameter 1 at org.eclipse.aether.internal.impl.DefaultRepositorySystem.<init>(Unknown Source)

         while locating org.eclipse.aether.internal.impl.DefaultRepositorySystem

         while locating java.lang.Object annotated with *

         while locating org.jvnet.jax_ws_commons.jaxws.MainWsImportMojo

       Caused by: java.lang.IllegalArgumentException: Can not set org.eclipse.aether.spi.log.Logger field org.apache.maven.repository.internal.DefaultVersionRangeResolver.logger to org.eclipse.aether.internal.impl.slf4j.Slf4jLoggerFactory

       	at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)

       	at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)

       	at java.base/jdk.internal.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)

       	at java.base/java.lang.reflect.Field.set(Field.java:780)

       	at org.eclipse.sisu.bean.BeanPropertyField.set(BeanPropertyField.java:72)

       	at org.eclipse.sisu.plexus.ProvidedPropertyBinding.injectProperty(ProvidedPropertyBinding.java:48)

       	at org.eclipse.sisu.bean.BeanInjector.injectMembers(BeanInjector.java:52)

       	at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:140)

       	at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:114)

       	at com.google.inject.internal.ConstructorInjector.access$000(ConstructorInjector.java:32)

       	at com.google.inject.internal.ConstructorInjector$1.call(ConstructorInjector.java:89)

       	at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:115)

       	at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:133)

       	at com.google.inject.internal.ProvisionListenerStackCallback.provision(ProvisionListenerStackCallback.java:68)

       	at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:87)

       	at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:267)

       	at com.google.inject.internal.FactoryProxy.get(FactoryProxy.java:56)

       	at com.google.inject.internal.InjectorImpl$2$1.call(InjectorImpl.java:1016)

       	at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103)

       	at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1012)

       	at org.eclipse.sisu.inject.Guice4$1.get(Guice4.java:162)

       	at org.eclipse.sisu.inject.LazyBeanEntry.getValue(LazyBeanEntry.java:81)

       	at org.eclipse.sisu.wire.BeanProviders.firstOf(BeanProviders.java:179)

       	at org.eclipse.sisu.wire.BeanProviders$7.get(BeanProviders.java:160)

       	at com.google.inject.internal.ProviderInternalFactory.provision(ProviderInternalFactory.java:81)

       	at com.google.inject.internal.InternalFactoryToInitializableAdapter.provision(InternalFactoryToInitializableAdapter.java:53)

       	at com.google.inject.internal.ProviderInternalFactory$1.call(ProviderInternalFactory.java:65)

       	at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:115)

       	at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:133)

       	at com.google.inject.internal.ProvisionListenerStackCallback.provision(ProvisionListenerStackCallback.java:68)

       	at com.google.inject.internal.ProviderInternalFactory.circularGet(ProviderInternalFactory.java:63)

       	at com.google.inject.internal.InternalFactoryToInitializableAdapter.get(InternalFactoryToInitializableAdapter.java:45)

       	at com.google.inject.internal.SingleParameterInjector.inject(SingleParameterInjector.java:38)

       	at com.google.inject.internal.SingleParameterInjector.getAll(SingleParameterInjector.java:62)

       	at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:104)

       	at com.google.inject.internal.ConstructorInjector.access$000(ConstructorInjector.java:32)

       	at com.google.inject.internal.ConstructorInjector$1.call(ConstructorInjector.java:89)

       	at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:115)

       	at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:133)

       	at com.google.inject.internal.ProvisionListenerStackCallback.provision(ProvisionListenerStackCallback.java:68)

       	at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:87)

       	at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:267)

       	at com.google.inject.internal.FactoryProxy.get(FactoryProxy.java:56)

       	at com.google.inject.internal.InjectorImpl$2$1.call(InjectorImpl.java:1016)

       	at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103)

       	at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1012)

       	at org.eclipse.sisu.inject.Guice4$1.get(Guice4.java:162)

       	at org.eclipse.sisu.inject.LazyBeanEntry.getValue(LazyBeanEntry.java:81)

       	at org.eclipse.sisu.plexus.LazyPlexusBean.getValue(LazyPlexusBean.java:51)

       	at org.eclipse.sisu.plexus.PlexusRequirements$RequirementProvider.get(PlexusRequirements.java:250)

       	at org.eclipse.sisu.plexus.ProvidedPropertyBinding.injectProperty(ProvidedPropertyBinding.java:48)

       	at org.eclipse.sisu.bean.BeanInjector.injectMembers(BeanInjector.java:52)

       	at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:140)

       	at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:114)

       	at com.google.inject.internal.ConstructorInjector.access$000(ConstructorInjector.java:32)

       	at com.google.inject.internal.ConstructorInjector$1.call(ConstructorInjector.java:89)

       	at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:115)

       	at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:133)

       	at com.google.inject.internal.ProvisionListenerStackCallback.provision(ProvisionListenerStackCallback.java:68)

       	at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:87)

       	at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:267)

       	at com.google.inject.internal.InjectorImpl$2$1.call(InjectorImpl.java:1016)

       	at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103)

       	at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1012)

       	at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1051)

       	at org.eclipse.sisu.space.AbstractDeferredClass.get(AbstractDeferredClass.java:48)

       	at com.google.inject.internal.ProviderInternalFactory.provision(ProviderInternalFactory.java:81)

       	at com.google.inject.internal.InternalFactoryToInitializableAdapter.provision(InternalFactoryToInitializableAdapter.java:53)

       	at com.google.inject.internal.ProviderInternalFactory$1.call(ProviderInternalFactory.java:65)

       	at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:115)

       	at org.eclipse.sisu.bean.BeanScheduler$Activator.onProvision(BeanScheduler.java:176)

       	at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:126)

       	at com.google.inject.internal.ProvisionListenerStackCallback.provision(ProvisionListenerStackCallback.java:68)

       	at com.google.inject.internal.ProviderInternalFactory.circularGet(ProviderInternalFactory.java:63)

       	at com.google.inject.internal.InternalFactoryToInitializableAdapter.get(InternalFactoryToInitializableAdapter.java:45)

       	at com.google.inject.internal.InjectorImpl$2$1.call(InjectorImpl.java:1016)

       	at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1092)

       	at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1012)

       	at org.eclipse.sisu.inject.Guice4$1.get(Guice4.java:162)

       	at org.eclipse.sisu.inject.LazyBeanEntry.getValue(LazyBeanEntry.java:81)

       	at org.eclipse.sisu.plexus.LazyPlexusBean.getValue(LazyPlexusBean.java:51)

       	at org.codehaus.plexus.DefaultPlexusContainer.lookup(DefaultPlexusContainer.java:263)

       	at org.codehaus.plexus.DefaultPlexusContainer.lookup(DefaultPlexusContainer.java:255)

       	at org.apache.maven.plugin.internal.DefaultMavenPluginManager.getConfiguredMojo(DefaultMavenPluginManager.java:517)

       	at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:121)

       	at org.twdata.maven.mojoexecutor.MojoExecutor.executeMojo(MojoExecutor.java:119)

       	at de.codecentric.cxf.BootCxfMojo.generateJaxbClassFiles(BootCxfMojo.java:88)

       	at de.codecentric.cxf.BootCxfMojo.execute(BootCxfMojo.java:69)

       	at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)

       	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:207)

       	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)

       	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)

       	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)

       	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)

       	at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)

       	at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)

       	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)

       	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)

       	at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)

       	at org.apache.maven.cli.MavenCli.execute(MavenCli.java:863)

       	at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)

       	at org.apache.maven.cli.MavenCli.main(MavenCli.java:199)

       	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

       	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

       	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

       	at java.base/java.lang.reflect.Method.invoke(Method.java:566)

       	at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)

       	at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)

       	at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)

       	at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
...
       [ERROR] 

       [ERROR] 8 errors

       [ERROR] role: org.apache.maven.plugin.Mojo

       [ERROR] roleHint: com.sun.xml.ws:jaxws-maven-plugin:2.3.2:wsimport

       [ERROR] -> [Help 1]

       [ERROR] 

       [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.

       [ERROR] Re-run Maven using the -X switch to enable full debug logging.

       [ERROR] 

       [ERROR] For more information about the errors and possible solutions, please read the following articles:

       [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

 !     ERROR: Failed to build app with Maven

       We're sorry this build is failing! If you can't find the issue in application code,

       please submit a ticket so we can help: https://help.heroku.com/

 !     Push rejected, failed to compile Java app.

 !     Push failed

Seems, that we need to use a newer Maven version on Heroku (see spotify/dockerfile-maven#252).

FailureAnalyzer for missing cxf-spring-boot-maven.properties

The new Complete Automation of Endpoint Initialization is working great. It is 100% dependent of a pre-runned cxf-spring-boot-maven-plugin mvn clean generate-sources, which produces the cxf-spring-boot-maven.properties with the needed package names.

A Spring Boot Failure Analyzer would be great for that - also accompanied with the SystemOutRule to grab the Logoutput (see https://github.com/codecentric/cxf-spring-boot-starter/blob/master/src/test/java/de/codecentric/cxf/logging/SleuthLogMessagesTest.java).

Complete Automation of Endpoint Initialization

Autodetect everything needed to initialize javax.xml.ws.Endpoint completely based upon generated Class files.

Background: The cxf-spring-boot-starter-maven-plugin generates two Class files among others:
One representing your Service Endpoint Interface (SEI) - annotated with javax.jws.WebService - and another WebServiceClient class - which implements javax.xml.ws.Service. Both are needed to initialize the javax.xml.ws.Endpoint for publishing it with Apache CXF. In traditional way with Spring Boot, but without the cxf-spring-boot-starter, this is done like that:

@Bean
public WeatherService weatherService() {
    return new WeatherServiceEndpoint();
}

@Bean
public Endpoint endpoint() {
    EndpointImpl endpoint = new EndpointImpl(springBus, weatherService());        
    // CXF JAX-WS implementation relies on the correct ServiceName as QName-Object with
    // the name-Attribute´s text <wsdl:service name="Weather"> and the targetNamespace
    // "http://www.codecentric.de/namespace/weatherservice/"
    // Also the WSDLLocation must be set
    endpoint.setServiceName(weather().getServiceName());
    endpoint.setWsdlLocation(weather().getWSDLDocumentLocation().toString());
    endpoint.publish(PUBLISH_URL_ENDING);
    return endpoint;
}

@Bean
public Weather weather() {
    // Needed for correct ServiceName & WSDLLocation to publish contract first incl. original WSDL
    return new Weather();
}

Now the idea is, that this is all boilerplate - if you like to run your SOAP web services in a contract first manner. Because then, everything is quite clear from your starting point - the WSDL and XSD files. There you have already the Name of your Service and all it´s methods. It should be possible to initialize the CXF endpoint from that information. Prerequisites remain the generation of the Java classes via the cxf-spring-boot-starter-maven-plugin and a manual implementation of the Service Endpoint Interface (SEI), because that´s the place where you´re service coding starts - we shouldn´t generate that one for you.

With this feature, you dont´t have to do a lot any more - the hole Endpoint initialization (including the definition of a WebService URL) is done for you.

Upgrade base cxf version from 3.2.1 to latest 3.2.5 to get important fix in cxf and wss4j and also provide support for Spring boot 2 :)

Hi,

Current CXF version used by your starter is quite old (3.2.1 where latest released version is 3.2.5).

Since 3.2.2, CXF references org.apache.wss4j in version 2.2.1 in which there is support to load security properties file from filepath instead of classpath which is very interesting feature when we deploy cxf application where security properties could be different according to destination infrastructure (DevOps context see related fixed issue in wss4j https://issues.apache.org/jira/browse/WSS-540).

In such scenario we couldn't embed such file in JAR file that could be resolved through the classPath.

For instance I have explicitly excluded cxf dependencies targeting cxf 3.2.1 from your very useful starter to load 3.2.2 instead.

Regards.

Spring Boot 2: Error creating bean with name 'org.springframework.cloud.netflix.zuul.ZuulProxyAutoConfiguration': Post-processing of merged bean definition failed; nested exception is java.lang.IllegalStateException: Failed to introspect Class [org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration] from ClassLoader [java.net.URLClassLoader]

2017-12-22 16:35:26.093 INFO 8336 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2017-12-22 16:35:26.094 INFO 8336 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.23
2017-12-22 16:35:26.110 INFO 8336 --- [ost-startStop-1] o.a.catalina.core.AprLifecycleListener : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/Users/jagapathiraju/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.]
2017-12-22 16:35:26.188 INFO 8336 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2017-12-22 16:35:26.189 INFO 8336 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1549 ms
2017-12-22 16:35:26.270 ERROR 8336 --- [ost-startStop-1] o.s.b.web.embedded.tomcat.TomcatStarter : Error starting Tomcat context. Exception: org.springframework.beans.factory.BeanCreationException. Message: Error creating bean with name 'org.springframework.cloud.netflix.zuul.ZuulProxyAutoConfiguration': Post-processing of merged bean definition failed; nested exception is java.lang.IllegalStateException: Failed to introspect Class [org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration] from ClassLoader [java.net.URLClassLoader@227fcef5]
2017-12-22 16:35:26.293 WARN 8336 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
[WARNING]
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:496)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:153)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:138)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:751)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:387)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:327)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1245)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1233)
at com.raju.tech.SpringWeb.main(SpringWeb.java:12)
... 6 more
Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:117)
at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.(TomcatWebServer.java:84)
at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:413)
at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:176)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:177)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:150)
... 14 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.cloud.netflix.zuul.ZuulProxyAutoConfiguration': Post-processing of merged bean definition failed; nested exception is java.lang.IllegalStateException: Failed to introspect Class [org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration] from ClassLoader [java.net.URLClassLoader@227fcef5]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:560)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:368)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1250)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1099)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
at org.springframework.boot.web.servlet.ServletContextInitializerBeans.getOrderedBeansOfType(ServletContextInitializerBeans.java:228)
at org.springframework.boot.web.servlet.ServletContextInitializerBeans.getOrderedBeansOfType(ServletContextInitializerBeans.java:215)
at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addServletContextInitializerBeans(ServletContextInitializerBeans.java:91)
at org.springframework.boot.web.servlet.ServletContextInitializerBeans.(ServletContextInitializerBeans.java:79)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getServletContextInitializerBeans(ServletWebServerApplicationContext.java:248)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.selfInitialize(ServletWebServerApplicationContext.java:235)
at org.springframework.boot.web.embedded.tomcat.TomcatStarter.onStartup(TomcatStarter.java:54)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5196)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1419)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
... 1 more
Caused by: java.lang.IllegalStateException: Failed to introspect Class [org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration] from ClassLoader [java.net.URLClassLoader@227fcef5]
at org.springframework.util.ReflectionUtils.getDeclaredFields(ReflectionUtils.java:759)
at org.springframework.util.ReflectionUtils.doWithLocalFields(ReflectionUtils.java:691)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.buildResourceMetadata(CommonAnnotationBeanPostProcessor.java:355)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.findResourceMetadata(CommonAnnotationBeanPostProcessor.java:339)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(CommonAnnotationBeanPostProcessor.java:298)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:1016)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
... 29 more
Caused by: java.lang.NoClassDefFoundError: Lorg/springframework/boot/autoconfigure/web/servlet/error/ErrorController;
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2583)
at java.lang.Class.getDeclaredFields(Class.java:1916)
at org.springframework.util.ReflectionUtils.getDeclaredFields(ReflectionUtils.java:754)
... 35 more
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.autoconfigure.web.servlet.error.ErrorController
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 39 more
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.190 s
[INFO] Finished at: 2017-12-22T16:35:26+05:30
[INFO] Final Memory: 58M/402M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.0.0.M7:run (default-cli) on project spring-web: An exception occurred while running. null: InvocationTargetException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat: Error creating bean with name 'org.springframework.cloud.netflix.zuul.ZuulProxyAutoConfiguration': Post-processing of merged bean definition failed; nested exception is java.lang.IllegalStateException: Failed to introspect Class [org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration] from ClassLoader [java.net.URLClassLoader@227fcef5]: Lorg/springframework/boot/autoconfigure/web/servlet/error/ErrorController;: org.springframework.boot.autoconfigure.web.servlet.error.ErrorController -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

Process finished with exit code 1

wsimport jvm arguments

It looks like you are already passing in wsimpot jvm argument "-Djavax.xml.accessExternalSchema=all". I also want to pass in "-Djavax.xml.accessExternalDTD=all".

Is this possible ?

Maven Enforcer Plugin

I always use maven-enforcer-plugin in my spring-boot apps, but I seem to get some dependency mismatches:
The plugin:

<build>
        <plugins>
            <plugin>
                <artifactId>maven-enforcer-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>enforce</goal>
                        </goals>
                        <configuration>
                            <rules>
                                <dependencyConvergence/>
                            </rules>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

The result:

Dependency convergence error for com.sun.xml.fastinfoset:FastInfoset:1.2.15 paths to dependency are:
  +-de.codecentric:cxf-spring-boot-starter:2.1.7.RELEASE
    +-de.codecentric:cxf-spring-boot-starter-maven-plugin:2.1.7.RELEASE
      +-org.glassfish.jaxb:jaxb-runtime:2.3.1
        +-com.sun.xml.fastinfoset:FastInfoset:1.2.15
and
  +-de.codecentric:cxf-spring-boot-starter:2.1.7.RELEASE
    +-de.codecentric:cxf-spring-boot-starter-maven-plugin:2.1.7.RELEASE
      +-com.sun.xml.ws:jaxws-rt:2.3.2
        +-com.sun.xml.fastinfoset:FastInfoset:1.2.16
Dependency convergence error for org.apache.maven:maven-artifact:3.6.0 paths to dependency are:
  +-de.codecentric:cxf-spring-boot-starter:2.1.7.RELEASE
    +-de.codecentric:cxf-spring-boot-starter-maven-plugin:2.1.7.RELEASE
      +-org.apache.maven:maven-plugin-api:3.6.0
        +-org.apache.maven:maven-artifact:3.6.0
and
  +-de.codecentric:cxf-spring-boot-starter:2.1.7.RELEASE
    +-de.codecentric:cxf-spring-boot-starter-maven-plugin:2.1.7.RELEASE
      +-org.twdata.maven:mojo-executor:2.3.0
        +-org.apache.maven:maven-core:3.0.5
          +-org.apache.maven:maven-artifact:3.0.5
Dependency convergence error for org.apache.maven:maven-artifact:3.6.0 paths to dependency are:
  +-de.codecentric:cxf-spring-boot-starter:2.1.7.RELEASE
    +-de.codecentric:cxf-spring-boot-starter-maven-plugin:2.1.7.RELEASE
      +-org.apache.maven:maven-plugin-api:3.6.0
        +-org.apache.maven:maven-artifact:3.6.0
and
  +-de.codecentric:cxf-spring-boot-starter:2.1.7.RELEASE
    +-de.codecentric:cxf-spring-boot-starter-maven-plugin:2.1.7.RELEASE
      +-org.twdata.maven:mojo-executor:2.3.0
        +-org.apache.maven:maven-core:3.0.5
          +-org.apache.maven:maven-artifact:3.0.5

These are not all of them.

Autowired constructor not working

I can't use a constructor with the @Autowired annotation.

@Autowired
public endpointImpl(Service service){...}

The parameters are null.
It is only possible with @Autowired fields.
This solves my problem but our team internal convention says that the use of @Autowired constructors is prefered because it makes unit testing easier.

Is it possible to use Autowired constructors ?
Its strange that the @Autowired annotation works on fields but not on the constructor and kinda not the way spring works.

Show the base package from the scan

We were debugging a problem were the implementation was in another package that wasn't considered by the scanner. I would like to add the base packager of the scanner to the output of the failure analyzer:

Action:

Build a Class that implements your Service Endpoint Interface (SEI): >'de.codecentric.namespace.weatherservice.WeatherService' and is present in a scanned sub-package of: >'de.codecentric'.

SoapRawClient fails with MTOM

When the CXF server enables MTOM, the SoapRawClient will fail to parse the xml.

@WebService
@MTOM(threshold = 2 * 1024 * 1024)
public class XXXEndpoint implements XXXServicePortType {

Reason:
CXF always sends multipart http request. That means that the xml parser will fail.

Outbound Message:

--uuid:052ebfc6-8d20-4545-8d26-93fa4573631c
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml"
Content-Transfer-Encoding: binary
Content-ID: <[email protected]>

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode>soap:Client</faultcode><faultstring>Message part {http://www.codecentric.de/namespace/weatherservice/general}GetCityForecastByZIP was not recognized.  (Does it exist in service WSDL?)</faultstring></soap:Fault></soap:Body></soap:Envelope>
--uuid:052ebfc6-8d20-4545-8d26-93fa4573631c--

Any idea what to do here? We could parse the message, but maybe you have experience how to it?

inconsistent results from jaxws version 3.3.3, earlier versions have the same issue

From a soap call hitting our implementation method after going through jaxws, the issue is with our bean that is using big int. The problem is when input of + and - values. We are getting inconsistent results causing issues with our venerability scans since the calculations are performed before our validations on the field values

test data results
9 returns in int value of 9 set - correct
9+9 returns consistent result eliminating the +
9-9 returns - consistent result making negative after concatenation
0+0+0+9 returns 9 as expected
12345-12345+9 -returns 539778429 not sure what is happening here ***** ISSUE
12345-1234-9 returns -1234512349 seems to be consistent with earlier results
289 -289 +9 returns -2892899 again consistent with earlier results

More than one wsdl?

Would it be possible to use more than one wsdl? I followed your tutorial over at codecentric. I added 2, not 1 wsdl, changed SimpleBootCxfConfiguration to have 2 Endpoints and Clients, created the 2 Endpoint classes, etc.

The Java classes for both wsdl's are generated properly, but when I run spring-boot:run I get this error:

Could not find service named {http://RegistrationServices}Transactions in wsdl file:/.../RetrieveMessages.wsdl

it's looking for services defined in the 2nd wsdl (transactions.wsdl) in the 1st wsdl (retrieveMessages.wsdl).

Is there any way to get this to work, or do I have to run 2 separate Spring Boot apps, one for each wsdl?

Thanks!

WSDL path in cxf-boot-simple Heroku deployment wrong

The example app cxf-boot-simple is deployed and running successfully on Heroku: https://cxf-boot-simple.herokuapp.com/my-foo-api

But the WSDL path has wrong curl braces inside it's URL and therefore isn't accessible:

{http://www.codecentric.de/namespace/weatherservice/}Weather, but the URL itself shows the following link: https://cxf-boot-simple.herokuapp.com/Weather?wsdl

If you access it, it shows a

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.
Mon Aug 05 12:56:39 CEST 2019
There was an unexpected error (type=Not Found, status=404).
No message available

Make Calltime-Logging optional

If you start with a fresh new project, it´s irritating that you get Console Outputs like

2016-09-30 09:16:59.837 INFO 28878 --- [nio-8080-exec-5] d.c.cxf.logging.LogCorrelationFilter : 009 >>> Calltime: 122

Allthough it´s a feature for Elasticsearch Field extraction, this should be configurable (maybe via the soap.messages.extract property)

Client only mode and soap logging properties does not recognoise by spring boot?

Hello.
I have project based on application.yml, when I trying to use:
soap:
messages:
extract: true

and
endpoint:
autoinit: false

spring boot do not understand this properties, how to fix this options? spring boot 2.1.6 version of cxf plugin and dep 2.1.7 and 2.1.6 releses

Also may be some one can take me a link to client only soap service with this plugins and dependencies?

CxfAutoConfiguration.baseAndServiceEndingUrl() just concatenates the strings, should it do more?

The CxfAutoConfiguration.baseAndServiceEndingUrl() method returns a concatenation of the baseUrl and serviceUrlEnding which might lead to unexpected addresses.

If we have the following configuration:

soap.service.base.url=/root/

The baseAndServiceEndingUrl will be "/root//YourService", which isn't exactly expected in my opinion. Shouldn't the baseAndServiceEndingUrl() strip trailing/leading/double-slashes from the address?

Better support for more than one WebService instance (Service Registry, Proxy, Edge-Service - e.g. w/ Spring Cloud Netflix)

As mentioned in #10 it is a common scenario to use the cxf-spring-boot-starter with more than one service instance (= more than one WSDL). Although we don´t want to support more than one WSDL inside the same Spring Boot service instance, we want to better support the scenario where one uses one WSDL per instance but in many instances and want to have a single entry-point into the WebServices landscape.

Handling of reverse proxies

Currently it is not possible to publish the CXF Services behind a reverse proxy and return the correct adresses in the WSDL when querying the live service.

Nginx as a reverse proxy with the following location:

nginx config with this location:

`location /service-location {

rewrite ^/service-location/(.*)$ real-endpoint/$1 break;
  
proxy_pass  http://some-container:8080;

proxy_set_header Host $host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}`

Our CXF Service is running in the docker container some-container on port 8a080.

When calling nginx/service-location/Service?wsdl the wsdl will not reflect the correct location of the client (WSDL contains real-endpoint instead of service-location). This makes the WSDL useless for a web service client generation process.

CxfAutoConfiguration is not extendable.

The CxfAutoConfiguration class is neither extendable nor easily modifiable. For example creating a custom serviceUrlEnding on the fly based on the WebServiceClient is not possible because the member is declared private and the methods inside the class do not use the serviceUrlEnding() method.

Either the members should all be made protected or the endpoint() method should be using the getters to retrieve the values. That would allow extending classes to override these values with dynamic ones. Additionally, the creation (without the publish() call) of the EndpointImpl should be moved to a protected method to give the possibility to modify the created instance before it is being published.

Support both SOAP 1.1 and 1.2 at the same time (handling two wsdl:port)

Greetings, thanks for the tutorial, is very detailed.
On the tutorial, you removed the additional ports to reduce the complexity.

I'm looking for a way to handle multiple versions of soap (1.1 and 1.2) as ports on the same service.

Something like that:

<wsdl:service name="someService">
	<wsdl:port name="SomeServicePort11" binding="ns0:SomeServicePortBinding">
		<soap11:address location="https://localhost:443/someService"/>
	</wsdl:port>
	<wsdl:port name="SomeServicePort12" binding="ns2:SomeServicePortBinding">
		<soap12:address location="https://localhost:443/someService"/>
	</wsdl:port>
</wsdl:service>

When I used wsimport on wsdl address, it just created one service interface.
I din't find any like that using jax ws, just using the SpringWS implementation.

Thank's in advance.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.