7
votes

I try to create a wadl from an existing CXF rest service. It does not work. I am getting instead HTTP 404. The rest service itself does work. I use Tomcat 7.

What am I doing wrong?

Server Information
Tomcat Version  JVM Version     JVM Vendor  OS Name     OS Version  OS Architecture     Hostname    IP Address
Apache Tomcat/7.0.52 (Ubuntu)   1.7.0_72-b14    Oracle Corporation  Linux   3.13.0-43-generic   amd64   myself  127.0.1.1

/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring-cxf-rest-example.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>CXFServlet</servlet-name>
        <servlet-class>
            org.apache.cxf.transport.servlet.CXFServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>CXFServlet</servlet-name>
        <url-pattern>/services/*</url-pattern>
    </servlet-mapping>

</web-app>

/WEB-INF/spring-cxf-rest-example.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jaxrs="http://cxf.apache.org/jaxrs"
       xmlns:cxf="http://cxf.apache.org/core"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                        http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
                        http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">

    <context:component-scan base-package="com.myself" />

    <jaxrs:server id="exampleCxfServer" address="/">
        <jaxrs:serviceBeans>
            <ref bean="exampleService"/>
        </jaxrs:serviceBeans>
        <jaxrs:extensionMappings>
            <entry key="json" value="application/json"/>
        </jaxrs:extensionMappings>
        <jaxrs:features>
            <cxf:logging/>
        </jaxrs:features>
        <jaxrs:providers>
            <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />
        </jaxrs:providers>
    </jaxrs:server>

</beans>

pom.xml

<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.myself</groupId>
  <artifactId>cxf3example</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>cxf3example Maven Webapp</name>
  <url>http://maven.apache.org</url>

    <properties>
        <spring.version>4.0.0.RELEASE</spring.version>
        <cxf.version>3.0.0</cxf.version>
        <jackson.version>2.0.1</jackson.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.jaxrs</groupId>
            <artifactId>jackson-jaxrs-json-provider</artifactId>
            <version>${jackson.version}</version>
        </dependency>
    </dependencies>

    <build>
        <sourceDirectory>src</sourceDirectory>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <!--
                    <source>1.8</source>
                    <target>1.8</target>
                    -->
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <warSourceDirectory>WebContent</warSourceDirectory>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>

        <finalName>cxf3example</finalName>
    </build>  

</project>

ExampleService.java

package com.myself.service;

import com.myself.model.ExampleModel;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

@Path("/example")
@Produces("application/json")
public interface ExampleService {

    @GET
    @Path("/{id}")
    public ExampleModel get(@PathParam("id") String id);

}

ExampleServiceImpl.java

package com.myself.service;

import com.myself.model.ExampleModel;
import org.springframework.stereotype.Service;

@Service("exampleService")
public class ExampleServiceImpl implements ExampleService {

    @Override
    public ExampleModel get(String modelId) {
        return new ExampleModel("example", 1001);
    }
}

ExampleModel.java

package com.myself.model;

public class ExampleModel {
    private String string;
    private int anInt;

    public ExampleModel() {}

    public ExampleModel(String string, int anInt) {
        this.string = string;
        this.anInt = anInt;
    }

    public String getString() {
        return string;
    }

    public void setString(String string) {
        this.string = string;
    }

    public int getAnInt() {
        return anInt;
    }

    public void setAnInt(int anInt) {
        this.anInt = anInt;
    }

    @Override
    public String toString() {
        return "ExampleModel{" +
                "string='" + string + '\'' +
                ", anInt=" + anInt +
                '}';
    }
}

This request works:

http://localhost:8080/cxf3example/services/example/1

catalina.out:

Feb 04, 2015 5:43:27 PM org.apache.cxf.interceptor.LoggingInInterceptor
INFO: Inbound Message
----------------------------
ID: 1
Address: http://localhost:8080/cxf3example/services/example/1
Http-Method: GET
Content-Type: 
Headers: {Accept=[text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8], accept-encoding=[gzip, deflate], accept-language=[en-US,en;q=0.5], connection=[keep-alive], Content-Type=[null], host=[localhost:8080], user-agent=[Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:34.0) Gecko/20100101 Firefox/34.0]}
--------------------------------------
Feb 04, 2015 5:43:27 PM org.apache.cxf.interceptor.LoggingOutInterceptor
INFO: Outbound Message
---------------------------
ID: 1
Response-Code: 200
Content-Type: application/json
Headers: {Content-Type=[application/json], Date=[Wed, 04 Feb 2015 22:43:27 GMT]}
Payload: {"string":"example","anInt":1001}
--------------------------------------

This request does NOT work:

http://localhost:8080/cxf3example/services/exampleService/?_wadl

catalina.out:

Feb 04, 2015 5:45:51 PM org.apache.cxf.interceptor.LoggingInInterceptor
INFO: Inbound Message
----------------------------
ID: 2
Address: http://localhost:8080/cxf3example/services/exampleService/?_wadl
Http-Method: GET
Content-Type: 
Headers: {Accept=[text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8], accept-encoding=[gzip, deflate], accept-language=[en-US,en;q=0.5], connection=[keep-alive], Content-Type=[null], host=[localhost:8080], user-agent=[Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:34.0) Gecko/20100101 Firefox/34.0]}
--------------------------------------
Feb 04, 2015 5:45:51 PM org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor processRequest
WARNING: No root resource matching request path /cxf3example/services/exampleService/ has been found, Relative Path: /exampleService/. Please enable FINE/TRACE log level for more details.
Feb 04, 2015 5:45:51 PM org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper toResponse
WARNING: javax.ws.rs.NotFoundException: HTTP 404 Not Found
    at org.apache.cxf.jaxrs.utils.SpecExceptions.toNotFoundException(SpecExceptions.java:89)
    at org.apache.cxf.jaxrs.utils.ExceptionUtils.toNotFoundException(ExceptionUtils.java:117)
    at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:167)
    at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:76)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
    at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
    at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:243)
    at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:223)
    at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:197)
    at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:149)
    at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:171)
    at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:286)
    at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doGet(AbstractHTTPServlet.java:211)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
    at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:262)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)

Feb 04, 2015 5:45:51 PM org.apache.cxf.interceptor.LoggingOutInterceptor
INFO: Outbound Message
---------------------------
ID: 2
Response-Code: 404
Content-Type: 
Headers: {Date=[Wed, 04 Feb 2015 22:45:51 GMT], Content-Length=[0]}
--------------------------------------
2

2 Answers

16
votes

I had to add to the dependencies:

<dependency>
  <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-rt-rs-service-description</artifactId>
  <version>${cxf.version}</version>
</dependency>

Sadly, it fails without giving me an exception that something is missing on the classpath.

Also, as suggested by David J. Liszewski the correct URL is:

http://localhost:8080/cxf3example/services/example?_wadl

1
votes

The service path component is declared as "/example".

Try http://localhost:8080/cxf3example/services/example?_wadl