microservices to-go mit dropwizardmicroservices to-go mit dropwizard java forum stuttgart 2017 mario...

37
Microservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG [email protected]

Upload: others

Post on 22-May-2020

9 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Microservices To-Gomit Dropwizard

Java Forum Stuttgart 2017

Mario GollerSoftware Engineer, Swisscom AG

[email protected]

Microservices To-Go

Page 2: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Excursion: Architecture Comparison

Monolith: multiple modules in the same container / processMicroservices: Modules running in di!erent processes

Page 3: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

“ Dropwizard is a Java

framework for developing ops-

friendly, high-performance,

RESTful web services

http://www.dropwizard.io/

Page 4: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Created by YammerYammer was migrating IT infrastructure to mircoservices ->common patterns where extracted in one frameworkFirst Release: 2011-12-22 ( )Independent project since 2014 ( )Current Release: Dropwizard 1.1.2

Dropwizard 0.1.0Dropwizard 0.7.0

History

Page 5: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

How the Dropwizard Frameworkcan help us to easily build

microservices ...

Page 6: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

“ Dropwizard ... pulls together stable,

mature libraries from the Java

ecosystem into a simple, light-

weight package that lets you focus on

getting things done

http://www.dropwizard.io/

Page 7: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

for HTTP servin' for REST modelin'

for JSON parsin' and generatin' for loggin'

for validatin' for "gurin' out what your application is

doin' in production and for databasin'

for migratin'

JettyJerseyJacksonLogbackHibernate ValidatorMetrics

JDBI HibernateLiquibase

Dropwizard's Library set

Page 8: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

How to get started ...?

Use existing Maven archetype to generate simple Dropwizard projecthttps://github.com/nicktelford/dropwizard/tree/feature/maven-archetypes

this is setting up the required base implementation (already executable)

mvn archetype:generate -DarchetypeGroupId=io.dropwizard.archetypes -DarchetypeArtifactId=java-simple -DarchetypeVersion=1.1.2

Page 9: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Dropwizard Components Overview

Page 10: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

main() - starts app (Jetty server)initialize() - bundles, con"guration options, etc.run() - register Jersey resources & servlet "lters and more

public class MyApplication extends Application<MyConfiguration> {

public static void main(String[] args) throws Exception { new MyApplication().run(args); }

@Override public void initialize(Bootstrap<AddressModuleConfiguration> bootstrap) { }

@Override public void run(final AddressModuleConfiguration configuration, final Environment environment) throws Exception { environment.jersey().register(...); environment.lifecycle().manage(...); environment.healthChecks().register(...); environment.admin().addTask(...); }}

Application

Page 11: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

server:applicationContextPath: /myApplication

rootPath: /rest applicationConnectors: - type: http port: 8080 adminConnectors: - type: http port: 8082helloMessage: 'Hello Dropwizard!'logging: level: INFO appenders: - type: console threshold: ALL target: stdout

Configurationpublic class MyConfiguration extends Configuration { @NotBlank private String helloMessage;

public void setCustomSetting(String message) { this.helloMessage = message; }

public String getHelloMessage() { return helloMessage; }}

Con"guration "le (Yaml)##

helloMessage: 'Hello Dropwizard!'logging:

Page 12: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

@Path(value = "/hello")@Produces(MediaType.TEXT_PLAIN)public class HelloResource {

private final MyConfiguration conf;

public HelloResource(MessagesConfiguration conf) { this.conf = conf; }

@GET public String sayHello() { return conf.getHelloMaessage(); }

}

Creating a REST Resource

using "plain" JAX-RS 2.0 to create resources or providers

Page 13: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

How it works together

Page 14: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

public class MyApplication extends Application<MyConfiguration> {

public static void main(String[] args) throws Exception { new MyApplication().run(args); }

@Override public String getName() { return "My application"; }

@Override public void initialize(Bootstrap<AddressModuleConfiguration> bootstrap) { bootstrap.addBundle(new AssetsBundle("/frontend-assets/", "/", "index.html", "frontend-assets")); bootstrap.addBundle(new WeldBundle()); }

@Override public void run(final AddressModuleConfiguration configuration, final Environment environment) throws Exception {

environment.jersey().register(ConstraintViolationExceptionMapper.class); environment.jersey().register(new JsonProcessingExceptionMapper()); environment.jersey().packages("org.jfs.dw.rest");

environment.servlets().addFilter("MdcLoggingServletFilter",MdcLoggingServletFilter.class) .addMappingForUrlPatterns(of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.ASYNC), false, "/*"); environment.servlets().addServletListeners(new RequestResponseHolderListener()); }}

Full Application Class Example

Page 15: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <configuration> <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>org.jfs.dw.MyApplication</mainClass> </transformer> </transformers> </configuration> </execution> </executions></plugin>

Build the Application Fat Jar with Maven

