Slide 1

Slide 1 text

Introduction to DropWizard Dmitry Noranovich (@javaeeeee1) Toronto JUG, 27th of October 2016

Slide 2

Slide 2 text

What is DropWizard ● Includes well-known frameworks like Jersey, Jackson, Hibernate, embedded Jetty HTTP server; ● All parts selected for you - saves time and effort; ● Parts are glued together and tested - tremendous effort; ● Offers some additional code to process HTTP requests, connect to the database, testing; ● Metrics; ● Packaged as a fat jar.

Slide 3

Slide 3 text

Why DropWizard ● Microservices are hot; ● Do we need to abandon what we know and learn something radically new to write microservices? ● Dropwizard relies on the same frameworks that are part of a full profile application server like Glassfish; ● Benefits: production-ready, greate documentation, support via a Google Group; ● Rivals: WildFly Swarm, Payara Micro, KumuluzEE, RestExpress.

Slide 4

Slide 4 text

Getting to know DropWizard ● The site of the project http://www.dropwizard.io/ ● The Git repo https://github.com/dropwizard/dropwizard ● The Google Group for users https://groups.google.com/forum/#!forum/dropwizard-u ser ● The reddit not associated with the team https://www.reddit.com/r/dropwizard ● An Unofficial initializer https://dropwizard-archetype.herokuapp.com/

Slide 5

Slide 5 text

Projects Used for this Demo ● Example project DropWizard 1.0.2 https://github.com/javaeeeee/DropBookmarks ● Example project DropWizard 0.8.2 https://bitbucket.org/dnoranovich/dropbookmarks ● Some code used in today’s presentation https://bitbucket.org/dnoranovich/dropwizard-getting-s tarted

Slide 6

Slide 6 text

Let’s try it ● Build: mvn clean package ● Check configuration: java -jar target/DropBookmarks-1.0-SNAPSHOT.jar check config.yml ● Check DB status: java -jar target/DropBookmarks-1.0-SNAPSHOT.jar db status config.yml ● Migrate: java -jar target/DropBookmarks-1.0-SNAPSHOT.jar db migrate -i TEST config.yml ● Clean DB: java -jar target/DropBookmarks-1.0-SNAPSHOT.jar db drop-all --confirm-delete-everything config.yml

Slide 7

Slide 7 text

Let’s run it ● Run: java -jar target/DropBookmarks-1.0-SNAPSHOT.jar server config.yml ● CURL it: curl -w "\n" 2>/dev/null -k https://localhost:8443/bookmarks -u javaeeeee:p@ssw0rd ● The takeaway: ○ Built a fat jar; ○ Exposed REST API; ○ Used MySQL as DBMS; ○ Used Hibernate to access DB, may use JDBI; ○ The API relies on Hibernate validator; ○ The solution includes tests.

Slide 8

Slide 8 text

Let’s create a project mvn archetype:generate -DgroupId=com.javaeeeee -DartifactId=DWGettingStarted -Dname=DWGettingStarted -Dpackage=com.javaeeeee.dwstart -DarchetypeGroupId=io.dropwizard.archetypes -DarchetypeArtifactId=java-simple -DarchetypeVersion=1.0.2 -DinteractiveMode=false

Slide 9

Slide 9 text

Generated Project Folder \---com.javaeeeee.dwstart | | | DWGettingStartedApplication.java | | | DWGettingStartedConfiguration.java | | | | | +---api | | +---cli | | +---client | | +---core | | +---db | | +---health | | \---resources

Slide 10

Slide 10 text

