I cannot get the swagger api listing, /api-docs.json, but I can get listings for specific resources

7,881 views
Skip to first unread message

John Duprey

unread,
May 9, 2013, 6:36:17 PM5/9/13
to swagger-sw...@googlegroups.com
Hello,

I cannot get the swagger api listing, /api-docs.json, but I can get listings for specific resources, e.g. 

404

{
    "apiVersion": "1.0", 
    "apis": {
        "description": "String transformation operations", 
        "operations": {
            "errorResponses": [
                {
                    "code": "400", 
                    "reason": "Invalid ID supplied"
                }, 
                {
                    "code": "404", 
                    "reason": "Pet not found"
                }
            ], 
            "httpMethod": "GET", 
            "nickname": "helloWorld", 
            "notes": "A first test of the service", 
            "responseClass": "string", 
            "summary": "Returns Hello World"
        }, 
        "path": "/xform.{format}helloWorld"
    }, 
    "basePath": "http://localhost:8080/rest/*", 
    "resourcePath": "/xform", 
    "swaggerVer sion": "1.1"
}

If I go to the wadl it looks like api-docs.xml is available, but that returns 404 as well:
<application xmlns="http://wadl.dev.java.net/2009/02">
<doc xmlns:jersey="http://jersey.java.net/" jersey:generatedBy="Jersey: 1.17 01/17/2013 03:31 PM"/>
<grammars>
<include href="application.wadl/xsd0.xsd">
<doc title="Generated" xml:lang="en"/>
</include>
</grammars>
<resources base="http://localhost:8080/rest/">
<resource path="/api-docs.xml">
<method id="resourceListing" name="GET">
<response>
<representation mediaType="application/xml"/>
</response>
</method>
<resource path="/{route: .+}">
<param xmlns:xs="http://www.w3.org/2001/XMLSchema" name="route" style="template" type="xs:string"/>
<method id="apiListing" name="GET">
<response>
<representation mediaType="application/xml"/>
</response>
</method>
</resource>
</resource>
<resource path="/xform">
<method id="xformGet" name="GET">
<request>
....
</rest>
</method>
</resource>
..
<resource path="/api-docs.json">
<method id="resourceListing" name="GET">
<response>
<representation mediaType="application/json"/>
</response>
</method>
<resource path="/{route: .+}">
<param xmlns:xs="http://www.w3.org/2001/XMLSchema" name="route" style="template" type="xs:string"/>
<method id="apiListing" name="GET">
<response>
<representation mediaType="application/json"/>
</response>
</method>
</resource>
</resource>


What am I doing wrong?

My web.xml:
...
<servlet>
        <servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>com.wordnik.swagger.jaxrs.listing;com.trgr.rd.sample_multimodule_project</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
            <param-value>com.trgr.rd.sample_multimodule_project.rest.util.UriExtensionsConfig</param-value>
        </init-param>
        <init-param>
            <param-name>swagger.api.basepath</param-name>
            <param-value>http://localhost:8080/rest/*</param-value>
        </init-param>
        <init-param>
            <param-name>api.version</param-name>
            <param-value>1.0</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>Jersey Web Application</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
...

Swagger maven dep:
        <dependency>
            <groupId>com.wordnik</groupId>
            <artifactId>swagger-jaxrs_2.9.1</artifactId>
            <version>1.2.1</version>
            <scope>compile</scope>
        </dependency>

My resource:
@Path("/xform")
@Api(value = "/xform", description = "String transformation operations")
public class StringTransformResource
{

..

    @GET
    @Path("helloWorld")
    @ApiOperation(value = "Returns Hello World", notes = "A first test of the service", responseClass = "java.lang.String")
    @ApiErrors(value = { @ApiError(code = 400, reason = "Invalid ID supplied"),
            @ApiError(code = 404, reason = "Pet not found") })
    @Produces(MediaType.TEXT_PLAIN)
    public String helloWorld()
    {
        return "Hello World.";
    }

...



Any help would be appreciated!

tony tam

unread,
May 9, 2013, 7:46:31 PM5/9/13
to swagger-sw...@googlegroups.com
I think your swagger.api.basepath should be this:

<param-value>http://localhost:8080/rest/</param-value>

instead of this:

<param-value>http://localhost:8080/rest/*</param-value>

(remove the *)

John Duprey

unread,
May 9, 2013, 8:08:48 PM5/9/13
to swagger-sw...@googlegroups.com
Thanks for the reply, Tony.  I've tried all manner of variants for the base path with no luck.

e.g.
 <param-value>http://localhost:8080/rest/*</param-value>
 <param-value>http://localhost:8080/rest/</param-value>
 <param-value>http://localhost:8080/rest</param-value>

In between each, change, I've done an mvn install, just to make sure everything is repackaged and available to everything else.

BTW.  On the first hit of /api-docs.json OR any other resource, I get this output:

May 09, 2013 7:54:28 PM com.sun.jersey.api.core.PackagesResourceConfig init
INFO: Scanning for root resource and provider classes in the packages:
  com.wordnik.swagger.jaxrs.listing
  com.trgr.rd.sample_multimodule_project
May 09, 2013 7:54:28 PM com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFO: Root resource classes found:
  class com.wordnik.swagger.jaxrs.listing.ApiListingResourceXML
  class com.trgr.rd.sample_multimodule_project.rest.StringTransformResource
  class com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON
May 09, 2013 7:54:28 PM com.sun.jersey.api.core.ScanningResourceConfig init
INFO: No provider classes found.
May 09, 2013 7:54:28 PM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.17 01/17/2013 03:31 PM'
May 09, 2013 7:54:31 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory manager

I'm not sure what "No provider classes found." means, but it doesn't seem to affect my resources or the api-docs.json/xform listing.

tony tam

unread,
May 9, 2013, 8:17:53 PM5/9/13
to swagger-sw...@googlegroups.com
OH, have you tried hitting http://localhost:8080/rest/api-docs.json

It looks like your GET error isn't pointed to that path, and your servlet is mounted on /rest/*

John Duprey

unread,
May 9, 2013, 10:35:48 PM5/9/13
to swagger-sw...@googlegroups.com
Gah!  That's a typo in my post.  This is the path I'm trying to GET: http://localhost:8080/rest/api-docs.json
-- 404.

tony tam

unread,
May 9, 2013, 11:52:38 PM5/9/13
to swagger-sw...@googlegroups.com
OK, that's super bizarre because the /api-docs.json and /api-docs.json/xform are generated by the exact same class:


which has this defined:


Do you have any other filters in the way?  I worked with another fellow on a similar symptom and it turned out to be a custom filter that was preventing access to that resource.

John Duprey

unread,
May 10, 2013, 12:25:28 AM5/10/13
to swagger-sw...@googlegroups.com
I do/did (CORS filter)

