Slide 1

Slide 1 text

RESTful Groovy Options for building a Services Oriented Architecture in Groovy Kyle Boon

Slide 2

Slide 2 text

Technical Lead @ Bloomhealth [email protected] @kyleboon http://www.kyleboon.org Kyle Boon

Slide 3

Slide 3 text

Architecture 2011

Slide 4

Slide 4 text

Architecture 2012

Slide 5

Slide 5 text

Architecture 2013

Slide 6

Slide 6 text

Goals Separate components Allow for different SLAs for each component Be able to combine components in different ways Increase developer productivity and ownership

Slide 7

Slide 7 text

Complete Tool Chain Groovy Grails for web applications Dropwizard for JSON web services Gradle for builds Swagger for Service Discovery Spock for testing Gatling for Performace/Load Testing Redis for Caching RabbitMQ for messaging Chef for infrastructure

Slide 8

Slide 8 text

What is Dropwizard Dropwizard is a heavily opinionated framework for building web services on the JVM. It is mostly glue around mature java libraries like Jetty, Jersey, Jackson and Guava. Dropwizard has out­of­the­box support for sophisticated configuration, application metrics, logging, operational tools, and much more, allowing you and your team to ship a production­quality HTTP+JSON web service in the shortest time possible.

Slide 9

Slide 9 text

@coda As I've said before, the only reason Dropwizard exists at all is to provide opinions on what a service should be. It uses fat JARs because I think they work better. It embeds Jetty because I think that works better. It uses Jackson because I think that works better. It uses Jersey because I think that works better. It has a single YAML configuration file because I think that works better. It wraps Logback because I think that works better. Who Created it?

Slide 10

Slide 10 text

How does it work? Deployed as a fat jar and starts jetty. No need for a container. Start the server from the command line by running: p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g s ) t h r o w s E x c e p t i o n { n e w C o n t a c t s S e r v i c e ( ) . r u n ( a r g s ) } j a v a - j a r c o n t a c t _ d r o p w i z a r d - s h a d o w - 0 . 1 . 0 - S N A P S H O T . j a r s e r v e r s t a r t d e v _ c o n f i g . y m l

Slide 11

Slide 11 text

The Service Services are a collection of bundles, commands, healthchecks, tasks and resources. The service class defines all of the abilities of your application. @ O v e r r i d e p u b l i c v o i d i n i t i a l i z e ( B o o t s t r a p b o o t s t r a p ) { b o o t s t r a p . n a m e = ' c o n f i g u r a t i o n _ s e r v i c e ' b o o t s t r a p . a d d B u n d l e m i g r a t i o n s B u n d l e b o o t s t r a p . a d d B u n d l e h i b e r n a t e B u n d l e b o o t s t r a p . a d d B u n d l e ( n e w A s s e t s B u n d l e ( ' / s w a g g e r - u i - 1 . 1 . 0 / ' , ' / s w a g g e r ' ) ) b o o t s t r a p . a d d C o m m a n d ( n e w m i g r a t i o n s C o m m a n d ( ) ) } @ O v e r r i d e p u b l i c v o i d r u n ( C o n t a c t s C o n f i g u r a t i o n c o n f i g u r a t i o n , E n v i r o n m e n t e n v i r o n m e n t ) t h r o w s C l a s s N o t F o u n d E x c e p t i o n { C o n t a c t D A O c o n t a c t D A O = n e w C o n t a c t D A O ( h i b e r n a t e B u n d l e . s e s s i o n F a c t o r y ) e n v i r o n m e n t . a d d R e s o u r c e ( n e w C o n t a c t R e s o u r c e ( c o n t a c t D A O ) ) }

Slide 12

Slide 12 text

The Resource Resources model what is exposed via your RESTful API. Dropwizard uses Jersey for this so these classes are mostly jersey annotations. @ P a t h ( ' / c o n t a c t s ' ) @ P r o d u c e s ( M e d i a T y p e . A P P L I C A T I O N _ J S O N ) c l a s s C o n t a c t R e s o u r c e { p r i v a t e f i n a l C o n t a c t D A O c o n t a c t D A O p u b l i c C o n t a c t R e s o u r c e ( C o n t a c t D A O c o n t a c t D A O ) { t h i s . c o n t a c t D A O = c o n t a c t D A O } @ T i m e d ( n a m e = ' c r e a t e C o n t a c t ' ) @ P O S T @ U n i t O f W o r k p u b l i c C o n t a c t c r e a t e C o n t a c t ( @ V a l i d C o n t a c t c o n t a c t ) { r e t u r n c o n t a c t D A O . s a v e O r U p d a t e ( c o n t a c t ) } }

