Search code examples
springspring-bootspring-wsspring-boot-actuator

Spring boot web services with actuator


I checked few other similar questions, but didn't found solution.

So I have spring boot project with web services configured:

@Configuration
public class WebServiceConfig {

@Autowired
private Bus bus;

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

ServiceImpl, like:

@javax.jws.WebService(serviceName = "ServiceImpl", portName = "ServiceImplPort", targetNamespace = "http://serivce.com/", endpointInterface = "pac.service...")
public class ServiceImpl... 

service is working fine.

My POM for that implementation looks like:

...
<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-ws</artifactId>
        <version>1.3.5.RELEASE</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
        <version>3.1.7</version>
    </dependency>
   ...

MainClass:

 @Configuration
 @EnableAutoConfiguration
 @EnableScheduling
 @EnableWebMvc
 @ComponentScan("com.package")
 public class Application extends SpringBootServletInitializer {

public static void main(String[] args) throws Exception {
    SpringApplication.run(Application.class, args);
}

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    return application.sources(Application.class);
} }

So far, everything is working fine- WS is reachable, but If I add to POM:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-actuator</artifactId>
        <version>1.3.5.RELEASE</version>
    </dependency>

application start, I can see in logs:

EndpointHandlerMapping: Mapped "{[/info

EndpointHandlerMapping: Mapped "{[/health etc.

and also:

ServerImpl: Setting the server's publish address to be /ws

so it's starting without any error and it looks like actuator should work, but when I tried invoke actuator endpoints I get 404 error.

when I invoke: localhost:8081/info

i get: No service was found.

I tried use:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

but then WS was unreachable (as well as actuator endpoints)

any suggestion?


Solution

  • You've mapped Spring Boot's dispatcher servlet to / and CXF's servlet to /*. This is shown in your application's log output:

    2016-09-18 19:51:20.538  INFO 31932 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
    2016-09-18 19:51:20.540  INFO 31932 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'CXFServlet' to [/*]
    

    These mappings clash and the CXF servlet wins. This means that it'll handle every request that's made to your application. This prevents Spring Boot's actuator from handling the request to /info for example.

    You can fix the problem by moving CXF to another path by configuring cxf.path in application.properties:

    cxf.path=/cxf
    

    This will then change the mapping of its servlet accordingly:

    2016-09-18 19:52:35.203  INFO 32213 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
    2016-09-18 19:52:35.205  INFO 32213 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'CXFServlet' to [/cxf/*]
    

    You can now access the actuator's /info endpoint:

    curl localhost:8080/info -i
    HTTP/1.1 200 OK
    Server: Apache-Coyote/1.1
    X-Application-Context: application
    Content-Type: application/json;charset=UTF-8
    Transfer-Encoding: chunked
    Date: Sun, 18 Sep 2016 18:57:08 GMT
    
    {}
    

    And the WSDL of your CXF-based service:

    $ curl http://localhost:8080/cxf/ws/Hello?WSDL -i
    HTTP/1.1 200 OK
    Server: Apache-Coyote/1.1
    X-Application-Context: application
    Content-Type: text/xml;charset=UTF-8
    Content-Length: 2286
    Date: Sun, 18 Sep 2016 18:59:17 GMT
    
    <?xml version='1.0' encoding='UTF-8'?><wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://service.ws.sample/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="HelloService" targetNamespace="http://service.ws.sample/">
      <wsdl:types>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://service.ws.sample/" elementFormDefault="unqualified" targetNamespace="http://service.ws.sample/" version="1.0">
    
      <xs:element name="sayHello" type="tns:sayHello"/>
    
      <xs:element name="sayHelloResponse" type="tns:sayHelloResponse"/>
    
      <xs:complexType name="sayHello">
        <xs:sequence>
          <xs:element minOccurs="0" name="myname" type="xs:string"/>
        </xs:sequence>
      </xs:complexType>
    
      <xs:complexType name="sayHelloResponse">
        <xs:sequence>
          <xs:element minOccurs="0" name="return" type="xs:string"/>
        </xs:sequence>
      </xs:complexType>
    
    </xs:schema>
      </wsdl:types>
      <wsdl:message name="sayHello">
        <wsdl:part element="tns:sayHello" name="parameters">
        </wsdl:part>
      </wsdl:message>
      <wsdl:message name="sayHelloResponse">
        <wsdl:part element="tns:sayHelloResponse" name="parameters">
        </wsdl:part>
      </wsdl:message>
      <wsdl:portType name="Hello">
        <wsdl:operation name="sayHello">
          <wsdl:input message="tns:sayHello" name="sayHello">
        </wsdl:input>
          <wsdl:output message="tns:sayHelloResponse" name="sayHelloResponse">
        </wsdl:output>
        </wsdl:operation>
      </wsdl:portType>
      <wsdl:binding name="HelloServiceSoapBinding" type="tns:Hello">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="sayHello">
          <soap:operation soapAction="urn:SayHello" style="document"/>
          <wsdl:input name="sayHello">
            <soap:body use="literal"/>
          </wsdl:input>
          <wsdl:output name="sayHelloResponse">
            <soap:body use="literal"/>
          </wsdl:output>
        </wsdl:operation>
      </wsdl:binding>
      <wsdl:service name="HelloService">
        <wsdl:port binding="tns:HelloServiceSoapBinding" name="HelloPort">
          <soap:address location="http://localhost:8080/cxf/ws/Hello"/>
        </wsdl:port>
      </wsdl:service>
    </wsdl:definitions>