Dropwizard: Guice Bundle

This entry is part 2 of 5 in the series Dropwizard

In this tutorial I will show you how to add Guice to your Dropwizard app. This will be a very basic implementation. Some things you should note is that I didn’t put in any docstrings. You should always do that!

Now there are a few Dropwizard Guice integrations available but the most active is the one I will show you today called “dropwizard-guicey“.

POM.xml

<dependency>
	<groupId>ru.vyarus</groupId>
	<artifactId>dropwizard-guicey</artifactId>
	<version>4.1.0</version>
</dependency>

Model

Now we create a model to use with our service

package ca.gaudreault.mydropwizardapp.models;

import java.io.Serializable;

import javax.validation.constraints.NotNull;

public class MyModel implements Serializable {
	private static final long serialVersionUID = 1L;
	private Integer value;
	
	public Integer getValue() {
		return value;
	}
	public void setValue(Integer value) {
		this.value = value;
	}
}

Service

Here you will create your service interface and class so that you can bind it in the guice module.

Interface

package ca.gaudraeult.mydropwizardapp.services;

import ca.gaudreault.mydropwizardapp.models.MyModel;

public interface MyService {
	MyModel runTest();
}

Implementation

package ca.gaudraeult.mydropwizardapp.services;

import ca.gaudreault.mydropwizardapp.models.MyModel;

public class MyServiceImpl implements MyService {
	
	public MyServiceImpl() { }

	@Override
	public MyModel runTest() {
		final MyModel myModel = new MyModel();
		myModel.setValue(123123);
		return myModel;
	}
}

ServerModule

Now when we create our module class you can bind the interface to the implementation. Note that if your implementation does not implement the interface this will not work.

package ca.gaudreault.mydropwizardapp;

import com.google.inject.AbstractModule;

import ca.gaudraeult.mydropwizardapp.services.MyService;
import ca.gaudraeult.mydropwizardapp.services.MyServiceImpl;

public class ServerModule extends AbstractModule  {

	@Override
	protected void configure() {
		bind(MyService.class).to(MyServiceImpl.class);
	}
}

Dropwizard Application

If you remember from part 1 of this series you created the based Dropwizard app. So you should have a class called “MyDropwizardAppApplication”. Open that now and modify the “initialize” like the below. Baseically here we are registering our ServerModule class to Dropwizard.

@Override
public void initialize(final Bootstrap bootstrap) {
	bootstrap.addBundle(GuiceBundle.builder()
		.enableAutoConfig(this.getClass().getPackage().getName())
		.modules(new ServerModule())
		.build());
}

And that is it you have configured a very basic Dropwizard Guice configuration.

NGINX + UWSGI + Ubuntu 16

If you use Python as part of your stack in developing a web architecture you most likely will also be utilizing NGINX with UWSGI together. In the following article I will give step by step instructions on how to set this up assuming you are using sockets as part of your installation.

What is UWSGI?: A full stack for building application servers for python and various other languages.

What is NGINX?: Is simply a web server or proxy server for various protocols but can also do load balancing, etc.

NGINX Installation:

sudo apt-get install nginx

#The next command checks that nginx is running
ps -auxw | grep nginx

#Stop the service
sudo service nginx stop
#Start the service
sudo service nginx start
#Restart the service
sudo service nginx restart
#nginx status
sudo service nginx status

Once it is installed you will have two folders. One called “sites-enabled” and one called “sites-available” located under /etc/nginx/ folder. The “sites-enabled” folder usually holds a symbolic link to the actual file sometimes in “sites-available” folder. But really can be hosted anywhere on the machine.

If you want to remove the default site link you can

sudo rm /etc/nginx/sites-enabled/default

Create our symbolic link in sites-enabled if we already have a nginx.conf file ready.

cd /etc/nginx/sites-enabled/

sudo ln -s ~/path/to/nginx/conf/nginx.conf nginx.conf

It’s important to note that you may run into permissions errors depending on where you are running your nginx.conf from. So you may need to grant permissions to your users home folder.

sudo chmod 755 /home/user_your_run_your_app_from/

UWSGI Installation:

sudo apt-get install uwsgi

#Stop uwsgi
sudo service uwsgi stop
#Start uwsgi
sudo service uwsgi start
#Restart uwsgi
sudo service uwsgi restart
#uwsgi status
sudo service uwsgi status

It you want to log to a custom folder your uwsgi.ini file will need “logto” folder specified and the correct permissions set.

cd /var/log/
sudo touch /var/log/mylogfile
sudo chmod 666 /var/log/mylogfile

You uwsgi.ini will also have a pid file “pidfile” which we will need to create.

cd /tmp/
touch mypid.pid

#Ownership
sudo chown THEUSER:www-data mypid.pid

#Ensure permissions are set to -rw-r--r--

UWSGI INI Options:

You can add whatever options you prefer as part of your uwsgi.ini setup file. However the below are usually the ones you should use.

[uwsgi]
socket = :5006 #or whatever socket you want
chmod-socket = 777
pidfile=/tmp/mypid.pid
master = True
chdir = /home/user_your_run_your_app_from/

#NOTE that you may or may not need this depending on how you setup your server.
plugin = python3
wsgi_file = my_python_class.py #File that runs your application
module = whatever
callable = app #Set default WSGI callable name.
logto = /var/log/mylogfile

These are not all the options you can pick. You can also set “stats”, “buffer-size”, “processes”, “threads”, “env”, etc. Just review the docs and pick what is right for you.

The option “env” you can add many times and for each time you use it you can set environment variable for use with your application.

NOTE: If you are running flask and use send_file and run as Python3.5 you may get the error “SystemError: <built-in function uwsgi_sendfile> returned a result with an error set”. If you do then you must add the following to your uwsgi.ini file “wsgi-disable-file-wrapper = true”.

NGINX Conf Example:

upstream flask {
    server 0.0.0.0:5006;
}
server {
    client_max_body_size 1G;
    listen 0.0.0.0:8081;
    server_name localhost;
    access_log /var/log/nginx/access_log combined;
	
    location / {
        include uwsgi_params;
        uwsgi_pass flask;
    }
    location /static/ {
        alias /path/to/my/app/static/;
    }
}
fastcgi_intercept_errors on;

UWSGI Service:

Sometimes we want to run our app as a service if you do then below are the steps for that.

sudo nano /etc/systemd/system/myawesomeservice.service

#Enter the contents below

[Unit]
Description=uWSGI instance to serve My Service
After=network.target
 
[Service]
User=user_to_run_as
Group=www-data
WorkingDirectory=/path/to/my/app/
ExecStart=/usr/bin/env bash -c 'uwsgi --ini /path/to/my/app/uwsgi.ini --uid user_to_run_as --gid www-data'
Restart=always
RestartSec=3
 
[Install]
WantedBy=multi-user.target

Next you need to ensure the user has access to your folder with correct ownerships.

chown -R user_to_run_as:www-data /path/to/my/app/*

Next enable the service and start the service.

sudo systemctl enable myawesomeservice
sudo systemctl daemon-reload
sudo systemctl start myawesomeservice
sudo service myawesomeservice status