Slide 13

Slide 13 text

The Representation Your POGOs will be turned into JSON via Jackson. Hibernate Validator lets you specify validation rules. @ T o S t r i n g @ E q u a l s A n d H a s h C o d e c l a s s C o n t a c t { @ J s o n P r o p e r t y L o n g i d @ N o t N u l l @ N o t E m p t y @ J s o n P r o p e r t y S t r i n g f i r s t N a m e @ N o t N u l l @ N o t E m p t y @ J s o n P r o p e r t y S t r i n g l a s t N a m e @ T r a n s i e n t @ J s o n I g n o r e d e f s o m e C r a p = f a l s e }

Slide 14

Slide 14 text

Metrics Yammer Metrics is built in and provides metrics over an administration port (8081). Resources can be annotated with @ T i m e d or @ M e t e r e d , and @ E x c e p t i o n M e t e r e d . " p o s t - r e q u e s t s " : { " t y p e " : " t i m e r " , " d u r a t i o n " : { " u n i t " : " m i l l i s e c o n d s " , " m i n " : 0 . 0 , " m a x " : 0 . 0 , " m e a n " : 0 . 0 , " s t d _ d e v " : 0 . 0 , " m e d i a n " : 0 . 0 , " p 7 5 " : 0 . 0 , " p 9 5 " : 0 . 0 , " p 9 8 " : 0 . 0 , " p 9 9 " : 0 . 0 , " p 9 9 9 " : 0 . 0 } , " r a t e " : { " u n i t " : " s e c o n d s " , " c o u n t " : 0 , " m e a n " : 0 . 0 , " m 1 " : 0 . 0 , " m 5 " : 0 . 0 , " m 1 5 " : 0 . 0 } }

Slide 15

Slide 15 text

Health Checks Health Checks are a method to make sure the infrastructure your service depends on are all running. They are accessible on the administration port. p u b l i c c l a s s R e d i s H e a l t h C h e c k e x t e n d s H e a l t h C h e c k { p r i v a t e s t a t i c f i n a l S t r i n g E C H O = ' c h e c k i n g ' p r i v a t e f i n a l J e d i s P o o l j e d i s P o o l p u b l i c R e d i s H e a l t h C h e c k ( J e d i s P o o l j e d i s P o o l ) { s u p e r ( ' r e d i s ' ) t h i s . j e d i s P o o l = j e d i s P o o l } @ O v e r r i d e p r o t e c t e d R e s u l t c h e c k ( ) t h r o w s E x c e p t i o n { i f ( E C H O . e q u a l s I g n o r e C a s e ( j e d i s P o o l . r e s o u r c e . e c h o ( E C H O ) ) ) { r e t u r n R e s u l t . h e a l t h y ( ) } r e t u r n R e s u l t . u n h e a l t h y ( ' M a n a g e d J e d i s P o o l c o n n e c t i v i t y i s d o w n ! ' ) } }

Slide 16

Slide 16 text

Bundles Bundles are reusable blocks of behaviour designed to be reused across services. Assets, Hibernate and Liquibase are all implemented as Dropwizard Bundles. @ S l f 4 j a b s t r a c t c l a s s R e d i s B u n d l e i m p l e m e n t s C o n f i g u r e d B u n d l e { M a n a g e d J e d i s P o o l j e d i s P o o l a b s t r a c t R e d i s C o n f i g u r a t i o n g e t R e d i s C o n f i g u r a t i o n ( T c o n f i g u r a t i o n ) @ O v e r r i d e p u b l i c f i n a l v o i d i n i t i a l i z e ( B o o t s t r a p b o o t s t r a p ) { l o g . i n f o ( ' I n i t i a l i z i n g R e d i s B u n d l e ' ) } @ O v e r r i d e p u b l i c f i n a l v o i d r u n ( T c o n f i g u r a t i o n , E n v i r o n m e n t e n v i r o n m e n t ) t h r o w s E x c e p t i o n { j e d i s P o o l = n e w M a n a g e d J e d i s P o o l ( n e w J e d i s P o o l C o n f i g ( ) , g e t R e d i s C o n f i g u r a t i o n ( c o n f i g u r a t i o n ) . h o s t , g e t R e d i s C o n f i g u r a t i o n ( c o n f i g u r a t i o n ) . p o r t , g e t R e d i s C o n f i g u r a t i o n ( c o n f i g u r a t i o n ) . t i m e o u t , g e t R e d i s C o n f i g u r a t i o n ( c o n f i g u r a t i o n ) . d b ) e n v i r o n m e n t . m a n a g e ( j e d i s P o o l ) e n v i r o n m e n t . a d d H e a l t h C h e c k ( n e w R e d i s H e a l t h C h e c k ( j e d i s P o o l ) ) } }

