Old Play2 Multi Project Tutorial With Swagger and Metrics
Intro
I've grown very fond of lieningen for managing dependencies and builds with Java and Clojure projects.
However, I'm currently working with some projects that rely on SBT for their build system.. namely the Play! Framework.
This guide is intended to show how to create a simple Play! Framework application with individual components that may be run independently of each other or aggregated into a monolithic service. It also adds the following nice features for building a REST API:
- Swagger for automatic API documentation and some nice to have basic API handling functions within your controllers. Swagger also has a generation project to create clients against your API. Swagger-Codegen
- Swagger-UI which allows you to easily document and interact with your API as you develop it.
- Metrics to display some basic information about aspects of your application.
- Vagrant configured with a VM to get you up and going with
- Ready to go publishing to your own maven repository with a
~/.ivy2/.credentials
file. - Ready to generate a windows MSI installer for your application
- Access logs
Many thanks to all the teams involved in these projects.
Tutorial
Get the Setup:
Download and install VirtualBox:
https://www.virtualbox.org/wiki/Downloads
Downoad and install Vagrant:
http://www.vagrantup.com/downloads.html
Get the Code:
Use your favorite git client to retrieve:
https://github.com/steveturner/play-multi-swagger
The project is structured as follows:
./services
contains the Play multi module project../services/modules
containsweb
,common
, andadmin
components to handle different aspects of your application.
Many thanks to http://eng.42go.com/multi-project-deployment-in-play-framework/ for this multi-module setup.
- ./vm contains support Puppet files to run your application in a VM.
##Start Running
Enter the repository and execute
vagrant up
. Go grab a coffee....Finished catalog run in 219.05 seconds
...vagrant up
downloads a base Ubuntu VM, installs JDK7, downloads Play 2.2-RC2 and puts it on your path, and forwards the VM port 9000 to your host port 9000.
Execute vagrant ssh
and cd \HOST\services
Execute play
At this point Play will download a number of dependencies and if all goes well dump you at a console [service-server] $
Execute run
from the play console. If all goes well you should get a pleasant Swagger-UI view with a single route defined called "firstMethod".
{}
Swagger JSON API documentation for this route is available at: http://localhost:9000/api-docs/server
The code that helps generate the UI is fairly basic but lets take a look.
Controller Code and APIs
The firstMethod
route is located in the toplevel Play application under app/controllers/Application.java
package controllers;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiResponses;
import controllers.common.JavaBaseApiController;
import controllers.common.ScalaBaseApiController;
import com.wordnik.swagger.annotations.*;
import play.api.mvc.Rendering;
import play.mvc.Http;
import play.mvc.Result;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
@Api(value = "/server", description = "Operations about the server")
public class Application extends JavaBaseApiController {
@GET
@Path("/server/firstMethod")
@ApiOperation(value = "Return woot hopefully!", response = Boolean.class, httpMethod = "GET")
@ApiResponses(value = {@ApiResponse(code = Http.Status.BAD_REQUEST, message = "Invalid status value")})
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public static Result firstMethod(
@ApiParam(value = "Status value for true or false", required = true, defaultValue = "false", allowableValues = "true,false") @PathParam("status") String status) {
if (status.equals("true")) {
if (request().accepts(MediaType.TEXT_HTML)) {
return ok(views.html.firstMethod.render(new value.ApiResponse(Http.Status.OK, "SUCCESS!")));
} else {
return returnValue(new value.ApiResponse(Http.Status.OK, "SUCCESS!"));
}
} else {
if (request().accepts(MediaType.TEXT_HTML)) {
return badRequest(views.html.firstMethod.render(new value.ApiResponse(Http.Status.BAD_REQUEST, "error")));
} else {
return returnValue(new value.ApiResponse(Http.Status.BAD_REQUEST, "error"));
}
}
}
}
If you read through the code, what you'll find is that it handles XML, JSON, and HTML via the ACCEPT header. Much of the code leverages the Swagger samples to make it easier to create relevant API responses, specifically JavaBaseAPIController
. Use your favorite client like DevHTTPClient for Chrome to exercise the API's with different content types. For example if you navigate to http://localhost:9000/server/firstMethod/true
you will see the HTML representation of the API call which is rendered via the Play template at: app/views/firstMethod.scala.html
Metrics
Metrics are available as JSON at: http://localhost:9000/admin/metrics
Additionally, the application logs all requests to logs/access.log
JMX Setup
The metrics engine also reports via JMX if you start the play application with:
play start -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=5678 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=localhost
Execute jvisualvm
from your shell and install the MBeans plugin via Tools->Plugins
{}
Routes
Samples routes available:
{}
Of note is how each submodule may be run independently and also handles public assets properly.
Summary
This tutorial creates a basic project laydown for Play! Framework development with submodules and some nice helper functions to get started building your own componentized REST API. If you have any questions or suggestions feel free to comment below or on GitHub.