UPDATED with SOLUTION below!!!
//////////////////////////////////////////////////////////////
Thanks to the advice of Ron below I slightly modified my setup to use BeanConfig instead of SwaggerConfig and got this working. In order to do this I had to modify the servlet and also (and this is where I believe the missing piece was) add the BeanConfig entry into the spring application context file so that spring picks up the resources. I included the updates below with comments in my code showing the old and new/updated code. It's possible I could've continued with the SwaggerConfig (maybe I was just missing something in the spring application context file for that as well?) but the BeanConfig works so I'm going to leave it as is.
//////////////////////////////////////////////////////////////
I'm trying to get Swagger running with my local REST-based Java App and have made quite a bit of progress. However, I seem to be missing something easy when I'm trying to get the Swagger UI working.
Whenever I actually hit this address: http://localhost:9082/mbl/index.html I'm getting the little green swagger header at the top but a blank white body with no content underneath. Shouldn't I be seeing more than this in the body of the page?
My stack is this: Java 6 / Wink / Spring 3.1 / Jackson 2.5 / JAX-RS (JSR-311) and I'm using the following Swagger jars: swagger-annotations-1.3.10.jar / swagger-core_2.10-1.3.10.jar / swagger-jaxrs_2.10-1.3.10.jar.
Now I've managed to get some json displaying that looks like this when i hit http://localhost:9082/mbl/services/api-docs:
{"apiVersion":"1.0","swaggerVersion":"1.2","info":{"title":"Java API","description":"The following documentation contains the REST Service API useful for interacting with web services.","termsOfServiceUrl":"terms of service","contact":"[email protected]","license":"license type","licenseUrl":"license url"}}
I can see that this is being generated from my SwaggerServlet.java which looks like this:
package com.somewhere.mblsvc.web;
import...
public class SwaggerServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/* additional working code */
BeanConfig beanConfig;
public void setBeanConfig(BeanConfig beanConfig) {
this.beanConfig = beanConfig;
}
/* end additional working code */
@Override
public void init(ServletConfig servletConfig) {
try {
/* code from original post*/
// SwaggerConfig swaggerConfig = new SwaggerConfig();
// ConfigFactory.setConfig(swaggerConfig);
// swaggerConfig.setBasePath("/mbl/services");
// swaggerConfig.setApiVersion("1.0");
// swaggerConfig.setApiInfo(new ApiInfo("Java API", "The following //documentation contains the REST Service API useful for interacting with web //services.", "terms of service", "[email protected]", "license type", "license //url"));
// ScannerFactory.setScanner(new DefaultJaxrsScanner());
// ClassReaders.setReader(new DefaultJaxrsApiReader());
/* end code from original post*/
/* updated working code */
beanConfig.setBasePath("/mbl/x-services");
beanConfig.setVersion("1.0");
beanConfig.setResourcePackage("com.somewhere.mblsvc.resources");
beanConfig.setScan(true);
/* end updated working code */
} catch (Exception e) {
e.printStackTrace();
}
}
}
Also, I have the following in my spring application context xml file:
<bean class="org.apache.wink.spring.Registrar">
<property name="classes">
<set value-type="java.lang.Class">
</set>
</property>
<property name="instances">
<set>
<ref local="jaxbProvider" />
<ref local="apiDeclarationProvider" />
<ref local="apiListingResourceJson" />
<ref local="resourceListingProvider" />
</set>
</property>
<!-- Jackson Providers -->
<bean id="jaxbProvider" class="com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider" >
<property name="mapper" ref="jacksonObjectMapper"/>
</bean>
<bean id="jacksonObjectMapper" class="com.fasterxml.jackson.databind.ObjectMapper" >
<property name="annotationIntrospector" ref="jacksonAnnotationIntrospector" />
</bean>
<bean id="jacksonAnnotationIntrospector" class="com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair" >
<constructor-arg ref="primaryAnnotationIntrospector" />
<constructor-arg ref="secondaryAnnotationIntrospector" />
</bean>
<bean id="primaryAnnotationIntrospector" class="com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector" />
<bean id="secondaryAnnotationIntrospector" class="com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector" />
<!-- Swagger Configuration and Providers -->
<!-- additional working code -->
<bean id="beanConfig" class="com.wordnik.swagger.jaxrs.config.BeanConfig">
<property name="title" value="Java API"/>
<property name="version" value="1.0" />
<property name="basePath" value="/mbl/services"/>
<property name="resourcePackage" value="com.somewhere.mblsvc.resources"/>
<property name="scan" value="true"/>
</bean>
<!-- end additional working code -->
<bean id="apiDeclarationProvider" class="com.wordnik.swagger.jaxrs.listing.ApiDeclarationProvider" />
<bean id="apiListingResourceJson" class="com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON" />
<bean id="resourceListingProvider" class="com.wordnik.swagger.jaxrs.listing.ResourceListingProvider" />
My web.xml looks like this:
<!-- REST servlet that dispatches to the App (resource class). Remove Init params entry containing application file -->
<servlet>
<servlet-name>Wink Servlet</servlet-name>
<servlet-class>org.apache.wink.server.internal.servlet.RestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Wink Servlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<!-- Enabling Swagger servlet -->
<servlet>
<servlet-name>Swagger Servlet</servlet-name>
<servlet-class>com.somewhere.mblsvc.web.SwaggerServlet</servlet-class>
<load-on-startup>-1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Swagger Servlet</servlet-name>
<url-pattern>/api-docs</url-pattern>
</servlet-mapping>
Here's a snippet of my Resource class:
@Path("test")
@Api(value ="test", description="Test Services")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public class TestResource {
.
.
.
@GET
@Path("testInfo")
@ApiParam(defaultValue="you would put test case input here for a post")
@ApiOperation(value="Composite service returning extensive test information", response=com.somewhere.mblsvc.messages.test.testinfo.pojo.UserResponseMessage.class)
@ApiResponses(value={
@ApiResponse(code=200, message="OK"),
@ApiResponse(code=500, message="Internal Error")
})
@JsonSerialize(include=JsonSerialize.Inclusion.ALWAYS)
public Response getTestInfo(@Context HttpHeaders headers,
@CookieParam(value = "testBrand") String testBrand) {
.
.
.
And, finally, the only important part of my index.html (that I can tell) looks like this:
<script type="text/javascript">
$(function () {
var url = window.location.search.match(/url=([^&]+)/);
if (url && url.length > 1) {
url = url[1];
} else {
url = "http://" + window.location.hostname + (window.location.port ? ':'+ window.location.port: '') + "/mbl/services/api-docs";
}
.
.
.
I will gladly supply any more information as needed. Does anyone have any idea what I might be missing?
Thanks a lot!
The core problem is that your resources are not really scanned. You do get the right now is the basic Swagger response, but if you look at the content, it has no API definitions in it.
As a result, swagger-ui is unable to show anything, because there's nothing to show.
While I'm curious as to how you got to the configuration above, the truth is that the integration can be simpler. We don't have specific documentation for Wink (we should), but the idea is very similar to any of the JAX-RS integrations.
I'd recommend the following steps:
I realize this doesn't solve the question at-hand exactly, but I'd rather promote the right overall solution in this case.