Slide 17

Slide 17 text

Commands Commands add options to the command line interface of your service. For example the server starts based on the 'server' command. Migrations run based on the 'db migrate' command. You might add your own command for running functional tests or seeding the database.

Slide 18

Slide 18 text

Tasks Tasks are run time actions available over the administration port. Dropwizard ships with a garbage collection task. You might want to right a task to clean a cache by key. c l a s s F l u s h R e d i s T a s k e x t e n d s T a s k { M a n a g e d J e d i s P o o l m a n a g e d J e d i s P o o l p r o t e c t e d F l u s h R e d i s T a s k ( S t r i n g n a m e , M a n a g e d J e d i s P o o l m a n a g e d J e d i s P o o l ) { s u p e r ( n a m e ) t h i s . m a n a g e d J e d i s P o o l = m a n a g e d J e d i s P o o l } @ O v e r r i d e v o i d e x e c u t e ( M a p p a r a m e t e r s , P r i n t W r i t e r o u t p u t ) t h r o w s E x c e p t i o n { J e d i s j e d i s = m a n a g e d J e d i s P o o l . r e s o u r c e j e d i s . f l u s h D B ( ) } }

Slide 19

Slide 19 text

Other Stuff Configuration Logging Hibernate/JDBI Clients Authentication Views

Slide 20

Slide 20 text

Grails 2.3 New REST APIs, making it easy to build REST APIs in Grails Scaffolding plugin that can generate REST controllers and Async controllers

Slide 21

Slide 21 text

Declaring the resource as part of the domain p a c k a g e g r a i l s . e x a m p l e i m p o r t g r a i l s . r e s t . * @ R e s o u r c e ( u r i = ' / c o n t a c t s ' , f o r m a t s = [ ' j s o n ' , ' x m l ' ] ) c l a s s C o n t a c t { S t r i n g f i r s t N a m e S t r i n g l a s t N a m e S t r i n g j o b T i t l e S t r i n g p h o n e N u m b e r A d d r e s s a d d r e s s s t a t i c c o n s t r a i n t s = { } }

Slide 22

Slide 22 text

Declaring the resource in UrlMappings.groovy or or " / c o n t a c t s " ( r e s o u r c e s : ' c o n t a c t ' ) " / c o n t a c t s " ( r e s o u r c e s : ' c o n t a c t ' , e x c l u d e : [ ' d e l e t e ' ] ) " / c o n t a c t s " ( r e s o u r c e s : ' c o n t a c t ' , i n c l u d e : [ ' i n d e x ' , ' s h o w ' ] )

Slide 23

Slide 23 text

Default URL patterns HTTP Method URI Grails Action GET /contacts index GET /contacts/create create POST /contacts save GET /contacts/${id} show GET /contacts/${id}/edit edit PUT /contacts/${id} update DELETE /contacts/${id} delete

Slide 24

Slide 24 text

Nested Resources " / c o n t a c t s " ( r e s o u r c e s : ' c o n t a c t ' ) { " / a d d r e s s e s " ( r e s o u r c e s : " a d d r e s s " ) }

Slide 25

Slide 25 text

Default Nested Resrouce URL patterns HTTP Method URI Grails Action GET /contacts/{$id}/addresses index GET /contacts/{$id}/addresses/create create POST /contacts/{$id}/addresses save GET /contacts/{$id}/addresses/${id} show GET /contacts/{$id}/addresses/${id}/edit edit PUT /contacts/{$id}/addresses/${id} update DELETE /contacts/{id}/addresses/${id} delete

Slide 26

Slide 26 text

Versioning APIs or " / c o n t a c t s / v 1 " ( r e s o u r c e s : " c o n t a c t " , n a m e s p a c e : ' v 1 ' ) " / c o n t a c t s / v 2 " ( r e s o u r c e s : " c o n t a c t s " , n a m e s p a c e : ' v 2 ' ) " / b o o k s " ( v e r s i o n : ' 1 . 0 ' , r e s o u r c e s : " b o o k " , n a m e s p a c e : ' v 1 ' ) " / b o o k s " ( v e r s i o n : ' 2 . 0 ' , r e s o u r c e s : " b o o k " , n a m e s p a c e : ' v 2 ' )