Hello Resource @Path("/hello") public class HelloResource { @GET @Produces(MediaType.TEXT_PLAIN) public String getGreeting() { return "Hello world!"; }

Slide 11

Slide 11 text

Register Resource in Application public class DWGettingStartedApplication extends Application { @Override public void run(final DWGettingStartedConfiguration configuration, final Environment environment) { environment.jersey().register(new HelloResource());

Slide 12

Slide 12 text

Run ● Build ● Start the Application: java -jar target/DWGettingStarted-1.0-SNAPSHOT.jar server config.yml ● Check that it’s running: http://localhost:8081/ ● CURL it: curl localhost:8080/hello 2>/dev/null -H '{Content-Type: text/plain}' ● Or use browser, Postman

Slide 13

Slide 13 text

Test public class HelloResourceTest { @Rule public ResourceTestRule resource = ResourceTestRule.builder() .addResource(new HelloResource()).build(); @Test public void testGetGreeting() { actual = resource.client() .target("http://localhost:8080/hello") .request(MediaType.TEXT_PLAIN) .get(String.class); assertEquals(expected, actual);

Slide 14

Slide 14 text

Configuration # config.yml --- # User login. login: javaeeeee # User password. password: crimson

Slide 15

Slide 15 text

Configuration continued... public class DWGettingStartedConfiguration extends Configuration { @NotEmpty private String login; @JsonProperty public String getLogin() { return login; }

Slide 16

Slide 16 text

Basic Authentication public class GreetingAuthenticator implements Authenticator { @Override public Optional authenticate(BasicCredentials credentials) throws AuthenticationException { if (password.equals(credentials.getPassword()) && login.equals(credentials.getUsername())) { return Optional.of(new User()); } else { return Optional.empty(); }

Slide 17

Slide 17 text

Register in Application class @Override public void run( … ) { environment.jersey().register(new AuthDynamicFeature( new BasicCredentialAuthFilter.Builder() .setAuthenticator(new GreetingAuthenticator(configuration.getLogin(), configuration.getPassword())) .setRealm("SECURITY REALM") .buildAuthFilter()));

Slide 18

Slide 18 text

Secure a method @GET @Produces(MediaType.TEXT_PLAIN) public String getGreeting(@Auth User user) { return "Hello world!"; }

Slide 19

Slide 19 text

Integration testing public class IntegrationTest { @ClassRule public static final DropwizardAppRule RULE = new DropwizardAppRule<>(DWGettingStartedApplication.class, "config.yml"); @Test public void testGetGreeting() { String actual = client .target("http://localhost:8080/secured_hello") .request(MediaType.TEXT_PLAIN) .get(String.class); assertEquals(expected, actual);

Slide 20

Slide 20 text

Connect to DB (Hibernate) ● Create JPA @Entity(s) (and JPQL queries); ● Class io.dropwizard.hibernate.AbstractDAO ● Methods: ○ Query namedQuery(String queryName); ○ E uniqueResult(Query query); ○ List list(Query query); ○ E get(Serializable id); ○ E persist(E entity); ○ Overloaded for Criteria.

Slide 21

Slide 21 text

Create your DAOs public class EmployeeDAO extends AbstractDAO { public List findAll() { return list(namedQuery("Employee.findAll")); } ….

Slide 22

Slide 22 text

Boilerplate ● Add Hibernate module and DB driver to pom.xml; ● Create and register Hibernate bundle in the Application class; Pass comma-separated list of entity classes; ● Create DAOs in the Application class; ● Pass them to the resource classes; ● More in the code of the example applications.

Slide 23

Slide 23 text

Use DAOs in Resource Classes @GET @Path("/{id}") @UnitOfWork public Optional findById(@PathParam("id") LongParam id) { return employeeDAO.findById(id.get()); }

Slide 24

Slide 24 text

Database Migrations ● Liquibase included; ● FlyWay possible as a third-party module; ● Necessary to add migrations module to the pom.xml file; ● Necessary to create and register migrations bundle in the Application class; ● Can be used by supplying arguments to the jar file; ● For development purposes it’s better to add migrations Maven plugin.

Slide 25

Slide 25 text

Database Migrations (Liquibase) A script to create a bookmarks table

Slide 26

Slide 26 text

More in the example projects ● Testing resources using Mockito; ● Testing DAOs using an in-memory DB; ● Enabling HTTPS; ● Integration testing of password protected resources and HTTPS; ● Authentication using DB; ● Password encryption.

Slide 27

Slide 27 text

Not covered and TODOs... ● Authorization; ● Metrics; ● Dependency Injection Frameworks; ● HTML Representations; ● LDAP Authentication.

Slide 28

Slide 28 text

Conclusion and Thanks The bottom line is that DropWizard is a production-ready framework which relies on well-known to Java EE developers parts and offer some goodies that can expedite REST API development and testing. Thank you for listening! :)