CXF with Spring-Boot
Asked Answered
M

3

6

I am attempting to get CXF and Sprint Boot to play nicely. I have a JAX-WS service endpoint called SubscriberApi. Looking at the spring-boot logs I see successful mapping:

Mapping servlet: 'CXFServlet' to [/api/*]
Setting the server's publish address to be /SubscriberApi

However, I cant seem to get the WSDL when hitting:

http://localhost:8080/api/SubscriberApi?wsdl
@Configuration
@ImportResource({"classpath:META-INF/cxf/cxf.xml"})
public class CxfConfiguration  {
  @Bean
  public SubscriberApi subscriberApi() {
    return new SubscriberApi();
  }
  @Bean
  public ServletRegistrationBean servletRegistrationBean() {
    CXFServlet cxfServlet = new CXFServlet();

    ServletRegistrationBean servletRegistrationBean =
        new ServletRegistrationBean(cxfServlet, "/api/*");
    servletRegistrationBean.setLoadOnStartup(1);
    return servletRegistrationBean;
  }
  @DependsOn("servletRegistrationBean")
  @Bean
  public Endpoint jaxwsEndpoint(SubscriberApi subscriberApi){
    javax.xml.ws.Endpoint jaxwsEndpoint =
        javax.xml.ws.Endpoint.publish("/SubscriberApi", subscriberApi);
      return jaxwsEndpoint;
  }
 }
Materiel answered 24/11, 2014 at 20:21 Comment(0)
R
3

Have your jaxwsEndpoint bean return an instance of org.apache.cxf.jaxws.EndpointImpl, which extends javax.xml.ws.Endpoint:

@Autowired
private ApplicationContext applicationContext;

@DependsOn("servletRegistrationBean")
@Bean
public Endpoint jaxwsEndpoint(){
   Bus bus = (Bus) applicationContext.getBean(Bus.DEFAULT_BUS_ID);
   EndpointImpl endpoint = new EndpointImpl(bus, subscriberApi());
   endpoint.publish("/SubscriberApi");
   // also showing how to add interceptors
   endpoint.getServer().getEndpoint().getInInterceptors().add(new LoggingInInterceptor());
   endpoint.getServer().getEndpoint().getOutInterceptors().add(new LoggingOutInterceptor());

   return endpoint;
}

The original post doesn't include a runnable example, but this should solve the issue.

A running example can be found here, with all the configuration linked together: Application.java

Reticule answered 12/3, 2015 at 19:33 Comment(0)
S
4

There's a much easier way to get Spring Boot & Apache CXF running and providing a SOAP webservice based on your WSDL file: Just use the cxf-spring-boot-starter, which does everything for you. You only need to use the starter and it's companion Maven plugin in your pom.xml like this (full example!):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>de.codecentric.soap</groupId>
    <artifactId>cxf-boot-simple</artifactId>
    <version>2.1.2-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>cxf-boot-simple</name>
    <description>Demo project for using Spring Boot Starter CXF</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.2.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>cxf-spring-boot-starter</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>de.codecentric</groupId>
                <artifactId>cxf-spring-boot-starter-maven-plugin</artifactId>
                <version>2.0.0.RELEASE</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Place your wsdl somewhere inside src/main/resources, implement your endpoint class and your done!. That's really everything, no manual boilerplate coding (no ServletRegistrationBean etc.). This is just generated for you based on the WSDL - 100% contract first.

Here's also a fully comprehensible example project: https://github.com/codecentric/spring-samples/tree/master/cxf-boot-simple. And there's also a blog post series, which will introduce you to everything related to know: https://blog.codecentric.de/en/2016/10/spring-boot-apache-cxf-spring-boot-starter/ Have fun!

Simeon answered 2/2, 2019 at 11:55 Comment(4)
What is the difference between apache's cxf-spring-boot-starter-jaxws and codecentric's cxf-spring-boot-starter?Nablus
The answer is in the very first paragraph of blog.codecentric.de/en/2016/10/… But wait! Isn´t there an official Apache CXF spring-boot-starter?. In short: The Apache starter only initializes parts of CXF, where the codecentric starter takes care of every needed component, initializes every boilerplate needed, generates the JAX-B class files automatically based on your WSDL (full contract first support), eases logging of SOAP messages and much more.Simeon
Hey @jonashackt, just a reminder that you are supposed to disclose your affiliation in the post. I also noticed that the blog link you provide now leads to a page in German (despite the en in the link), and the language selector does not work there. The GitHub repo also appears to have moved.Copyboy
I was quite hopeful with this solution, but I just realized that it hasn’t been upgraded for the Jakarta migration, and it does not seem to be maintained anymore. Might be worth mentioning it in the answer too. (To be frank, I think it would have been much better to contribute the improvements to the CXF project rather than creating a new plugin and library…)Copyboy
R
3

Have your jaxwsEndpoint bean return an instance of org.apache.cxf.jaxws.EndpointImpl, which extends javax.xml.ws.Endpoint:

@Autowired
private ApplicationContext applicationContext;

@DependsOn("servletRegistrationBean")
@Bean
public Endpoint jaxwsEndpoint(){
   Bus bus = (Bus) applicationContext.getBean(Bus.DEFAULT_BUS_ID);
   EndpointImpl endpoint = new EndpointImpl(bus, subscriberApi());
   endpoint.publish("/SubscriberApi");
   // also showing how to add interceptors
   endpoint.getServer().getEndpoint().getInInterceptors().add(new LoggingInInterceptor());
   endpoint.getServer().getEndpoint().getOutInterceptors().add(new LoggingOutInterceptor());

   return endpoint;
}

The original post doesn't include a runnable example, but this should solve the issue.

A running example can be found here, with all the configuration linked together: Application.java

Reticule answered 12/3, 2015 at 19:33 Comment(0)
H
1

You can now use autoconfiguration with a Spring Boot CXF starter by adding:

<dependency>
  <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
  <version>3.1.7</version>
</dependency>

See also: http://cxf.apache.org/docs/springboot.html

Hedge answered 28/7, 2016 at 12:39 Comment(1)
This is good one, but doesn't have support to bootstrapping spring inside cxf endpointWeariless

© 2022 - 2024 — McMap. All rights reserved.