Swagger-based REST API definitions allow services to be easily understood by consumers in a language-neutral way. Use WebSphere Developer Tools to create, edit and deploy your REST API for discovery on the Liberty runtime.

Writing up a Swagger REST API document can be an error-prone task. Whether you’re building a file from the ground up or trying to edit a large document, there can be a lot of trial and error in the process just to ensure your syntax is valid and is aligned with the specification. If your main objective is to build an application without having to deal with the small stuff, then the good news is, starting in WDT 8.5.5.9, there are tools to help you create, edit and validate your REST API docs. You can also use these tools to build POJO or JAX-RS servlets to test out your REST API on Liberty.

To highlight some of the tooling capabilities, we will go through the steps to build a simple, top-down, REST API application, an online bookstore.

Creating and editing a Swagger-based REST API document

Before we begin, ensure that Liberty 8.5.5.9 server is installed.

First, we need to create a Web project to generate a new Swagger REST API doc:

  1. Create a new Web 3.1 project called Bookstore and target it to the Liberty runtime.
  2. To generate a swagger.json file, select the Bookstore project and right-click New > Swagger REST API Definition file. In the dialog that opens, select the type of file that you want to generate.

    For this application, we’ll opt for the defaults and generate a skeletal swagger.json file.

    Alt

    This produces a well-formed document consisting of the required top-level fields, which you can use as a starting point for editing:

    {
        "swagger": "2.0",
        "info": {
            "title": "",
            "description": "GENERATED Swagger template",
            "termsOfService": "",
            "contact":{
               "name": "",
               "email": "",
               "url": ""
            },
            "license":{
              "name":"",
              "url":""
            },
            "version": "1.0.0"        
        },
        "paths":{
        
        }
    
    }
    

  3. The file opens in the default JSON editor. We’ll provide a common title and description, called Bookstore API:
    "swagger": "2.0",
    "info": {
       "title": "Bookstore API",
       "description": "Bookstore API",
      

  4. Next, we’ll define a path object /books/{isbn} and POST operation for the Book API. If the file is saved at this point, you’ll see an error marker indicating that a response object is missing. This is something that is required by the spec and is typically a valid HTTP response code:
        "paths":{
            "/books/{isbn}":{
                "post":{
                }
            }
        }
      
    Alt
  5. To correct this problem, add the HTTP 200 response code and save the file:
        "paths":{
            "/books/{isbn}":{
                "post":{
                    "200":{
                        "description": "Book is successfully added"
                    }
                }
            }
        }
      

  6. Next, you’ll notice the path URI contains a variable {isbn}. According to the Swagger spec, we should define a corresponding path parameter with that name, but let’s say you add just an empty parameter structure before completing the definition. This will result in two errors in your file:
        "paths":{
            "/books/{isbn}":{
                "post":{
                    "200":{
                        "description": "Book is successfully added"
                    }
                },
                "parameters":[{
                }]
            }
        }
      
    Alt

    The first error marker indicates that the {isbn} variable does not have a corresponding path parameter definition. The second error marker indicates that the required name field is missing. By filling out all the required fields, we now have a well-formed path parameter:

    "parameters":[{
       "name":"isbn",
       "in": "path",
       "type": "string",
       "required": true
    }
      

  7. To round out the rest of the parameter definitions, we’ll add a body parameter detailing what the properties of the book should be. Within this definition, we have a reference to the bookBody schema:

    "parameters":[{
       "name":"isbn",
       "in": "path",
       "type": "string",
       "required": true
    },
    {
       "name":"bookBody",
       "in":"body",
       "schema": {
          "$ref": "#/definitions/bookBody"
       }
    }]
      

  8. The bookBody schema would then be defined under the definitions object (see the final document below for the exact location in the document):

    "definitions":{
    	"bookBody":{
    		"type":"object",
    		"description": "The properties of a book",
    		"properties":{
    			"isbn":"string",
    			"title":{
    				"type":"string",
    				"example":"To Kill a Mockingbird"
    			},
    			"author":{
    				"type":"string",
    				"example":"Harper Lee"
    			
    			}
    		}
    	}
    }
    

The final document should look like this:

{
	"swagger": "2.0",
	"info": {
		"title": "Bookstore API",
		"description": "Bookstore API",
		"termsOfService": "",
		"contact":{
		   "name": "",
		   "email": "",
		   "url": ""
		},
		"license":{
		  "name":"",
		  "url":""
		},
		"version": "1.0.0"		
	},
	"paths":{
		"/books/{isbn}":{
			"post":{
				"responses":{
					"200":{
						"description": "Book is successfully added"
					}
				},
				"parameters":[{
					"name":"isbn",
					"in": "path",
					"type": "string",
					"required": true
				},
				{
					"name":"bookBody",
					"in":"body",
			        "schema": {
	        	      "$ref": "#/definitions/bookBody"
	        	     }
					
				}]
			}
		}
	},
	"definitions":{
		"bookBody":{
			"type":"object",
			"description": "The properties of a book",
			"properties":{
				"isbn":"string",
				"title":{
					"type":"string",
					"example":"To Kill a Mockingbird"
				},
				"author":{
					"type":"string",
					"example":"Harper Lee"
				
				}
			}
		}
	}

}
  

So far, we have created a basic REST API definition that details what the contents of the Book API would look like. While editing the API in the JSON editor, you can expect your file to be validated, which will help you create well-formed Swagger docs for clean deployment to the server.

Next, we’ll create a simple POJO servlet to test this API.

Creating a POJO servlet

In the Bookstore project, we will create a new HTTP servlet called BookServlet:

  1. Select the Bookstore project, right-click New > Servlet. Fill out the Java package (bookstore.servlet) and Class Name (BookServlet) fields and click Next:
    Alt
  2. Edit the URL mappings field to contain the pattern /books/*, then click Finish

    Alt
  3. Click Finish. Your generated servlet should have the annotation @WebServlet("/books/*").
  4. Add an implementation for the doPost method. The implementation will extract the isbn value from the request URI and construct a response body with it:

     
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		String booksURL = "/books";
    		String uri = request.getRequestURI();
    		uri = uri.substring(request.getContextPath().length());
    		if(uri.startsWith(booksURL)){
    			//extract the isbn
    			String isbn = uri.substring(booksURL.length()+1);
    			createResponse(request, response, isbn);
    			return;
    		}
    		super.doPost(request, response);
    	}
    
  5. Create another method called createResponse to parse the JSON and add the isbn to the object:

    private void createResponse(HttpServletRequest req, HttpServletResponse resp, String isbn){
    		try {
    			JSONObject jbook = JSONObject.parse(req.getReader());
    			jbook.put("isbn", isbn);
    			resp.setContentType("application/json");
    			resp.setStatus(200);
    			if(jbook!=null)
    			{
    				try {
    					String json = jbook.serialize();
    					resp.setContentLength(json.length());
    					resp.getWriter().write(json);
    				} catch (IOException e) {
    				}
    			}			
    	
    		} catch (IOException e) {
    		}
    		finally {
    
    		}
    	}
    
  6. Press Ctrl + Shift + O to import packages that are missing.

You are now ready to deploy and test your REST API application.

Deploy and test

  1. Right-click your Liberty server and click Add and Remove.
  2. Select the Bookstore web module.
  3. The presence of the swagger.json file in your application automatically adds the apiDiscovery-1.0 feature to your server.xml.
  4. Configure a user name and password and a keystore to access the API doc:
        <keyStore id="defaultKeyStore" password="Liberty"/>
        <basicRegistry>
          <user id="user" name="user" password="pwd"/>
        </basicRegistry>
    
  5. Once that’s in place, open up a web browser and type in this URL: https://localhost:9443/ibm/api/explorer/ (change the HTTPS port to match what you have in your server.xml).
  6. Type in your user name and password to access the site and you should see a rendering of your API:

    Alt
  7. To test out the POST operation, expand the section and fill in the form:

    1. Enter 111-111 in the isbn field.
    2. Click the example schema to copy over the bookBody content:
      Alt
    3. Click the Try it out! button:

      Alt
  8. When the operation is successful, you can expect to see the HTTP 200 response code, as well as the response body which contains the isbn you provided as input:

    Alt

And there you have a simple REST API application with Swagger REST API documentation.

3 comments on"Developing a Swagger-enabled REST API using WebSphere Developer Tools"

  1. Arthur De Magalhaes March 01, 2017

    Hi Gaurav,

    Where have you located your swagger.json file? It needs to be in the folder META-INF of your web app. And are you requesting JSON or YAML from /ibm/api/docs?

  2. can someone share web.xml for this web module?

  3. my local liberty server can’t locate swagger.json file from my web app. I can see following message in the console:
    [WARNING ] CWWKO1101W: A document of type Swagger_20_YAML was not returned by the APIProvider SwaggerWebProvider={contextRoot=/Bookstore}.
    What can be the reason and workaround for this situation?

Join The Discussion

Your email address will not be published. Required fields are marked *