Jboss AS 7.1.1 no xml config: Resource listing is empty

602 views
Skip to first unread message

f.ter...@shaa.it

unread,
Oct 16, 2013, 6:08:33 AM10/16/13
to swagger-sw...@googlegroups.com
Hello,

I'm trying to use Swagger in my resteasy application (deployed on a Jboss AS 7.1.1). The application has a no xml configuration. All is based on annotations (@webfilter annotation inside the implementation of javax.servlet.Filter interface).

I followed this example with no luck: https://github.com/riteshmodi/RestEasy

Here is my web.xml file (which I added only because it's requested to configure swagger, otherwise my app doesn't have any):

<?xml version="1.0" encoding="UTF-8"?>
id="WebApp_ID" version="3.0">

<display-name>Archetype Created Restful Web Application</display-name>
<context-param>
<param-name>javax.ws.rs.core.Application</param-name>
<param-value>it.shaa.api.JaxRsActivator</param-value>
</context-param>
<context-param>
<param-name>resteasy.resources</param-name>
<param-value>com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON</param-value>
</context-param>

<!-- note! You must add the swagger providers below to correctly handle 
writing json for the swagger json -->
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>it.shaa.api.filter.JacksonJsonProvider, com.wordnik.swagger.jaxrs.listing.ApiDeclarationProvider, com.wordnik.swagger.jaxrs.listing.ResourceListingProvider</param-value>
</context-param>

<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<!--
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
-->
<servlet>
<servlet-name>DefaultJaxrsConfig</servlet-name>
<servlet-class>com.wordnik.swagger.jaxrs.config.DefaultJaxrsConfig</servlet-class>
<init-param>
<param-name>api.version</param-name>
<param-value>1.0.0</param-value>
</init-param>
<init-param>
<param-name>swagger.api.basepath</param-name>
<param-value>>/</param-value>
</init-param>
<!-- <init-param> <param-name>swagger.security.filter</param-name> <param-value>it.shaa.api.filter.ApiAuthorizationFilterImpl</param-value> 
</init-param> -->
<load-on-startup>2</load-on-startup>
</servlet>

</web-app>

As you can see I had to comment the resteasy-servlet because generates conflict with the Jboss automated scanner at startup. As consequence I have an empty resource json file (only apiVersion and swaggerVersion are shown).

What else could I attempt to get swagger working with my configuration?
Thanks for the help.

f.ter...@shaa.it

unread,
Oct 16, 2013, 6:14:55 AM10/16/13
to swagger-sw...@googlegroups.com
This is my pom.xml:

<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>it.shaa</groupId>
<artifactId>shaa</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>shaa-web-jax-rs-api</artifactId>
<packaging>war</packaging>

<name>shaa Web jax-rs api module</name>

<dependencies>

<!-- Dependency on the EJB module so we can use it's services if needed -->

<!-- Import the JAX-RS API, we use provided scope as the API is included 
in JBoss AS 7 -->
<dependency>
<groupId>org.jboss.spec.javax.ws.rs</groupId>
<artifactId>jboss-jaxrs-api_1.1_spec</artifactId>
<scope>provided</scope>
</dependency>

<!-- Import the CDI API, we use provided scope as the API is included in 
JBoss AS 7 -->
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<scope>provided</scope>
</dependency>

<!-- Import the JSF API, we use provided scope as the API is included in 
JBoss AS 7 -->
<dependency>
<groupId>org.jboss.spec.javax.faces</groupId>
<artifactId>jboss-jsf-api_2.1_spec</artifactId>
<scope>provided</scope>
</dependency>

<!-- Import the JPA API, we use provided scope as the API is included in 
JBoss AS 7 -->
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>it.shaa</groupId>
<artifactId>shaa-common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>it.shaa</groupId>
<artifactId>shaa-ejb</artifactId>
<type>ejb</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.spec.javax.transaction</groupId>
<artifactId>jboss-transaction-api_1.1_spec</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.spec.javax.servlet</groupId>
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>it.shaa</groupId>
<artifactId>shaa-common-server</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>it.shaa</groupId>
<artifactId>shaa-jpa-audit</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.spec.javax.ejb</groupId>
<artifactId>jboss-ejb-api_3.1_spec</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>it.shaa</groupId>
<artifactId>shaa-media</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>it.shaa</groupId>
<artifactId>shaa-ejb-cloudfiles</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>ejb</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>it.shaa</groupId>
<artifactId>shaa-ejb-rackspace</artifactId>
<type>ejb</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>it.shaa</groupId>
<artifactId>shaa-ejb-tika-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- swagger  -->
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-annotations_2.9.1</artifactId>
<version>1.3.0-RC2</version>
</dependency>
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-jaxrs_2.9.1</artifactId>
<version>1.3.0-RC2</version>
</dependency>
<!-- JBoss RESTEasy -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.0.4.Final</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<!-- Java EE 6 doesn't require web.xml, Maven needs to catch up! -->
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>

