Serving static content with Dropwizard

2 minute read

Dropwizard, in its own words is a "Java framework for developing ops-friendly, high-performance, RESTful web services".

It is extremely lightweight, stable and mature, with most of the boilerplate code for configuration, application metrics, logging, alerting already built in.

In User Insights, Dropwizard powers our REST API. The same code base also hosts an internal console powered by BackboneJS which consumes these API's for visualizing the results. Now, here is where the challenge comes in. By default, static files are part of the JAR that runs your application server. Any changes to the console (quite frequent) requires the JAR to be rebuilt and deployed on the server. I wanted to separate the static files required by the console so that the UI developer could deploy the console package as per his whims without having any dependency on the API JAR. At the same time I did not want to deploy another web server on the box just for these files.

One of the issues that most people face while serving static content with Dropwizard is how to serve these static files from outside the JAR. If you are one of those people, here is a post that you might find useful.

You can serve static content for your Dropwizard application efficiently in two ways:
1) Using nginx
2) Using a custom Asset Bundler

1) Using nginx:
You can configure nginx so that it serves all the static content, while unrecognized requests can be forwarded to your application server.
Here is a sample config:

# Site (port 80 -> 8080)
server {
   listen          80;       # Listen on port 80 for IPv4 requests

server_name localhost;

access_log /var/log/nginx/site_access.log;
error_log /var/log/nginx/site_error.log;

# Set the root of the static content

root /usr/share/nginx/html;

# Redirect server error pages to the static page /50x.html

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}

# Filter static content types and serve from the root

location ~\*\.(jpg|jpeg|gif|css|png|js|ico|html)$ {
access_log off;
expires max;
}

# Serve the dynamic content (Site)

location / { # The application provides its own detailed logs
access_log off;

     # Hand over to the application
     proxy_pass http://localhost:8080/;

     proxy_set_header Host $http_host;
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

}

}

</code>

For the above config, nginx is serving files with the any of the following extensions: *.jpg, *.jpeg, *.gif, *.css, *.png, *.js, *.ico, *.html.
The location of these files should be: /usr/share/nginx/html
Any other content is forwarded to your application server serving on port 8080 (default Dropwizard port).
Any 50x error generated by your application server will cause a redirect to the /50x.html static file located at /usr/share/nginx/html

2) Using custom Asset Bundler:
This github repo hosts a drop in replacement for Dropwizard's AssetsBundle class which allows Assets (files) to be served from outside the jar.
Many people find it difficult to use this plugin because of lack of proper documentation/examples.
Here is a link to a sample project I created which shows the proper use of this plugin.

Hope you find this useful. If you have any suggestions/alternatives regarding this, then do let me know!