diff --git a/.gitignore b/.gitignore index dce44572f55..87a80ef8408 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ target atlassian-ide-plugin.xml logs +*.iml +*.ipr diff --git a/dropwizard-example/README.md b/dropwizard-example/README.md new file mode 100644 index 00000000000..0449d033ca6 --- /dev/null +++ b/dropwizard-example/README.md @@ -0,0 +1,41 @@ +# Introduction + +The drop wizard example application was developed to, as its name implies, provide examples of some of the features +present in drop wizard. + +# Overview + +Included with this application is an example of the optional db API module. The examples provided illustrate a few of +the features available in (JDBI)[http://jdbi.org], along with demonstrating how these are used from within dropwizard. + +This database example is comprised of the following classes. + +* The `PersonDAO` illustrates using the [SQL Object Queries](http://jdbi.org/sql_object_api_queries/) and string template +features in JDBI. + +* The `PeopleDAO.sql.stg` stores all the SQL statements for use in the `PersonDAO`, note this is located in the +src/resources under the same path as the `PersonDAO` class file. + +* The `SetupDatabaseCommand` illustrates building a "setup" command which can create your database prior to running +dropwizard your application for the first time. + +* The `PersonResource` and `PeopleResource` are the REST resource which use the PersonDAO to retrieve data from the database, note the injection +of the PersonDAO in their constructors. + +As with all the modules the db example is wired up in the `initialize` function of the `HelloWorldService`. + +# Running The Application + +To test the example application run the following commands. + +* To package the example run. + + mvn package + +* To setup the h2 database run. + + java -jar target/dropwizard-example-0.3.0-SNAPSHOT.jar setup example.yml + +* To run the server run. + + java -jar target/dropwizard-example-0.3.0-SNAPSHOT.jar server example.yml diff --git a/dropwizard-example/example.yml b/dropwizard-example/example.yml index 868cb1de5cc..4c20852601f 100644 --- a/dropwizard-example/example.yml +++ b/dropwizard-example/example.yml @@ -2,6 +2,21 @@ template: Hello, %s! defaultName: Stranger +# Database settings. +database: + + # the name of your JDBC driver + driverClass: org.h2.Driver + + # the username + user: sa + + # the password + password: sa + + # the JDBC URL + url: jdbc:h2:target/example + # HTTP-specific options. http: diff --git a/dropwizard-example/pom.xml b/dropwizard-example/pom.xml index 8ff22098522..9d9c51a0460 100644 --- a/dropwizard-example/pom.xml +++ b/dropwizard-example/pom.xml @@ -25,6 +25,23 @@ dropwizard-core ${project.version} + + com.yammer.dropwizard + dropwizard-db + ${project.version} + + + + org.antlr + stringtemplate + 3.2.1 + + + + com.h2database + h2 + 1.3.158 + com.yammer.dropwizard dropwizard-auth diff --git a/dropwizard-example/src/main/java/com/example/helloworld/HelloWorldConfiguration.java b/dropwizard-example/src/main/java/com/example/helloworld/HelloWorldConfiguration.java index c985f3ef850..8e97a3a4e7e 100644 --- a/dropwizard-example/src/main/java/com/example/helloworld/HelloWorldConfiguration.java +++ b/dropwizard-example/src/main/java/com/example/helloworld/HelloWorldConfiguration.java @@ -2,16 +2,27 @@ import com.example.helloworld.core.Template; import com.yammer.dropwizard.config.Configuration; +import com.yammer.dropwizard.db.DatabaseConfiguration; +import org.codehaus.jackson.annotate.JsonProperty; import org.hibernate.validator.constraints.NotEmpty; +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + @SuppressWarnings("FieldMayBeFinal") public class HelloWorldConfiguration extends Configuration { + @NotEmpty private String template; @NotEmpty private String defaultName = "Stranger"; + @Valid + @NotNull + @JsonProperty + private DatabaseConfiguration database = new DatabaseConfiguration(); + public String getTemplate() { return template; } @@ -23,4 +34,8 @@ public String getDefaultName() { public Template buildTemplate() { return new Template(template, defaultName); } + + public DatabaseConfiguration getDatabaseConfiguration() { + return database; + } } diff --git a/dropwizard-example/src/main/java/com/example/helloworld/HelloWorldService.java b/dropwizard-example/src/main/java/com/example/helloworld/HelloWorldService.java index 1b617ee06dc..b75dc01f336 100644 --- a/dropwizard-example/src/main/java/com/example/helloworld/HelloWorldService.java +++ b/dropwizard-example/src/main/java/com/example/helloworld/HelloWorldService.java @@ -2,15 +2,21 @@ import com.example.helloworld.auth.ExampleAuthenticator; import com.example.helloworld.cli.RenderCommand; +import com.example.helloworld.cli.SetupDatabaseCommand; import com.example.helloworld.core.Template; import com.example.helloworld.core.User; +import com.example.helloworld.db.PeopleDAO; import com.example.helloworld.health.TemplateHealthCheck; import com.example.helloworld.resources.HelloWorldResource; +import com.example.helloworld.resources.PeopleResource; +import com.example.helloworld.resources.PersonResource; import com.example.helloworld.resources.ProtectedResource; import com.yammer.dropwizard.Service; import com.yammer.dropwizard.auth.basic.BasicAuthBundle; import com.yammer.dropwizard.bundles.AssetsBundle; import com.yammer.dropwizard.config.Environment; +import com.yammer.dropwizard.db.Database; +import com.yammer.dropwizard.db.DatabaseFactory; public class HelloWorldService extends Service { public static void main(String[] args) throws Exception { @@ -20,18 +26,27 @@ public static void main(String[] args) throws Exception { private HelloWorldService() { super("hello-world"); addCommand(new RenderCommand()); + addCommand(new SetupDatabaseCommand()); addBundle(new AssetsBundle()); addBundle(new BasicAuthBundle(new ExampleAuthenticator(), "SUPER SECRET STUFF")); } @Override protected void initialize(HelloWorldConfiguration configuration, - Environment environment) { + Environment environment) throws ClassNotFoundException{ final Template template = configuration.buildTemplate(); + final DatabaseFactory factory = new DatabaseFactory(environment); + final Database db = factory.build(configuration.getDatabaseConfiguration(), "h2"); + final PeopleDAO peopleDAO = db.onDemand(PeopleDAO.class); + + environment.addHealthCheck(new TemplateHealthCheck(template)); environment.addResource(new HelloWorldResource(template)); environment.addResource(new ProtectedResource()); + + environment.addResource(new PeopleResource(peopleDAO)); + environment.addResource(new PersonResource(peopleDAO)); } } diff --git a/dropwizard-example/src/main/java/com/example/helloworld/cli/SetupDatabaseCommand.java b/dropwizard-example/src/main/java/com/example/helloworld/cli/SetupDatabaseCommand.java new file mode 100644 index 00000000000..4c9a00c186f --- /dev/null +++ b/dropwizard-example/src/main/java/com/example/helloworld/cli/SetupDatabaseCommand.java @@ -0,0 +1,33 @@ +package com.example.helloworld.cli; + +import com.example.helloworld.HelloWorldConfiguration; +import com.example.helloworld.db.PeopleDAO; +import com.yammer.dropwizard.AbstractService; +import com.yammer.dropwizard.cli.ConfiguredCommand; +import com.yammer.dropwizard.config.Environment; +import com.yammer.dropwizard.db.Database; +import com.yammer.dropwizard.db.DatabaseFactory; +import com.yammer.dropwizard.logging.Log; +import org.apache.commons.cli.CommandLine; + +public class SetupDatabaseCommand extends ConfiguredCommand { + + public SetupDatabaseCommand() { + super("setup", "Setup the database."); + } + + @Override + protected void run(AbstractService service, HelloWorldConfiguration configuration, CommandLine params) throws Exception { + + final Log log = Log.forClass(SetupDatabaseCommand.class); + final Environment environment = new Environment(configuration, service); + //service.initializeWithBundles(configuration, environment); + final DatabaseFactory factory = new DatabaseFactory(environment); + final Database db = factory.build(configuration.getDatabaseConfiguration(), "h2"); + final PeopleDAO peopleDAO = db.onDemand(PeopleDAO.class); + + log.info("creating tables."); + peopleDAO.createPeopleTable(); + + } +} diff --git a/dropwizard-example/src/main/java/com/example/helloworld/core/Person.java b/dropwizard-example/src/main/java/com/example/helloworld/core/Person.java new file mode 100644 index 00000000000..fcd627dbaa7 --- /dev/null +++ b/dropwizard-example/src/main/java/com/example/helloworld/core/Person.java @@ -0,0 +1,32 @@ +package com.example.helloworld.core; + +public class Person { + + private long id; + private String fullName; + private String jobTitle; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getFullName() { + return fullName; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + public String getJobTitle() { + return jobTitle; + } + + public void setJobTitle(String jobTitle) { + this.jobTitle = jobTitle; + } +} diff --git a/dropwizard-example/src/main/java/com/example/helloworld/db/PeopleDAO.java b/dropwizard-example/src/main/java/com/example/helloworld/db/PeopleDAO.java new file mode 100644 index 00000000000..2ed09727485 --- /dev/null +++ b/dropwizard-example/src/main/java/com/example/helloworld/db/PeopleDAO.java @@ -0,0 +1,31 @@ +package com.example.helloworld.db; + +import com.example.helloworld.core.Person; +import com.google.common.collect.ImmutableList; +import org.skife.jdbi.v2.sqlobject.Bind; +import org.skife.jdbi.v2.sqlobject.BindBean; +import org.skife.jdbi.v2.sqlobject.GetGeneratedKeys; +import org.skife.jdbi.v2.sqlobject.SqlQuery; +import org.skife.jdbi.v2.sqlobject.SqlUpdate; +import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapperFactory; +import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3; +import org.skife.jdbi.v2.tweak.BeanMapperFactory; + +@ExternalizedSqlViaStringTemplate3 +@RegisterMapperFactory(BeanMapperFactory.class) +public interface PeopleDAO { + + @SqlUpdate + void createPeopleTable(); + + @SqlQuery + Person findById(@Bind("id") Long id); + + @SqlUpdate + @GetGeneratedKeys + long create(@BindBean Person person); + + @SqlQuery + ImmutableList findAll(); + +} diff --git a/dropwizard-example/src/main/java/com/example/helloworld/resources/PeopleResource.java b/dropwizard-example/src/main/java/com/example/helloworld/resources/PeopleResource.java new file mode 100644 index 00000000000..2d996996289 --- /dev/null +++ b/dropwizard-example/src/main/java/com/example/helloworld/resources/PeopleResource.java @@ -0,0 +1,34 @@ +package com.example.helloworld.resources; + +import com.example.helloworld.core.Person; +import com.example.helloworld.db.PeopleDAO; + +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import java.util.List; + +@Path("/people") +@Produces(MediaType.APPLICATION_JSON) +public class PeopleResource { + + private final PeopleDAO peopleDAO; + + public PeopleResource(PeopleDAO peopleDAO) { + this.peopleDAO = peopleDAO; + } + + @POST + public Person createPerson(Person person) { + final long personId = peopleDAO.create(person); + return peopleDAO.findById(personId); + } + + @GET + public List listPeople() { + return peopleDAO.findAll(); + } + +} diff --git a/dropwizard-example/src/main/java/com/example/helloworld/resources/PersonResource.java b/dropwizard-example/src/main/java/com/example/helloworld/resources/PersonResource.java new file mode 100644 index 00000000000..748470c022a --- /dev/null +++ b/dropwizard-example/src/main/java/com/example/helloworld/resources/PersonResource.java @@ -0,0 +1,28 @@ +package com.example.helloworld.resources; + +import com.example.helloworld.core.Person; +import com.example.helloworld.db.PeopleDAO; +import com.yammer.dropwizard.jersey.params.LongParam; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Path("/person/{personId}") +@Produces(MediaType.APPLICATION_JSON) +public class PersonResource { + + private final PeopleDAO peopleDAO; + + public PersonResource(PeopleDAO peopleDAO) { + this.peopleDAO = peopleDAO; + } + + @GET + public Person getPerson(@PathParam("personId") LongParam personId) { + return peopleDAO.findById(personId.get()); + } + +} diff --git a/dropwizard-example/src/main/resources/com/example/helloworld/db/PeopleDAO.sql.stg b/dropwizard-example/src/main/resources/com/example/helloworld/db/PeopleDAO.sql.stg new file mode 100644 index 00000000000..f65570a6f31 --- /dev/null +++ b/dropwizard-example/src/main/resources/com/example/helloworld/db/PeopleDAO.sql.stg @@ -0,0 +1,17 @@ +group PeopleDAO; + +createPeopleTable() ::= << + create table people (id Serial primary key, fullName varchar(255), jobTitle varchar(100)) +>> + +findById(id) ::= << + select id, fullName, jobTitle from people where id = :id +>> + +create() ::= << + insert into people (fullName, jobTitle) values (:fullName, :jobTitle) +>> + +findAll() ::= << + select id, fullName, jobTitle from people +>> \ No newline at end of file