</project>

tony tam

unread,
Oct 16, 2013, 12:02:48 PM10/16/13
to swagger-sw...@googlegroups.com
Hi, you can easily use programmatic configuration of swagger.  In this example:


You can see how swagger is configured via spring-managed bean

f.ter...@shaa.it

unread,
Oct 22, 2013, 10:40:35 AM10/22/13
to swagger-sw...@googlegroups.com
Thanks for the suggestion Tony.

I figured out where my config was wrong. Now I'm able to get the correct json for the single API class I annotated.
But to get all this to work I had to specify this class inside my  javax.ws.rs.core.Application class (adding it to the singletons, as reported here: https://github.com/wordnik/swagger-core/blob/master/samples/java-resteasy/src/main/java/org/jboss/resteasy/examples/service/LibraryApplication.java).

But my restful application is composed by several API classes, so how can I tell swagger to scan the entire package where I have all my annotated classes?
At the moment, if I specify my apis package in the resteasy.resources param in my web.xml the application, this gives an Internal server error.

Thanks for the help.

tony tam

unread,
Oct 22, 2013, 11:32:10 AM10/22/13
to swagger-sw...@googlegroups.com
Hi, this should be easy.  You simply need to bootstrap the configurator in your application startup:

import com.wordnik.swagger.jaxrs.config.BeanConfig;

// your application startup logic
...
BeanConfig config = new BeanConfig();
config.setResourcePackage("com.your.package.to.scan");

// this metadata appears in the swagger-ui and is ALL optional
config.setTitle("your sample service");
config.setDescription("details about your service");
config.setTermsOfServiceUrl("http://terms.of.service/url");
config.setContact("sup...@your-api.com");
config.setLicense("Your license (i.e. apache 2.0");
config.setLicenseUrl("http://your-api.com/license");

// this triggers the scanning of the package specified above
config.setScan(true);

With this configuration, you don't need to specify the properties to scan in your web.xml

f.ter...@shaa.it

unread,
Oct 23, 2013, 5:43:16 AM10/23/13
to swagger-sw...@googlegroups.com
Thanks Tony,

before I start to follow you BeanConfig suggestion, I want to report a mafunction when I try to add an API class as singleton as reported above. If i follow this kind of configuration, all the @inject inside my api classes stop working (so I break all my APIs functionality, because I make an extensive use of @inject). I have a standard Jboss AS 7.1.1 configuration, without a web.xml.
I post here my current web.xml used to configure swagger:

<?xml version="1.0" encoding="UTF-8"?>
id="WebApp_ID" version="3.0">

<display-name>Archetype Created Restful Web Application</display-name>

<context-param>
<param-name>javax.ws.rs.core.Application</param-name>
<param-value>it.shaa.api.JaxRsActivator</param-value>
</context-param>

<context-param>
   <param-name>resteasy.scan</param-name>
   <param-value>true</param-value>
</context-param>

<context-param>
<param-name>resteasy.resources</param-name>
<param-value>com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON</param-value>
</context-param>

<!-- note! You must add the swagger providers below to correctly handle 
writing json for the swagger json -->
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>it.shaa.api.filter.JacksonJsonProvider, com.wordnik.swagger.jaxrs.listing.ApiDeclarationProvider, com.wordnik.swagger.jaxrs.listing.ResourceListingProvider</param-value>
</context-param>

<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>

<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>DefaultJaxrsConfig</servlet-name>
<servlet-class>com.wordnik.swagger.jaxrs.config.DefaultJaxrsConfig</servlet-class>
<init-param>
<param-name>api.version</param-name>
<param-value>/v2.0/00001</param-value>
</init-param>
<init-param>
<param-name>swagger.api.basepath</param-name>
<param-value>http://local.api.shaa.it:8080/v2.0/00001/</param-value>
</init-param>
<!-- <init-param> 
<param-name>swagger.security.filter</param-name> 
<param-value>it.shaa.api.filter.ApiAuthorizationFilterImpl</param-value> 
 </init-param> -->
<load-on-startup>2</load-on-startup>
</servlet>

</web-app>

And this is my javax.ws.rs.core.Application class:

package it.shaa.api;

import java.util.HashSet;
import java.util.Set;

import it.shaa.api.content.AccessProfileAPI;
import it.shaa.common.HeaderParameter;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

/**
 * A class extending {@link Application} and annotated with @ApplicationPath is
 * the Java EE 6 "no XML" approach to activating JAX-RS.
 * 
 * <p>
 * Resources are served relative to the servlet path specified in the
 * {@link ApplicationPath} annotation.
 * </p>
 */
@ApplicationPath(HeaderParameter.API_VERSION)
public class JaxRsActivator extends Application {

HashSet<Object> singletons = new HashSet<Object>();

public JaxRsActivator() {
singletons.add(new AccessProfileAPI());
}
@Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> set = new HashSet<Class<?>>();
return set;
}
@Override
public Set<Object> getSingletons() {
return singletons;
}
}

If I add any class to the singletons (above I added the only swaggerannotated class I have at the moment) I break all my APIs functionaity because the @inject inside my API class breaks.

Speaking of the BeanConfig approach: The only point where I could try to put the configuration is inside my javax.serlvet.Filter implementation class (annotated with @WebFilter), but I need to test it.
Otherwise I don't know how to access my application startup logic inside this kind of Jboss configuration.

I appreciate your help.
Thank you so much.

tony tam

unread,
Oct 23, 2013, 11:34:13 AM10/23/13
to swagger-sw...@googlegroups.com

Hi, I'm not as familiar with RestEasy as I should be, but I can suggest the following:

* Please try removing the DefaultJaxrsConfig servlet and ensure your service still starts up OK.  If so we know that the providers are not causing trouble.

* If it succeeds to start (and I expect it will), you can simply create a bootstrap servlet and configure the BeanConfig object as such:

https://github.com/wordnik/swagger-core/blob/develop/samples/java-jaxrs/src/main/webapp/WEB-INF/web.xml#L54

  <servlet>
    <servlet-name>Bootstrap</servlet-name>
    <servlet-class>com.wordnik.swagger.sample.Bootstrap</servlet-class>
    <load-on-startup>2</load-on-startup>
  </servlet>

And in the "Bootstrap.java" class you can configure your BeanConfig in a static block

That should avoid your injection issues

f.ter...@shaa.it

unread,
Oct 25, 2013, 4:31:37 AM10/25/13
to swagger-sw...@googlegroups.com
Hi,

I tried what you suggested, step by step, the exception is gone, but I still have an empty json when I call the api-docs service.

Now I have this web.xml:


<?xml version="1.0" encoding="UTF-8"?>
id="WebApp_ID" version="3.0">

<display-name>Archetype Created Restful Web Application</display-name>
<!-- 
<context-param> 
<param-name>javax.ws.rs.core.Application</param-name> 
<param-value>it.shaa.api.JaxRsActivator</param-value> 
</context-param> 
-->
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param>

<context-param>
<param-name>resteasy.resources</param-name>
<param-value>com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON</param-value>
</context-param>

<!-- note! You must add the swagger providers below to correctly handle 
 writing json for the swagger json -->
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>it.shaa.api.filter.JacksonJsonProvider, com.wordnik.swagger.jaxrs.listing.ApiDeclarationProvider, com.wordnik.swagger.jaxrs.listing.ResourceListingProvider</param-value>
</context-param>

<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>

<servlet>
<servlet-name>Bootstrap</servlet-name>
<servlet-class>it.shaa.api.Bootstrap</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>

<!-- 
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>DefaultJaxrsConfig</servlet-name>
<servlet-class>com.wordnik.swagger.jaxrs.config.DefaultJaxrsConfig</servlet-class>
<init-param>
<param-name>api.version</param-name>
<param-value>/v2.0/00001</param-value>
</init-param>
<init-param>
<param-name>swagger.api.basepath</param-name>
<param-value>http://local.api.shaa.it:8080/v2.0/00001/</param-value>
</init-param>
<init-param>
<param-name>swagger.security.filter</param-name>
<param-value>it.shaa.api.filter.ApiAuthorizationFilterImpl</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
-->
</web-app>


And this is the Bootstrap servlet:

package it.shaa.api;

import com.wordnik.swagger.jaxrs.config.BeanConfig;
import com.wordnik.swagger.model.*;
import com.wordnik.swagger.config.*;
//import com.wordnik.swagger.sample.util.*;
//import com.wordnik.swagger.config.FilterFactory;

import javax.servlet.http.HttpServlet;

import java.util.List;
import java.util.ArrayList;

public class Bootstrap extends HttpServlet {

static {
    // do any additional initialization here, such as set your base path programmatically as such:
    // ConfigFactory.config().setBasePath("http://www.foo.com/");
    // add a custom filter
    //FilterFactory.setFilter(new CustomFilter());
    
    
    BeanConfig config = new BeanConfig();
    config.setResourcePackage("it.shaa.api"); //here I have other subpackages that have to be scanned
    // this triggers the scanning of the package specified above
    config.setScan(true);
    
}
  
}


Thanks for the help 

tony tam

unread,
Oct 25, 2013, 11:31:09 AM10/25/13
to swagger-sw...@googlegroups.com
I think we need to increase logging to see what's going on.  My guess is the api-docs resource is being mounted, but perhaps somewhere that you don't expect.

Logging depends on how your app is set up--in our resteasy sample, it's done in log4j.properties:


Can you crank that up, and post back the output of com.wordnik.swagger.* log entries?  


On Wednesday, October 16, 2013 3:08:33 AM UTC-7, f.ter...@shaa.it wrote:
Reply all
Reply to author
Forward
0 new messages