1
votes

I'm trying to generate REST documentation using swagger with cxf and camel. I've succeed to get swagger documentation. And I have swagger-ui working correctly !

So now i'm trying to export everything and build an offline documentation. In order to do that I use : 1) swagger-maven-plugin : REST -> json 2) swagger2markup-maven-plugin : json -> asciidoc

I managed to get a json file but it doesn't contain my api documentation..

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>net.jeffsbox</groupId>
    <artifactId>jaxrs-cxf-camel-spring-example</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>

    <name>jaxrs-cxf-camel-spring-example</name>

    <description>
        An example demonstrating how to use create a REST web service using
        a gazillion wrappers (JAX-RS, CXF, Camel and Spring).
    </description>

    <properties>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
        <camel.version>2.17.1</camel.version>
        <spring.version>4.2.6.RELEASE</spring.version>
        <swagger-ui-version>2.1.0</swagger-ui-version>
        <jackson.version>1.9.0</jackson.version>
        <swagger.version>1.5.0</swagger.version>
        <cxf-rt.version>3.2.0-SNAPSHOT</cxf-rt.version>
        <cors-filter.version>2.1</cors-filter.version>
        <enunciate.version>2.5.0</enunciate.version>
        <swagger2markup.version>1.0.0</swagger2markup.version>
        <generated.asciidoc.directory>/asciidoc</generated.asciidoc.directory>
        <phase.generate-documentation>compile</phase.generate-documentation>
    </properties>

    <repositories>
        <repository>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <id>jcenter-releases</id>
            <name>jcenter</name>
            <url>http://jcenter.bintray.com</url>
        </repository>
    </repositories>

    <dependencies>

        <dependency>
            <groupId>io.github.swagger2markup</groupId>
            <artifactId>swagger2markup</artifactId>
            <version>${swagger2markup.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-core</artifactId>
            <version>${camel.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-spring</artifactId>
            <version>${camel.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-cxf</artifactId>
            <version>${camel.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-jaxrs</artifactId>
            <version>${jackson.version}</version>
        </dependency>

        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-jaxrs</artifactId>
            <version>${swagger.version}</version>
            <exclusions>
                <exclusion>
                     <groupId>javax.ws.rs</groupId>
                     <artifactId>jsr311-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>${cxf-rt.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
            <version>${cxf-rt.version}</version>
        </dependency>

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

        <dependency>
            <groupId>com.thetransactioncompany</groupId>
            <artifactId>cors-filter</artifactId>
            <version>${cors-filter.version}</version>
        </dependency>

        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>swagger-ui</artifactId>
            <version>2.1.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.9</version>
                <executions>
                    <execution>
                        <phase>generate-resources</phase>
                        <goals>
                            <goal>unpack</goal>
                        </goals>
                        <configuration>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>org.webjars</groupId>
                                    <artifactId>swagger-ui</artifactId>
                                    <version>${swagger-ui-version}</version>
                                    <overWrite>true</overWrite>
                                    <outputDirectory>${project.build.directory}/swagger-ui</outputDirectory>
                                    <excludes>**/*.gz</excludes>                                    
                                </artifactItem>                                
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                        <id>copy-resources</id>
                        <phase>generate-resources</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.build.directory}/${project.artifactId}-${project.version}</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>${project.build.directory}/swagger-ui/META-INF/resources/webjars/swagger-ui/${swagger-ui-version}</directory>
                                    <filtering>true</filtering>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
<!--             <plugin> -->
<!--            <groupId>com.webcohesion.enunciate</groupId> -->
<!--            <artifactId>enunciate-maven-plugin</artifactId> -->
<!--            <version>${enunciate.version}</version> -->
<!--            <executions> -->
<!--               <execution> -->
<!--                      <goals> -->
<!--                        <goal>docs</goal> -->
<!--                      </goals> -->
<!--                      <configuration> -->
<!--                        <configFile>enunciate.xml</configFile> -->
<!--                        <docsDir>${project.build.directory}</docsDir> -->
<!--                      </configuration> -->
<!--               </execution> -->
<!--            </executions> -->
<!--            </plugin> -->
            <plugin>
                <groupId>com.github.kongchen</groupId>
                <artifactId>swagger-maven-plugin</artifactId>
                <version>3.1.3</version>
                <configuration>
                    <apiSources>
                        <apiSource>
                            <springmvc>false</springmvc>
                            <locations>net.jeffsbox.beans</locations>
                            <basePath>/api</basePath>
                            <info>
                                <title>DocId</title>
                                <description>documentation of DocId webservice</description>
                                <version>v1</version>
                            </info>
                            <swaggerDirectory>${project.build.directory}/api</swaggerDirectory>
                            <attachSwaggerArtifact>true</attachSwaggerArtifact>
                        </apiSource>
                    </apiSources>
                </configuration>
                <executions>
                    <execution>
                        <phase>${phase.generate-documentation}</phase>
                        <!-- fx process-classes phase -->
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>io.github.robwin</groupId>
                <artifactId>swagger2markup-maven-plugin</artifactId>
                <version>0.9.3</version>
                <configuration>
                    <inputDirectory>${project.build.directory}/api</inputDirectory>
                    <outputDirectory>${project.build.directory}/${generated.asciidoc.directory}</outputDirectory>
<!--                    specify location to place asciidoc files -->
                    <markupLanguage>asciidoc</markupLanguage>
                </configuration>
                <executions>
                    <execution>
                        <phase>${phase.generate-documentation}</phase>
                        <goals>
                            <goal>process-swagger</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <warSourceDirectory>${project.build.directory}/${project.artifactId}-${project.version}</warSourceDirectory>
                    <port>8080</port>
                    <path>/</path>
                </configuration>
                <executions>
                    <execution>
                        <id>run-tomcat</id>
                        <configuration>
                            <fork>true</fork>
                        </configuration>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Web.xml

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>Example REST Service</display-name>

    <!-- location of spring xml files -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/applicationContext.xml</param-value>
    </context-param>

    <!-- the listener that kick-starts Spring -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- CXF servlet -->
    <servlet>
        <servlet-name>CXFServlet</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <!-- If you want to leverage the Servlet3's async feature in Tomcat, please enable this feature -->
<!--        <async-supported>true</async-supported> -->
    </servlet>

    <!-- all our webservices are mapped under this URI pattern -->
    <servlet-mapping>
        <servlet-name>CXFServlet</servlet-name>
        <url-pattern>/ws/*</url-pattern>
    </servlet-mapping>

    <filter>
    <filter-name>CORS</filter-name>
    <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>

    <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.allowSubdomains</param-name>
        <param-value>false</param-value>
    </init-param>

    <init-param>
        <param-name>cors.supportedMethods</param-name>
        <param-value>GET, HEAD, POST, DELETE, OPTIONS</param-value>
    </init-param>

    <init-param>
        <param-name>cors.supportedHeaders</param-name>
        <param-value>*</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>

    <filter>
        <filter-name>ApiOriginFilter</filter-name>
        <filter-class>com.github.kongchen.swagger.sample.wordnik.util.ApiOriginFilter</filter-class>
      </filter>
    <filter-mapping>
        <filter-name>ApiOriginFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
</web-app>

application.context

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

    <import resource="classpath:META-INF/cxf/cxf.xml" />
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

    <!-- REST resources -->
    <bean id="docidService" class="net.jeffsbox.services.DocIDService" />
    <bean id="identityService" class="net.jeffsbox.services.IdentityService" />

    <!-- Camel beans definitions -->
    <bean id="monitorBean" class="net.jeffsbox.beans.MonitorBean" />
    <bean id="identityBean" class="net.jeffsbox.beans.IdentityBean" />
    <bean id="unimplementedHTTPError" class="net.jeffsbox.beans.RESTErrorBean">
        <property name="statusCode" value="501" />
        <property name="message" value="Resource not implemented" />
    </bean>

    <!-- JAXRS providers -->
    <bean id="jsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />

    <bean id="swagger2Feature" class="org.apache.cxf.jaxrs.swagger.Swagger2Feature">
        <!-- customize some of the properties -->
        <property name="basePath" value="/api"/>
        <property name="resourcePackage" value="net.jeffsbox.services"/>
        <property name="version" value="1.0.0"/>
        <property name="host" value="localhost:8080"/>
        <property name="title" value="Swagger DocId"/>
        <property name="description" value="This is a app."/>
        <property name="contact" value="[email protected]"/>
        <property name="license" value="Apache 2.0"/>
        <property name="licenseUrl" value="http://www.apache.org/licenses/LICENSE-2.0.html"/>
        <property name="scan" value="true"/>
    </bean>

    <!-- Tell CXF/JAX-RS where the REST service is defined -->
    <!-- Specifying the address as '/' or '/something' makes sure it uses the containing app server. In certain configurations, 
        not including address causes Camel to start a Jetty instance which hosts the REST service. This can cause conflicts in dependencies. -->
    <jaxrs:server id="jaxRsServer" address="/jaxrs">
        <jaxrs:serviceBeans>
            <ref bean="docidService" />
            <ref bean="identityService" />
        </jaxrs:serviceBeans>
        <jaxrs:providers>
            <ref bean="jsonProvider" />
        </jaxrs:providers>
        <jaxrs:features>
            <ref bean="swagger2Feature" />
        </jaxrs:features>
    </jaxrs:server>

      <cxf:rsServer id="rsServer" address="/rest">
        <cxf:serviceBeans> 
         <ref bean="docidService" />
         <ref bean="identityService" /> 
        </cxf:serviceBeans>
        <cxf:providers>
           <ref bean="jsonProvider"/>
        </cxf:providers>
      </cxf:rsServer>

    <!-- Camel routes definitions -->
    <camelContext trace="true" xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="cxfrs://bean://rsServer" />
            <to uri="log:body?level=INFO" />
            <choice>
                <when>
                    <simple>${in.header.camelhttppath} == '/monitor/ping'</simple>
                    <to uri="direct:ping" />
                </when>
                <when>
                    <simple>${in.header.camelhttppath} == '/identity/get'</simple>
                    <to uri="direct:getIdentity" />
                </when>
                <when>
                    <simple>${in.header.camelhttppath} == '/identity/post'</simple>
                    <to uri="direct:notImplemented" />
                </when>
                <otherwise>
                    <to uri="direct:notImplemented" />
                </otherwise>
            </choice>
        </route>
        <route>
            <from uri="direct:ping" />
            <to uri="bean:monitorBean?method=processPing" />
        </route>
        <route>
            <from uri="direct:getIdentity" />
            <to uri="bean:identityBean?method=processGet" />
        </route>
        <route>
            <from uri="direct:notImplemented" />
            <to uri="bean:unimplementedHTTPError?method=fill" />
        </route>
    </camelContext>
</beans>

I can access te swagger-ui documentation at : http://localhost:8080/?url=http://localhost:8080/ws/jaxrs/swagger.json This documentation contains everything !!

1

1 Answers

1
votes

Just a basic error in the swagger-maven-plugin.. The attribute 'location' has to point on your services...