$ mvn package

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <configuration> <rules> <DependencyConvergence/> </rules> </configuration> <executions> <execution> <id>enforce</id> <configuration> <rules> <DependencyConvergence/> </rules> </configuration> <goals> <goal>enforce</goal> </goals> <phase>package</phase> </execution> </executions> </plugin>

Use also maven enforcer plugin !

Page 16: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

java -jar myApplication.jar server myConfig.yaml

INFO org.eclipse.jetty.util.log - Logging initialized @1780msINFO io.dropwizard.server.DefaultServerFactory - Registering jersey handler with root path prefix: /myappINFO io.dropwizard.server.DefaultServerFactory - Registering admin handler with root path prefix: /INFO io.dropwizard.assets.AssetsBundle - Registering AssetBundle with name: frontend-assets for path /*INFO io.dropwizard.server.DefaultServerFactory - Registering jersey handler with root path prefix: /myappINFO io.dropwizard.server.DefaultServerFactory - Registering admin handler with root path prefix: /INFO io.dropwizard.server.ServerFactory - Starting My fancy Application

INFO org.eclipse.jetty.setuid.SetUIDListener - Opened application@4905c46b{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}INFO org.eclipse.jetty.setuid.SetUIDListener - Opened application@17ae7628{SSL,[ssl, http/1.1]}{0.0.0.0:8443}INFO org.eclipse.jetty.setuid.SetUIDListener - Opened admin@1136b469{HTTP/1.1,[http/1.1]}{0.0.0.0:8082}INFO org.eclipse.jetty.setuid.SetUIDListener - Opened admin@6579c3d9{SSL,[ssl, http/1.1]}{0.0.0.0:8444}INFO org.eclipse.jetty.server.Server - jetty-9.3.9.v20160517INFO org.eclipse.jetty.server.handler.ContextHandler - Started i.d.j.MutableServletContextHandler@7a364e1c{/,null,AVAILABLE}INFO org.eclipse.jetty.server.AbstractConnector - Started application@4905c46b{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}INFO org.eclipse.jetty.server.AbstractConnector - Started application@17ae7628{SSL,[ssl, http/1.1]}{0.0.0.0:8443}INFO org.eclipse.jetty.server.AbstractConnector - Started admin@1136b469{HTTP/1.1,[http/1.1]}{0.0.0.0:8082}INFO org.eclipse.jetty.server.AbstractConnector - Started admin@6579c3d9{SSL,[ssl, http/1.1]}{0.0.0.0:8444}

Running the Application Jar

Two arguments are needed in order to run the JAR“server” which instructs Dropwizard to run as server.path to YAML con"guration "le.

Page 17: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Bundles

reusable group of functionality, used to de"ne blocks of anapplication’s behavior

public interface Bundle { void initialize(Bootstrap<?> bootstrap); void run(Environment environment);}

public interface ConfiguredBundle<T> { void initialize(Bootstrap<?> bootstrap); void run(T configuration, Environment environment) throws Exception;}

@Overridepublic void initialize(final Bootstrap<BeachBarClientConfiguration> bootstrap) { VersionSupplier supplier = new MavenVersionSupplier("org.jfs.dw", "my-appication"); bootstrap.addBundle(new VersionBundle(supplier));}

Page 18: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Using Databases

you can chose your preferred API:Hibernate ORMJDBI Data Access

#DataSource con"guration via YAML

database: driverClass : org.postgresql.Driver url: 'jdbc:postgresql://db.example.com/db-prod' user: pg-user password: iAMs00perSecrEET

Page 19: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

JDBI

the "dropwizard-jdbi" module allows us to create a databaseconnections and Data Access Objects (DAO) through which we willquery the databasemaking use of the API provided by the JDBI project ( )

Example:

http://jdbi.org/

@Overridepublic void run(ExampleConfiguration config, Environment environment) { final DBIFactory factory = new DBIFactory(); final DBI jdbi = factory.build(environment, config.getDataSourceFactory(), "postgresql"); final UserDAO dao = jdbi.onDemand(UserDAO.class); environment.jersey().register(new UserResource(dao));}

public interface UserDAO {

@SqlUpdate("insert into users (sessionid, name) values (:sessionId, :name)") @GetGeneratedKeys int insert(@Bind("sessionId") String sessionId, @Bind("name") String name);

@MapResultAsBean @SqlQuery("select * from users") List<User> getAllUsers();}

Page 20: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Managed Objects (Example MongoDB)

public class App extends Application<AppConfiguration> {

@Override public void run(AppConfiguration config, Environment environment) { ManagedMongoClient mongoClient = config.getMongo().build(); environment.lifecycle().manage(mongoClient); DB db = mongoClient.getDB(config.getMongo().getDbName()); } }

public class ManagedMongoClient extends MongoClient implements Managed {

public ManagedMongoClient(MongoClientURI uri) throws UnknownHostException { super(uri); }

@Override public void start() throws Exception { }

@Override public void stop() throws Exception { close(); }

}

Page 21: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Operations friendly

HealthchecksCommands (executable actions via CL)Tasks (executable actions via HTTP)Metrics (via )Easy con"gurable Logging (Logback,SLF4J)

Dropwizard Metrics

Dropwizard provides some handy features to support operational work

Page 22: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Application Healthchecks

Page 23: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Healthchecks

a runtime test which you can use to verify your application’sbehaviour, depencencies etc. in its environmentHealth checks should lightly test service dependencies, e.g.databases, downstream services, etc.

$ curl http://dw.example.com:8081/healthcheck

{"deadlocks":{"healthy":true},"database":{"healthy":true}}

Page 24: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

public class DatabaseHealthCheck extends HealthCheck {

private final HibernateBundle hibernate; public DatabaseHealthCheck(HibernateBundle hibernate) { super("database"); this.hibernate = hibernate; } @Override protected Result check() throws Exception { if(!hibernate.getSessionFactory().isClosed()) { return Result.healthy(); } else { return Result.unhealthy("Cannot connect to database"); } }}

Healthcheck Class Example

environment.addHealthCheck(new DatabaseHealthCheck(hibernate));

adding the healthcheck to the application

Page 25: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Deployment into the Cloud

Example of deploying a Dropwizard App to theHeroku Cloud

web: java $JAVA_OPTS -Ddw.http.port=$PORT -Ddw.http.adminPort=$PORT -jar target/myproject-1.0-SNAPSHOT.jar server config.yaml

heroku create

git push heroku master

-----> Discovering process types Procfile declares types -> web-----> Compiled slug size: 57.7MB-----> Launching... done, v9 http://myproject.herokuapp.com deployed to Heroku

Page 26: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Metrics

http://metrics.dropwizard.io

almost all applications need the ability to report key statisticsmetrics library written by Dropwizard teamsupports Meters, Gauges, Histograms, and Timers

Page 27: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Monitoring a Dropwizard Application(visualize pushed metrics)

Page 28: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

"dropwizard-testing" module can be easily used for testingyour application representation classes and resource classesFixtures for unit testing representationsEasily unit test resources using mock DAOsExcellent integration test support…Prefer AssertJ $uent-assertionsJUnit rule for full-stack testing of your entire app

!ResourceTestRule

DropwizardClientRule

DropwizardAppRule

DropwizardTestSupport

Testing a Dropwizard Application

Page 29: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

public class HelloResourceTest {

@Rule public ResourceTestRule resource = ResourceTestRule.builder() .addResource(new HelloResource()).build();

@Test public void testGetGreeting() { String expected = "Hello world!"; //Obtain client from @Rule. Client client = resource.client(); //Get WebTarget from client using URI of root resource. WebTarget helloTarget = client.target("http://localhost:8080/hello"); //To invoke response we use Invocation.Builder //and specify the media type of representation asked from resource. Invocation.Builder builder = helloTarget.request(MediaType.TEXT_PLAIN); //Obtain response. Response response = builder.get();

//Do assertions. assertEquals(Response.Status.OK, response.getStatusInfo()); String actual = response.readEntity(String.class); assertEquals(expected, actual);

}}

Integration Test Example

Page 30: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Dropwizard vs. Spring Boot

Main di!erence is dependency injection supportSpring’s core comes with it’s built in dependency injection supportDropwizard doesn’t come out of the box with DIDropwizard o!ers integrations with other DI frameworks like Guice, CDI…

both frameworks have a special module for testing including JUnit andMockito dependencies.Spring Boot is a part of Spring ecosystem and suits best for Spring-oriented projectsSpring o!ers broader list of supported services - REST, JMS, Messaging...Dropwizard owns popular metrics library

Page 31: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Dropwizard vs. Spring Boot

Page 32: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Anything else?

Page 33: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Additional Dropwizard Modulesand Tooling

http://modules.dropwizard.io/

https://github.com/Tasktop/dropwizard-tools

Page 34: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Dropwizard and Dependency Injection

only Jersey H2K dependency injection support out-of-the-boxuseful for simple casesfor more features a existing DI framework must be included

Google GuiceWeld CDISpring DI

@Overridepublic void run(ExampleServiceConfiguration conf, Environment env) throws Exception { Injector injector = Guice.createInjector(); env.addResource(injector.getInstance(HelloResource.class));}

an additional "H2K-bridge" is needed to avoid clashes in DI<dependency> <groupId>org.glassfish.hk2</groupId> <artifactId>guice-bridge</artifactId> <version>2.4.0-b31</version></dependency>

Page 35: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Database Migrationwith Liquibase

Validation

View Templates

Authentication

Page 36: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture

Questions

Page 37: Microservices To-Go mit DropwizardMicroservices To-Go mit Dropwizard Java Forum Stuttgart 2017 Mario Goller Software Engineer, Swisscom AG mario.goller@swisscom.com Excursion: Architecture