    <filter>
        <!-- The CORS filter with parameters -->
        <filter-name>CORS</filter-name>
        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
        <!-- Note: All parameters are options, if ommitted CORS Filter
           will fall back to the respective default values.
        -->
        <init-param>
            <param-name>cors.allowGenericHttpRequests</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>cors.allowOrigin</param-name>
            <param-value>*</param-value>
        </init-param>
        <init-param>
            <param-name>cors.supportedMethods</param-name>
            <param-value>GET, POST, HEAD, OPTIONS</param-value>
        </init-param>
        <init-param>
            <param-name>cors.supportedHeaders</param-name>
            <param-value>Content-Type, X-Requested-With, Origin, Accept</param-value>
        </init-param>
        <!--<init-param>-->
        <!--<param-name>cors.exposedHeaders</param-name>-->
        <!--<param-value>X-Test-1, X-Test-2</param-value>-->
        <!--</init-param>-->
        <init-param>
            <param-name>cors.supportsCredentials</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>cors.maxAge</param-name>
            <param-value>3600</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <!-- CORS Filter mapping -->
        <filter-name>CORS</filter-name>
        <url-pattern>*</url-pattern>
    </filter-mapping>

I removed these settings and got the same unfortunate results.

I've cloned the latest swagger-core from git and have run the sample max-rs project successfully (api-docs.json GETs).  I'll try to compare and contrast what is different - certainly the samples are using the latest snapshot of core...

tony tam

unread,
May 10, 2013, 2:44:36 PM5/10/13
to swagger-sw...@googlegroups.com
Sounds good, yes please post back the diff that you have

John Duprey

unread,
May 16, 2013, 11:24:29 PM5/16/13
to swagger-sw...@googlegroups.com
It took me a while to finally corner the problem, but this is the culprit:

In my <servlet> definition, I have:

        <init-param>
            <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
            <param-value>com.trgr.rd.sample_multimodule_project.rest.util.UriExtensionsConfig</param-value>
        </init-param>

Where UriExtensionsConfig is
/**
 *  Registers URI extensions for some common media types.  This lets clients
 *  specify the desired response format right in the URI like
 *  Accept:application/xml header.
 */
public class UriExtensionsConfig extends PackagesResourceConfig
{
...
    @Override
    public Map<String, MediaType> getMediaTypeMappings()
    {
        if (mediaTypeMap == null)
        {
            mediaTypeMap = new HashMap<String, MediaType>();
            mediaTypeMap.put("json", MediaType.APPLICATION_JSON_TYPE);
            mediaTypeMap.put("xml", MediaType.APPLICATION_XML_TYPE);
            mediaTypeMap.put("txt", MediaType.TEXT_PLAIN_TYPE);
            mediaTypeMap.put("html", MediaType.TEXT_HTML_TYPE);
            mediaTypeMap.put("xhtml", MediaType.APPLICATION_XHTML_XML_TYPE);
            MediaType jpeg = new MediaType("image", "jpeg");
            mediaTypeMap.put("jpg", jpeg);
            mediaTypeMap.put("jpeg", jpeg);
            mediaTypeMap.put("zip", new MediaType("application", "x-zip-compressed"));
        }
        return mediaTypeMap;
    }
}

I'm not sure how this is messing with swagger as api-docs.json it seems to work fine for http://localhost:8080/sample-restwebapp/rest/api-docs.xml/xform and http://localhost:8080/sample-restwebapp/rest/api-docs.json/xform work fine with the mediaTypeMap settings.

Of course if I remove the whole servlet com.sun.jersey.config.property.resourceConfigClass setting api-docs.json works.  Also if I comment out mediaTypeMap.put("json", ...) and mediaTypeMap.put("xml",  ...) it works too.  So just declaring this config does not break it.

Is this a bug (should I file an issue) or is the use of this media type extension config in error?


John Duprey

unread,
May 18, 2013, 12:09:52 AM5/18/13
to swagger-sw...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages