Spring MVC and Swagger. Generating documentation for your RESTful web services - PART 1

Automating your RESTful web services documentation Using Spring MVC with Swagger for generating it


Part 1 - Setting up the WAR and spring configuration


1.- Introduction


Through this simple tutorial I will be developing a simple web application using the following technologies :

The main goal of this tutorial is to illustrate how the swagger documentation framework can be integrated into a spring mvc application.

2.- The Database Model

In this tutorial we will be using a very simple model consisting of 1 table :


3.- Creating the maven project structure

There are a few of Spring archetypes when creating java web applications but I find them oversized for this simple tutorial so I will use here the org.codehaus.mojo.archetypes.webapp-javaee6 archetype :


archetype generation
1
mvn archetype:generate -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=webapp-javaee6 -DpackageName=com.ufasoli.tutorial.swagger.springmvc -DgroupId=com.ufasoli.tutorial -DartifactId=swagger-spring-mvc -Dversion=1.0

This should generate a pretty standard maven WAR project structure

Note : You should adapt your groupId and artifactId according to your config.

4.- Dependencies

In your pom.xml file add the following dependencies that we are going to need for our project :

pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
...
 <properties>
        <endorsed.dir>${project.build.directory}<endorsed.dir>
        <project.build.sourceencoding>UTF-8</project.build.sourceencoding>
        <version.spring>3.2.1.RELEASE</version.spring>
        <version.hsqldb>1.8.0.10</version.hsqldb>
    </endorsed.dir></endorsed.dir></properties>
 
    <dependencies>
        <dependency>
            <groupid>javax</groupid>
            <artifactid>javaee-web-api</artifactid>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
 
        <dependency>
            <groupid>com.mangofactory</groupid>
            <artifactid>swagger-springmvc</artifactid>
            <version>0.5.2</version>
        </dependency>
 
        <dependency>
            <groupid>org.springframework</groupid>
            <artifactid>spring-core</artifactid>
            <version>${version.spring}</version>
        </dependency>
 
        <dependency>
            <groupid>org.springframework</groupid>
            <artifactid>spring-jdbc</artifactid>
            <version>${version.spring}</version>
        </dependency>
        <dependency>
            <groupid>org.springframework</groupid>
            <artifactid>spring-expression</artifactid>
            <version>${version.spring}</version>
        </dependency>
        <dependency>
            <groupid>org.springframework</groupid>
            <artifactid>spring-web</artifactid>
            <version>${version.spring}</version>
        </dependency>
        <dependency>
            <groupid>org.springframework</groupid>
            <artifactid>spring-webmvc</artifactid>
            <version>${version.spring}</version>
        </dependency>
 
        <dependency>
            <groupid>org.springframework</groupid>
            <artifactid>spring-beans</artifactid>
            <version>${version.spring}</version>
        </dependency>
        <dependency>
            <groupid>org.hsqldb</groupid>
            <artifactid>hsqldb</artifactid>
            <version>${version.hsqldb}</version>
        </dependency>
 
    </dependencies>
 
...

5.- Spring Configuration

There are many schools when it comes to creating spring context files
I usually create a spring-web.xml file under the src/main/webapp/WEB-INF folder that I will use as my web application context and an applicationContext.xml file under src/main/resources/META-INF/spring that will be my application context.

5.1.- Configuring the Application Context (applicationContext.xml)
5.1.1- Setting up the classpath scanner
1
2
3
4
 <!-- Where to scan for spring components available in the application context-->
    <context:component-scan base-package="com.ufasoli.tutorial.swagger.springmvc.core">
 
</context:component-scan>
5.1.2- Setting up the database

Spring has a pretty nifty way to step up an in-memory database.You can provide a list of SQL scripts that will be executed when the database is started

I have written 2 SQL scripts one for creating the database and another one to have some sample data inserted in the database

This scripts can be found under src/main/resources/sql :

schema.sql
1
CREATE TABLE BOOKS (id VARCHAR NOT NULL, title VARCHAR NOT NULL, author VARCHAR NOT NULL, publicationYear INTEGER, comment VARCHAR, PRIMARY KEY(id))
data.sql
1
2
3
4
5
6
7
INSERT INTO BOOKS VALUES ('1', 'A Game of Thrones', 'George R. R. Martin', 1996, 'n.c.');
INSERT INTO BOOKS VALUES ('2', 'A Clash of Kings', 'George R. R. Martin', 1998, 'n.c.');
INSERT INTO BOOKS VALUES ('3', 'A Storm of Swords', 'George R. R. Martin', 2000, 'n.c.');
INSERT INTO BOOKS VALUES ('4', 'A Feast for Crows ', 'George R. R. Martin', 2005, 'n.c.');
INSERT INTO BOOKS VALUES ('5', 'A Dance with Dragons', 'George R. R. Martin', 2011, 'It was about time!');
INSERT INTO BOOKS VALUES ('6', 'The Winds of Winter', 'George R. R. Martin', 2014, 'If we are lucky!');
INSERT INTO BOOKS VALUES ('7', 'A Dream of Spring', 'George R. R. Martin', 2100, 'oh c`mon');

We will now configure the applicationContext.xml file using a HSQL in-memory database and instruct spring to execute the SQL scripts in a predefined order as well as bootstrap Spring's JDBC template class which is an utility class that simplifies the use of JDBC

Below is how the applicationContext.xml file should look like :

applicationContext.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!--xml version="1.0" encoding="UTF-8"?-->
 
    <!-- Where to scan for spring components available in the application context-->
    <context:component-scan base-package="com.ufasoli.tutorial.swagger.springmvc.core">
 
    <!-- Create an in-memory data source-->
    <jdbc:embedded-database id="dataSource" type="HSQL">
         <!-- run the following scripts when bootstrapping the context-->
        <jdbc:script location="classpath:sql/schema.sql">
        <jdbc:script location="classpath:sql/data.sql">
    </jdbc:script></jdbc:script></jdbc:embedded-database>
 
    <!-- create a JDBC template bean that will use the in-memory datasource-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource">
    </property></bean>
</context:component-scan></beans>

With this configuration every time the application is started the database will be bootstraped and some sample data will be inserted

5.2.- Configuring the Web Application Context (spring-web.xml)

The Web Application context extended Application Context which is designed for work with the standard javax.servlet.ServletContext so it's able to communicate with the container.

5.2.1- Setting up the classpath scanner & the Spring MVC configuration

I will not go into the details of Spring but to sumarize the classpath scanner for the web application context will essentially pick up the controllers and register them in the context whereas the Spring MVC configuration will define how controllers should by discovered and how URLs should be handled

spring-web.xml
1
2
3
4
5
6
7
8
9
10
11
<!--xml version="1.0" encoding="UTF-8"?-->
      
<!-- Where to scan for web components (@Controller)-->
    <context:component-scan base-package="com.ufasoli.tutorial.swagger.springmvc.web.services">
    <!-- Use annotations to discover web components-->
    <mvc:annotation-driven>
    <!-- forward all requests to the default Servlet (see http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/mvc.html) -->
    <mvc:default-servlet-handler>
     
</mvc:default-servlet-handler></mvc:annotation-driven></context:component-scan></beans>
5.3.- Configuring the web.xml descriptor

It's now time to tell our web app to use spring-mvc. For this to happen we need to edit the web.xml file under src/main/webapp/WEB-INF and add the spring configuration :

web.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
         http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" metadata-complete="true">
      
<!-- Title for the web application-->
    <display-name>Spring MVC Swagger integration</display-name>
 
      <!-- Default file when none is indicated in the URL-->
        <welcome-file-list>
            <welcome-file>index.html</welcome-file>
        </welcome-file-list>
 
    <!-- Where to find the spring application context file-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/META-INF/spring/applicationContext.xml</param-value>
    </context-param>
 
    <!-- Spring utility class that will load the application context-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
 
    <!-- Spring MVC "Main Controller" dispatcher-->
    <servlet>
        <servlet-name>spring-servlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- Where to load the web application context-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-web.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
 
    <!-- What to map to the spring-servlet -->
    <servlet-mapping>
        <servlet-name>spring-servlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
 
</web-app>

6.- Taking it for a spin

If everything goes according to plan we should be able to take our application for a spin with a simple hello world!

6.1.- Creating the HelloWorld Controller

Create a HelloWorldService.java file under src/main/java/ and the package of your choice

HelloWorldController.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.ufasoli.tutorial.swagger.springmvc.web.services;
 
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
 
@Controller
@RequestMapping(value = "/hello", produces = MediaType.TEXT_PLAIN_VALUE)
public class HelloWorldService {
 
    @RequestMapping( produces = MediaType.TEXT_PLAIN_VALUE, method = RequestMethod.GET)
    public @ResponseBody String sayHelloWorld(HttpServletResponse response){
 
        return "Hello World!";
    }
}

With this configuration spring will register your hello-world controller under :

1
${context.root}/hello
6.2.- Configuring jetty and running the app

We are almost there, the last thing we need to do is to configure our embedded Jetty server

Head to your pom.xml file

pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
 
<build>
  <plugins>
    ...
    <plugin>
      <groupid>org.mortbay.jetty</groupid>
      <artifactid>maven-jetty-plugin</artifactid>
      <version>6.1.26</version>
      <configuration>
        <webappconfig>
          <contextpath>/spring-mvc-swagger-tutorial</contextpath>
        </webappconfig>
        <scanintervalseconds>0</scanintervalseconds>
        <connectors>
          <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
             <port>9090</port>
             <maxidletime>60000</maxidletime>
           </connector>
          </connectors>
       </configuration>
     </plugin>
     ...
</plugins>
 
...
 
</build>

This configuration will start a jetty server under the port 9090 and deploy my application under the /spring-mvc-swagger-tutorial context-root

6.3.- Running the app

Head to your command line or favorite IDE and run the following maven goal

1
mvn jetty:run

Wait for your server to start, you should see a message similar to:

1
2
3
4
5
6
7
8
9
10
...
  2013-06-06 15:23:50.668:INFO::jetty-6.1.26
2013-06-06 15:23:50.825:INFO::No Transaction manager found - if your webapp requires one, please configure one.
2013-06-06 15:23:51.135:INFO:/spring-mvc-swagger-tutorial:Initializing Spring root WebApplicationContext
log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
2013-06-06 15:23:51.957:INFO:/spring-mvc-swagger-tutorial:Initializing Spring FrameworkServlet 'spring-servlet'
2013-06-06 15:23:53.511:INFO::Started SelectChannelConnector@0.0.0.0:9090
[INFO] Started Jetty Server

Now crack open your favorite browser and head to :

And if the programming Gods are good you should get your well deserved greeting

6.- Wrapping-up part 1

So that's it for part 1 of the tutorial. On the second part we will create a more complex controller and see how to integrate the Swagger framework into our project

You can find this sample application over at github :

Swagger - Spring MVC tutorial sample application code

1 comment:

OSX show used ports or listening applications with their PID

On OSX you can display applications listening on a given port using the lsof the commands described below will show listening application...