this article is copied from Day 13: Dropwizard -- The Awesome Java REST Server Stack
Setting Up Maven
% mvn archetype:create -DgroupId=com.example -DartifactId=myblog % cd myblog
% git init % git add . % git commit -m 'initial commit'
create .gitignore:
.idea/ *.iml target/
% git add .gitignore % git commit -m 'add .gitignore'
Updating the pom.xml
update pom.xml:
diff --git a/pom.xml b/pom.xml index 2ff8c7f..0e4df99 100644 --- a/pom.xml +++ b/pom.xml @@ -12,6 +12,7 @@ <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <dropwizard.version>0.7.1</dropwizard.version> </properties> <dependencies> @@ -21,5 +22,49 @@ <version>3.8.1</version> <scope>test</scope> </dependency> + <dependency> + <groupId>io.dropwizard</groupId> + <artifactId>dropwizard-core</artifactId> + <version>${dropwizard.version}</version> + </dependency> </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>1.6</version> + <configuration> + <createDependencyReducedPom>true</createDependencyReducedPom> + <filters> + <filter> + <artifact>*:*</artifact> + <excludes> + <exclude>META-INF/*.SF</exclude> + <exclude>META-INF/*.DSA</exclude> + <exclude>META-INF/*.RSA</exclude> + </excludes> + </filter> + </filters> + </configuration> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + <configuration> + <transformers> + <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> + <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> + <mainClass>com.example.myblog.MyBlogApplication</mainClass> + </transformer> + </transformers> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> </project>
install dependency
% mvn clean install
% git add pom.xml % git commit -m 'add dropwizard.version, dependency and maven-shade plugins'
Creating Configuration class
create src/main/java/com/example/myblog/MyBlogConfiguration.java:
package com.example.myblog; import io.dropwizard.Configuration; public class MyBlogConfiguration extends Configuration { }
% git add src/main/java/com/example/myblog/MyBlogConfiguration.java % git commit -m 'create configuration class'
※ name, template が必須?
Creating Application class
create src/main/java/com/example/myblog/MyBlogApplication.java:
package com.example.myblog; import io.dropwizard.Application; import io.dropwizard.setup.Bootstrap; import io.dropwizard.setup.Environment; public class MyBlogApplication extends Application<MyBlogConfiguration> { public static void main(String[] args) throws Exception { new MyBlogApplication().run(args); } @Override public String getName() { return "my-blog"; } @Override public void initialize(Bootstrap<MyBlogConfiguration> bootstrap) { // nothing to do yet } @Override public void run(MyBlogConfiguration configuration, Environment environment) throws Exception { // nothing to do yet } }
% git add src/main/java/com/example/myblog/MyBlogApplication.java % git commit -m 'create application class'
Creating A Representation Class
create src/main/java/com/example/myblog/core/Blog.java:
package com.example.myblog.core; import java.util.Date; import java.util.UUID; import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.URL; public class Blog { private String id = UUID.randomUUID().toString(); @NotBlank private String title; @URL @NotBlank private String url; private final Date publishedOn = new Date(); public Blog() { } public Blog(String title, String url) { super(); this.title = title; this.url = url; } public String getId() { return id; } public String getTitle() { return title; } public String getUrl() { return url; } public Date getPublishedOn() { return publishedOn; } }
% git add src/main/java/com/example/myblog/core/Blog.java % git commit -m 'create representation class'
Creating Resource class
create src/main/java/com/example/myblog/resources/IndexResource.java:
package com.example.myblog.resources; import java.util.Arrays; import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import com.codahale.metrics.annotation.Timed; import com.example.myblog.core.Blog; @Path("/") public class IndexResource { @GET @Produces(value = MediaType.APPLICATION_JSON) @Timed public List<Blog> index() { return Arrays.asList(new Blog("getting started dropwizard 0.7.0", "http://okamuuu.hatenablog.com/entry/2014/11/06/192836")); } }
and update MyBlogApplication.java:
diff --git a/src/main/java/com/example/myblog/MyBlogApplication.java b/src/main/java/com/example/myblog/MyBlogApplication.java index f64d82d..81c8ab4 100644 --- a/src/main/java/com/example/myblog/MyBlogApplication.java +++ b/src/main/java/com/example/myblog/MyBlogApplication.java @@ -4,6 +4,8 @@ import io.dropwizard.Application; import io.dropwizard.setup.Bootstrap; import io.dropwizard.setup.Environment; +import com.example.myblog.resources.IndexResource; + public class MyBlogApplication extends Application<MyBlogConfiguration> { public static void main(String[] args) throws Exception { new MyBlogApplication().run(args); @@ -22,7 +24,9 @@ public class MyBlogApplication extends Application<MyBlogConfiguration> { @Override public void run(MyBlogConfiguration configuration, Environment environment) throws Exception { - // nothing to do yet + + final IndexResource indexResource = new IndexResource(); + environment.jersey().register(indexResource); } }
% git add src/main/java/com/example/myblog/MyBlogApplication.java % git add src/main/java/com/example/myblog/resources/IndexResource.java % git commit -m 'add IndexResource'
Running Application
% mvn package
run it.
% java -jar target/myblog-1.0-SNAPSHOT.jar server
check it.
% curl http://localhost:8080 [{"id":"083541a0-29bc-474a-b1ec-dae598bbafc1","title":"getting started dropwizard 0.7.0","url":"http://okamuuu.hatenablog.com/entry/2014/11/06/192836","publishedOn":1416107023288}]
Configuring MongoDB
update pom.xml
diff --git a/pom.xml b/pom.xml index 0e4df99..ed89c53 100644 --- a/pom.xml +++ b/pom.xml @@ -27,6 +27,11 @@ <artifactId>dropwizard-core</artifactId> <version>${dropwizard.version}</version> </dependency> + <dependency> + <groupId>net.vz.mongodb.jackson</groupId> + <artifactId>mongo-jackson-mapper</artifactId> + <version>1.4.2</version> + </dependency> </dependencies> <build>
% git add pom.xml % git commit -m 'add mongo-jackson-mapper to dependency'
% mvn clean install
create myblog.yml
mongoHost: localhost mongoPort: 27017 mongoDb: myblog
update src/main/java/com/example/myblog/MyBlogConfiguration.java:
package com.example.myblog; import io.dropwizard.Configuration; import com.fasterxml.jackson.annotation.JsonProperty; import org.hibernate.validator.constraints.NotEmpty; import javax.validation.constraints.Max; import javax.validation.constraints.Min; public class MyBlogConfiguration extends Configuration { @JsonProperty @NotEmpty private String mongoHost = "localhost"; @JsonProperty @Min(1) @Max(65535) private int mongoPort = 27017; @JsonProperty @NotEmpty private String mongoDb = "myblog"; @JsonProperty public String getMongoHost() { return mongoHost; } @JsonProperty public void setMongoHost(String host) { this.mongoHost = host; } @JsonProperty public int getMongoPort() { return mongoPort; } @JsonProperty public void setMongoPort(int port) { this.mongoPort = port; } @JsonProperty public String getMongoDb() { return mongoDb; } @JsonProperty public void setMongoDb(String db) { this.mongoDb = db; } }
% git add myblog.yml % git add src/main/java/com/example/myblog/MyBlogConfiguration.java % git commit -m 'add mongoDB configuration'
create src/main/java/com/example/myblog/MongoManaged.java:
package com.example.myblog; import com.mongodb.Mongo; import io.dropwizard.lifecycle.Managed; public class MongoManaged implements Managed { private Mongo mongo; public MongoManaged(Mongo mongo) { this.mongo = mongo; } @Override public void start() throws Exception { } @Override public void stop() throws Exception { mongo.close(); } }
update src/main/java/com/example/myblog/MyBlogApplication.java
diff --git a/src/main/java/com/example/myblog/MyBlogApplication.java b/src/main/java/com/example/myblog/MyBlogApplication.java index 81c8ab4..ce938eb 100644 --- a/src/main/java/com/example/myblog/MyBlogApplication.java +++ b/src/main/java/com/example/myblog/MyBlogApplication.java @@ -6,6 +6,8 @@ import io.dropwizard.setup.Environment; import com.example.myblog.resources.IndexResource; +import com.mongodb.Mongo; + public class MyBlogApplication extends Application<MyBlogConfiguration> { public static void main(String[] args) throws Exception { new MyBlogApplication().run(args); @@ -25,6 +27,10 @@ public class MyBlogApplication extends Application<MyBlogConfiguration> { public void run(MyBlogConfiguration configuration, Environment environment) throws Exception { + Mongo mongo = new Mongo(configuration.getMongoHost(), configuration.getMongoPort()); + MongoManaged mongoManaged = new MongoManaged(mongo); + environment.lifecycle().manage(mongoManaged); + final IndexResource indexResource = new IndexResource(); environment.jersey().register(indexResource); }
% git add src/main/java/com/example/myblog/MyBlogApplication.java % git add src/main/java/com/example/myblog/MongoManaged.java % git commit -m 'add Mongo lifecycle managed class'
% mvn celan install
Add HealthCheck
create src/main/java/com/example/myblog/health/MongoHealthCheck.java
package com.example.myblog.health; import com.mongodb.Mongo; import com.codahale.metrics.health.HealthCheck; public class MongoHealthCheck extends HealthCheck { private final Mongo mongo; public MongoHealthCheck(Mongo mongo) { this.mongo = mongo; } @Override protected Result check() throws Exception { mongo.getDatabaseNames(); return Result.healthy(); } }
update src/main/java/com/example/myblog/MyBlogApplication.java:
diff --git a/src/main/java/com/example/myblog/MyBlogApplication.java b/src/main/java/com/example/myblog/MyBlogApplication.java index 81c8ab4..902ff86 100644 --- a/src/main/java/com/example/myblog/MyBlogApplication.java +++ b/src/main/java/com/example/myblog/MyBlogApplication.java @@ -5,6 +5,9 @@ import io.dropwizard.setup.Bootstrap; import io.dropwizard.setup.Environment; import com.example.myblog.resources.IndexResource; +import com.example.myblog.health.MongoHealthCheck; + +import com.mongodb.Mongo; public class MyBlogApplication extends Application<MyBlogConfiguration> { public static void main(String[] args) throws Exception { @@ -25,6 +28,14 @@ public class MyBlogApplication extends Application<MyBlogConfiguration> { public void run(MyBlogConfiguration configuration, Environment environment) throws Exception { + Mongo mongo = new Mongo(configuration.getMongoHost(), configuration.getMongoPort()); + MongoManaged mongoManaged = new MongoManaged(mongo); + environment.lifecycle().manage(mongoManaged); + + final MongoHealthCheck mongoHealthCheck = + new MongoHealthCheck(mongo); + environment.healthChecks().register("mongo", mongoHealthCheck); + final IndexResource indexResource = new IndexResource(); environment.jersey().register(indexResource); }
% git add src/main/java/com/example/myblog/MyBlogApplication.java % git add src/main/java/com/example/myblog/health/MongoHealthCheck.java % git commit -m 'add MongoHealthCheck'
check
% java -jar target/myblog-1.0-SNAPSHOT.jar server myblog.yml
% curl http://localhost:8081/healthcheck {"deadlocks":{"healthy":true},"mongo":{"healthy":true}
Create BlogResource
update src/main/java/com/example/myblog/core/Blog.java
package com.example.myblog.core; import java.util.Date; import net.vz.mongodb.jackson.Id; import net.vz.mongodb.jackson.ObjectId; import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.URL; import com.fasterxml.jackson.annotation.JsonCreator; public class Blog { @Id public String id; @NotBlank public String title; @URL @NotBlank public String url; public final Date publishedOn = new Date(); }
update src/main/java/com/example/myblog/resources/IndexResource.java:
package com.example.myblog.resources; import java.util.ArrayList; import java.util.List; import com.example.myblog.core.Blog; import com.google.common.base.Optional; import com.codahale.metrics.annotation.Timed; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import java.util.concurrent.atomic.AtomicLong; import net.vz.mongodb.jackson.DBCursor; import net.vz.mongodb.jackson.JacksonDBCollection; @Path("/") @Produces(MediaType.APPLICATION_JSON) public class IndexResource { private JacksonDBCollection<Blog, String> collection; public IndexResource(JacksonDBCollection<Blog, String> blogs) { this.collection = blogs; } @GET @Timed public List<Blog> index() { DBCursor<Blog> dbCursor = collection.find(); List<Blog> blogs = new ArrayList<Blog>(); while (dbCursor.hasNext()) { Blog blog = dbCursor.next(); blogs.add(blog); } return blogs; } }
create src/main/java/com/example/myblog/resources/BlogResource.java:
package com.example.myblog.resources; import java.util.ArrayList; import java.util.List; import javax.validation.Valid; import javax.ws.rs.Consumes; 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 javax.ws.rs.core.Response; import net.vz.mongodb.jackson.DBCursor; import net.vz.mongodb.jackson.JacksonDBCollection; import com.example.myblog.core.Blog; import com.codahale.metrics.annotation.Timed; @Path("/blogs") @Produces(value = MediaType.APPLICATION_JSON) @Consumes(value = MediaType.APPLICATION_JSON) public class BlogResource { private JacksonDBCollection<Blog, String> collection; public BlogResource(JacksonDBCollection<Blog, String> blogs) { this.collection = blogs; } @GET @Timed public List<Blog> blogsTimeLine() { DBCursor<Blog> dbCursor = collection.find(); List<Blog> blogs = new ArrayList<Blog>(); while (dbCursor.hasNext()) { Blog blog = dbCursor.next(); blogs.add(blog); } return blogs; } @POST @Timed public Response publishNewBlog(@Valid Blog blog) { collection.insert(blog); return Response.noContent().build(); } }
update src/main/java/com/example/myblog/MyBlogApplication.java:
package com.example.myblog; import io.dropwizard.Application; import io.dropwizard.setup.Bootstrap; import io.dropwizard.setup.Environment; import com.example.myblog.core.Blog; import com.example.myblog.resources.IndexResource; import com.example.myblog.resources.BlogResource; import com.example.myblog.health.MongoHealthCheck; import com.mongodb.Mongo; import com.mongodb.DB; import net.vz.mongodb.jackson.JacksonDBCollection; public class MyBlogApplication extends Application<MyBlogConfiguration> { public static void main(String[] args) throws Exception { new MyBlogApplication().run(args); } @Override public String getName() { return "my-blog"; } @Override public void initialize(Bootstrap<MyBlogConfiguration> bootstrap) { // nothing to do yet } @Override public void run(MyBlogConfiguration configuration, Environment environment) throws Exception { Mongo mongo = new Mongo(configuration.getMongoHost(), configuration.getMongoPort()); MongoManaged mongoManaged = new MongoManaged(mongo); environment.lifecycle().manage(mongoManaged); final MongoHealthCheck mongoHealthCheck = new MongoHealthCheck(mongo); environment.healthChecks().register("mongo", mongoHealthCheck); DB db = mongo.getDB(configuration.getMongoDb()); JacksonDBCollection<Blog, String> blogs = JacksonDBCollection.wrap(db.getCollection("blogs"), Blog.class, String.class); final IndexResource indexResource = new IndexResource(blogs); environment.jersey().register(indexResource); final BlogResource blogResource = new BlogResource(blogs); environment.jersey().register(blogResource); } }
% git add src/main/java/com/example/myblog/MyBlogApplication.java % git add src/main/java/com/example/myblog/core/Blog.java % git add src/main/java/com/example/myblog/resources/BlogResource.java % git commit -m 'use mongoDB'
curl -i -X POST -H "Content-Type: application/json" -d '{"title":"getting started dropwizard 0.7.0 part2","url":"http://okamuuu.hatenablog.com/entry/2014/11/12/145356"}' http://localhost:8080/blogs HTTP/1.1 204 No Content Date: Sun, 16 Nov 2014 03:53:20 GMT Content-Type: application/json
% curl http://localhost:8080 [{"id":"5467c915300414290c4253a6","title":"getting started dropwizard 0.7.0","url":"http://okamuuu.hatenablog.com/entry/2014/11/06/192836","publishedOn":1416087829129},{"id":"54681fb0300467ec3b406434","title":"getting started dropwizard 0.7.0 part2","url":"http://okamuuu.hatenablog.com/entry/2014/11/12/145356","publishedOn":1416110000144}]
% curl http://localhost:8080/blogs [{"id":"5467c915300414290c4253a6","title":"getting started dropwizard 0.7.0","url":"http://okamuuu.hatenablog.com/entry/2014/11/06/192836","publishedOn":1416087829129},{"id":"54681fb0300467ec3b406434","title":"getting started dropwizard 0.7.0 part2","url":"http://okamuuu.hatenablog.com/entry/2014/11/12/145356","publishedOn":1416110000144}]