I am new to Vaadin, just generated the application in Vaadin web site and built it locally. Then I added Apache CXF SOAP service to it, but I am unable to use the Tomcat that Vaadin is using, but instead I load SOAP in Jetty using:
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${cxf.version}</version>
<scope>compile</scope>
</dependency>
My Vaadin application is:
@SpringBootApplication
@Theme(value = "iciclient", variant = Lumo.DARK)
@PWA(name = "ICI Client", shortName = "ICI Client", offlineResources = {"images/logo.png"})
public class Application extends SpringBootServletInitializer implements AppShellConfigurator {
public static void main(String[] args) {
LaunchUtil.launchBrowserInDevelopmentMode(SpringApplication.run(Application.class, args));
try {
System.out.println("Starting IciEventClient");
Object implementor = new IciEventServiceSoap12Impl();
String address = "http://localhost:8081/ici/IciEventService";
Endpoint.publish(address, implementor);
// http://localhost:8081/ici/IciEventService?WSDL
} catch (Exception e) {
e.printStackTrace();
}
}
}
While this works, I would like to get rid of separate Jetty dependency and run the SOAP service in Vaadin Tomcat (localhost:8080). Should be simple but I can’t figure out how to do it. I think that it needs a separate servlet and route, but I don’t know how to add them. There is no web.xml in the Vaadin application, for example.
Advertisement
Answer
I am not familiar with Apache CXF, but based on CXF docs and the sample project I think I got it to work.
I downloaded a new Vaadin 14/Java 8 project from start.vaadin.com, and did the following:
Added the dependency
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-spring-boot-starter-jaxws</artifactId> <version>3.4.3</version> </dependency>Created a web service
import javax.jws.WebMethod; import javax.jws.WebService; @WebService public class Test { @WebMethod public String test() { return "This works"; } }Exposed it as a bean in my
Applicationclassimport javax.xml.ws.Endpoint; import org.apache.cxf.Bus; import org.apache.cxf.jaxws.EndpointImpl; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; import org.vaadin.artur.helpers.LaunchUtil; import org.vaadin.erik.endpoint.Test; @SpringBootApplication public class Application extends SpringBootServletInitializer { public static void main(String[] args) { LaunchUtil.launchBrowserInDevelopmentMode(SpringApplication.run(Application.class, args)); } @Bean public Endpoint test(Bus bus) { EndpointImpl endpoint = new EndpointImpl(bus, new Test()); endpoint.publish("/Test"); return endpoint; } }
That was it! At least I can now list the service definition at http://localhost:8080/services/Test?wsdl
The first documentation link lists some configurations you can do, for example to change the /services path. The example project shows how to configure Spring actuator metrics if that is something you need.
You might want to create a separate @Configuration-annotated class for all your service @Bean definitions.
If you don’t want to use the starter dependency, this Baeldung article looks promising.