In the previous Gradle series post we built Wrapper to execute Gradle tasks without installed version on your machine. It’s time to write some code and make our project useful. In this post Gradle will help us to start a web server.
To make it happened we need:
Dropwizard
All the aspects related with providing readable RESTful API via reliable Web Server are covered by Dropwizard. These folks give all of these nice features for us:
- Jetty – lighweight Java Web Server
- Jersey – building RESTful web applications (JAX-RS implementation)
- Jackson – parsing JSON data format
- Metrics – measure app performance
- and more!
To start using all of above features you must add Dropwizard core as a dependency to the project:
apply plugin: 'java' | |
sourceCompatibility = 1.8 | |
project.ext { | |
dropwizardVersion = '0.8.2' | |
} | |
repositories { | |
mavenCentral() | |
} | |
dependencies { | |
compile group: 'io.dropwizard', name: 'dropwizard-core', version: dropwizardVersion | |
} |
Configuration
It stores all the project and environment related settings. Our simple configuration contains just one field: appName
package com.karollotkowski.cleancode; | |
import com.fasterxml.jackson.annotation.JsonProperty; | |
import io.dropwizard.Configuration; | |
import org.hibernate.validator.constraints.NotEmpty; | |
public class AppConfiguration extends Configuration { | |
@NotEmpty | |
private String appName; | |
@JsonProperty | |
public String getAppName() { | |
return appName; | |
} | |
@JsonProperty | |
public void setAppName(final String appName) { | |
this.appName = appName; | |
} | |
} |
@NotEmpty annotation will assure that application will not start if appName value will be not defined.
@JsonProperty allows to deserialise and serialise from a YAML property.
Let’s add YAML configuration file with property appName and value equals ‘Clean code rulez!‘
appName: Clean code rulez! |
I placed config file in the new directory config at the top project level.
Application
The last Dropwizard part is to create a new Application class to start web server with simple logic.
package com.karollotkowski.cleancode; | |
import io.dropwizard.Application; | |
import io.dropwizard.setup.Environment; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
public class CleanCodeApplication extends Application<AppConfiguration> { | |
public static final Logger LOGGER = LoggerFactory.getLogger(CleanCodeApplication.class); | |
public static void main(final String[] args) throws Exception { | |
new CleanCodeApplication().run(args); | |
} | |
@Override | |
public void run(final AppConfiguration configuration, final Environment environment) | |
throws Exception { | |
LOGGER.info("Application name: {}", configuration.getAppName()); | |
} | |
} |
This class is using our Configuration class and is a main entry point to the application. To run the app we just need a main method to start a run method which starts a web server as a process.
During spin on the Dropwizard we should see appName value in the logs:
LOGGER.info("Application name: {}", configuration.getAppName());
To start web server I will use Gradle plugin.
Gradle Application plugin
Gradle provides Application plugin to create an executable JVM application. This plugin contains java and distribution plugins.
At this moment we can replace standard java plugin with application plugin.
apply plugin: 'application'
After refresh you should see 2 new sections on Gradle tasks list: Application and Distribution
Application tasks ----------------- installApp - Installs the project as a JVM application along with libs and OS specific scripts. run - Runs this project as a JVM application Distribution tasks ------------------ assembleDist - Assembles the main distributions distTar - Bundles the project as a distribution. distZip - Bundles the project as a distribution. installDist - Installs the project as a distribution as-is.
We will use run task to start application. This task needs full name of the main class to execute and execution parameters:
mainClassName = "com.karollotkowski.cleancode.CleanCodeApplication"
project.ext { configPath = "$rootProject.projectDir/config/" }
run { args 'server', configPath + 'app_config.yml' }
Full build.gradle file with Dropwizard and Gralde plugin settings:
apply plugin: 'application' | |
sourceCompatibility = 1.8 | |
project.ext { | |
configPath = "$rootProject.projectDir/config/" | |
dropwizardVersion = '0.8.2' | |
} | |
repositories { | |
mavenCentral() | |
} | |
dependencies { | |
compile group: 'io.dropwizard', name: 'dropwizard-core', version: dropwizardVersion | |
} | |
mainClassName = "com.karollotkowski.cleancode.CleanCodeApplication" | |
run { | |
args 'server', configPath + 'app_config.yml' | |
} |
Spin on web server
All the stuff is ready to start a server. Execute run Gradle task from cmd or IDE:
$ ./gradlew run
Output should looks similar to this:
:compileJava UP-TO-DATE | |
:processResources UP-TO-DATE | |
:classes UP-TO-DATE | |
:run | |
INFO [2015-10-13 22:28:52,049] org.eclipse.jetty.util.log: Logging initialized @2319ms | |
INFO [2015-10-13 22:28:52,297] com.karollotkowski.cleancode.CleanCodeApplication: Application name: Clean code rulez! | |
INFO [2015-10-13 22:28:52,305] io.dropwizard.server.ServerFactory: Starting CleanCodeApplication | |
INFO [2015-10-13 22:28:52,498] org.eclipse.jetty.setuid.SetUIDListener: Opened application@75d0911a{HTTP/1.1}{0.0.0.0:8080} | |
INFO [2015-10-13 22:28:52,499] org.eclipse.jetty.setuid.SetUIDListener: Opened admin@75e91545{HTTP/1.1}{0.0.0.0:8081} | |
INFO [2015-10-13 22:28:52,504] org.eclipse.jetty.server.Server: jetty-9.2.9.v20150224 | |
INFO [2015-10-13 22:28:53,415] io.dropwizard.jersey.DropwizardResourceConfig: The following paths were found for the configured resources: | |
NONE | |
INFO [2015-10-13 22:28:53,423] org.eclipse.jetty.server.handler.ContextHandler: Started i.d.j.MutableServletContextHandler@4d4960c8{/,null,AVAILABLE} | |
INFO [2015-10-13 22:28:53,431] io.dropwizard.setup.AdminEnvironment: tasks = | |
POST /tasks/log-level (io.dropwizard.servlets.tasks.LogConfigurationTask) | |
POST /tasks/gc (io.dropwizard.servlets.tasks.GarbageCollectionTask) | |
WARN [2015-10-13 22:28:53,432] io.dropwizard.setup.AdminEnvironment: | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! THIS APPLICATION HAS NO HEALTHCHECKS. THIS MEANS YOU WILL NEVER KNOW ! | |
! IF IT DIES IN PRODUCTION, WHICH MEANS YOU WILL NEVER KNOW IF YOU'RE ! | |
! LETTING YOUR USERS DOWN. YOU SHOULD ADD A HEALTHCHECK FOR EACH OF YOUR ! | |
! APPLICATION'S DEPENDENCIES WHICH FULLY (BUT LIGHTLY) TESTS IT. ! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
INFO [2015-10-13 22:28:53,442] org.eclipse.jetty.server.handler.ContextHandler: Started i.d.j.MutableServletContextHandler@5d39f2d8{/,null,AVAILABLE} | |
INFO [2015-10-13 22:28:53,475] org.eclipse.jetty.server.ServerConnector: Started application@75d0911a{HTTP/1.1}{0.0.0.0:8080} | |
INFO [2015-10-13 22:28:53,477] org.eclipse.jetty.server.ServerConnector: Started admin@75e91545{HTTP/1.1}{0.0.0.0:8081} | |
INFO [2015-10-13 22:28:53,477] org.eclipse.jetty.server.Server: Started @3749ms |
As you see there is an appName variable value:
INFO [2015-10-13 22:28:52,297] com.karollotkowski.cleancode.CleanCodeApplication: Application name: Clean code rulez!
Dropwizard started two services:
- application: http://localhost:8080/ (no content because no resources registered)
- admin panel: http://localhost:8081
1 Pingback