Slide 27

Slide 27 text

More options Using the RestController super class Implementing a REST controller from scratch Using a generated REST controller form the scaffold plugin

Slide 28

Slide 28 text

Hypermedia as the Engine of Application State Allows the idea of a 'uniform interface' for REST. Services are self documenting and describing in the sense that each resource gives the clients the links necessary to change the state of that resource.

Slide 29

Slide 29 text

JSON+HAL example H T T P / 1 . 1 2 0 0 O K S e r v e r : A p a c h e - C o y o t e / 1 . 1 C o n t e n t - T y p e : a p p l i c a t i o n / v n d . b o o k s . o r g . b o o k + j s o n ; c h a r s e t = I S O - 8 8 5 9 - 1 { " _ l i n k s " : { " s e l f " : { " h r e f " : " h t t p : / / l o c a l h o s t : 8 0 8 0 / m y a p p / b o o k s / 1 " , " h r e f l a n g " : " e n " , " t y p e " : " a p p l i c a t i o n / v n d . b o o k s . o r g . b o o k + j s o n " } " p u b l i s h e r " : { " h r e f " : " h t t p : / / l o c a l h o s t : 8 0 8 0 / m y a p p / b o o k s / 1 / p u b l i s h e r " , " h r e f l a n g " : " e n " } } , " t i t l e " : " " T h e S t a n d " " }

Slide 30

Slide 30 text

Custom MIME types i m p o r t g r a i l s . r e s t . r e n d e r . h a l . * b e a n s = { h a l C o n t a c t R e n d e r e r ( H a l J s o n R e n d e r e r , g r a i l s . e x a m p l e . C o n t a c t ) } g r a i l s . m i m e . t y p e s = [ a l l : " * / * " , b o o k : " a p p l i c a t i o n / v n d . b o o k s . o r g . b o o k + j s o n " , b o o k L i s t : " a p p l i c a t i o n / v n d . b o o k s . o r g . b o o k l i s t + j s o n " , … ] i m p o r t g r a i l s . r e s t . r e n d e r . h a l . * i m p o r t o r g . c o d e h a u s . g r o o v y . g r a i l s . w e b . m i m e . * b e a n s = { h a l B o o k R e n d e r e r ( H a l J s o n R e n d e r e r , r e s t . t e s t . B o o k , n e w M i m e T y p e ( " a p p l i c a t i o n / v n d . b o o k s . o r g . b o o k + j s o n " , [ v : " 1 . 0 " h a l B o o k L i s t R e n d e r e r ( H a l J s o n C o l l e c t i o n R e n d e r e r , r e s t . t e s t . B o o k , n e w M i m e T y p e ( " a p p l i c a t i o n / v n d . b o o k s . o r g . b o o k l i s t + j s o n " }

Slide 31

Slide 31 text

Non REST stuff in 2.3 Changed resolver from ivy to maven Declarative transaction declaration Forked execution mode for speedier test Hibernate 4

Slide 32

Slide 32 text

Metrics gathering No metrics collection by default for grails applications Yammer Metrics Plugin New Relic Custom code

Slide 33

Slide 33 text

Dropwizard Main Benefits Dead simple deployments Built in metrics collection Smaller than grails No Spring More choices made for you

Slide 34

Slide 34 text

Grails Main Benefits Great Community Large Library of Plugins Less opiniated More Conventions Supports HATEOAS and XML

Slide 35

Slide 35 text

Conclusion There is no spoon.

Slide 36

Slide 36 text

References Dropwizard User Guide Dropwizard User Group https://github.com/codahale/dropwizard Presentation about Dropwizard @ Yammer Presentation about Dropwizard @ Simple Coda Hale and Metrics Coda Hale and the Programming Ape Grails 2.3 REST improvements

Slide 37

Slide 37 text

Code we've Looked at Presentation and Example Code Swagger Enhanced Groovy Doc swagger­jaxrs­doclet

Slide 38

Slide 38 text

Thanks A special thanks to the people who actually figured all this stuff out. Including but not limited to: Chad Small Sairam Rekapalli Ryley Gahagan Charlie Knudsen John Engelman

Slide 39

Slide 39 text

Technical Lead @ Bloomhealth [email protected] @kyleboon http://www.kyleboon.org Kyle Boon