SlideShare une entreprise Scribd logo
1  sur  75
Télécharger pour lire hors ligne
http://www.ratpack.io
Dan Woods
#ratpack #learningratpack
•  Member of the Ratpack core team
•  Work at Netflix
•  Writing Learning Ratpack for O’Reilly
•  Follow me on Twitter: @danveloper
•  A full-stack, high throughput, non-blocking
web framework
•  Built entirely on Java 8
•  Specialized support for writing apps in Groovy
•  Groovy has come a long way over the last few
years…
•  Static compilation and (optional) compile time type
checking
•  Excellent language for writing concise DSLs
•  DSLs can be statically compiled!
Why Groovy?
•  Groovy’s three compilation modes give
applications a lot of flexibility
•  Parallels Java performance using Invoke Dynamic
or Static Compilation
•  Pick-and-choose static or dynamic, depending on
the use-case!
Why Groovy?
•  Requires Groovy 2.3.6+
•  Utilize advanced static compilation and type
checking features of Groovy, like @DelegatesTo
•  Allows you to define your application structure in a
ratpack.groovy file
Why Groovy?
@GrabResolver(name='netty', root='http://clinker.netty.io/
nexus/content/repositories/snapshots')!
@Grab('io.ratpack:ratpack-groovy:0.9.13-SNAPSHOT')!
!
import static ratpack.groovy.Groovy.ratpack!
!
ratpack {!
handlers {!
handler { !
response.send ”Hello World!"!
}!
}!
}!
Simple Groovy Script*
* @GrabResolver will not be required after 4.1.0-Beta4 is published;
* Ratpack 0.9.13 will be released on Feb 1, 2014
•  There are no plugins in Ratpack, instead the
framework provides functionality through modules
•  Modules are built in Guice*
•  DI is an abstraction in Ratpack, so even though the
framework uses Guice, you don’t have to
*	
  h$ps://github.com/google/guice	
  
•  A set of composable libraries for building
unopinionated, rich web applications
•  Pick-and-choose what aspects of the
framework you want
•  No lock-in to a single way of doing things
•  Emphasis on Performance and Efficiency in both applications
and development experience
•  Hot reloading is available during development time
•  Beautiful development-time error pages
•  Extreme emphasis on developer testing, especially functional
and integration
•  Support for mocking nearly all aspects of the framework
Example of a development-time error:
•  Convention over configuration taken too far
doesn’t let you wire things together
•  Ratpack makes wiring modules a “one-liner”, so
there’s not a lot of work to get new features
integrated
•  Out of the box support for Guice and Spring
(Spring Boot) DI
•  Gradle integration makes building robust
projects easy to do
•  Simple apps can be run entirely through
the Groovy command-line
buildscript {
repositories {
jcenter()
maven { url "http://oss.jfrog.org/oss-snapshot-local" }
maven { url "http://clinker.netty.io/nexus/content/repositories/snapshots" }
}
dependencies {
classpath 'io.ratpack:ratpack-gradle:0.9.13-SNAPSHOT'
}
}
apply plugin: 'io.ratpack.ratpack-java'
Simple Gradle Build Script*
* Ratpack 0.9.13 will be released on Feb 1, 2014
•  Any non-trivial application needs build and
packaging capabilities
•  The Ratpack Gradle plugin provides all the
fixtures to support building web
application projects
•  Ratpack is built on Netty, which provides
the infrastructure for highly performant,
non-blocking networking
•  Netty is an extremely mature, super low-level
networking library
•  Excellent documentation, very involved
community
•  Heavy emphasis on high throughput and
performance
•  Netty provides the infrastructure for non-
blocking networking, but doesn’t help
much in the way of web application
structure
•  Provides an asynchronous API for working
with network data (including HTTP)
•  Computers “think” very good in asynchronous
terms; humans do not…
•  Without app structure, programming toward this
paradigm is difficult
•  Ratpack ensures the most performant structures of
Netty are being utilized, while providing a sensible
app structure and programming model
•  Ratpack provides applications with a Netty-based, non-
blocking HTTP client
•  Can be used to integrate with external RESTful services
•  Utilizes the same event loop as the server, so resources
are appropriately utilized
•  Provides a robust API for programmatically crafting
requests
Above all else…
Ratpack is your
GATEWAY DRUG
to non-blocking
•  The JVM doesn’t have any concept of continuations, so
the only option we have is asynchronous APIs
•  Async APIs allow callers to provide a completion
handler (or callback), which is to be invoked when some
processing has finished
•  There is no temporal relationship between the caller
and the invocation of the callback
handler { req, res ->!
... (1) do some work ...!
!
async {!
... (2) do some async work ...!
}!
async {!
... (3) do some more async ...!
}!
!
... (4) send response ...!
}!
(1)  – Definitely finishes first
(2)  – May finish before or after (3)
and (4)
(3)  – May finish before or after (2) or
(4)
(4)  – May finish before or after (2) or
(3)
Async APIs create non-determinism in control flow
•  The temporal disconnect creates non-determinism
in request processing
•  This is a big problem for web applications, because
they demand a deterministic control flow
•  Ratpack provides the concept of an Execution,
which creates determinism in asynchronous
processing
handler { req, res ->!
... (1) do some work ...!
!
async {!
... (3) do some async work ...!
}!
async {!
... (4) do some more async ...!
}!
!
... (2) send response ...!
}!
(1) – Definitely finishes first
(3) – Definitely finishes third
(4) – Definitely finishes fourth
(2) – Definitely finishes second
Ratpack creates a deterministic control flow
•  Through Ratpack’s promise API, the Execution
is able to schedule async segments to be
invoked after the handler code has finished
•  Promise API ensures that developers can work
with asynchronous processing in a sensible
way
•  In non-blocking, it is of paramount importance
to not block the thread
•  Since a single thread is handling processing
for many clients, blocking one blocks all
•  Need to adopt libraries that are non-blocking
or provide async APIs
•  This is not always practical…
•  Not all interfaces are able to be non-blocking or
asynchronous
•  Most non-blocking frameworks force you to be either
entirely async or wholesale define your handlers as
blocking
•  This is limiting and makes it difficult to work with legacy
APIs or those not crafted for non-blocking work
•  Ratpack gives you a mechanism to define blocking
execution segments in your handler code
handler(r -> (ctx) -> {
ModelDAO dao = ctx.get(ModelDAO.class);
ctx.blocking(() ->
dao.load(ctx.getPathTokens().get("id")))
.then(model -> {
... do some work with the data ...
ctx.render(model);
});
})
Handler with blocking operation
•  Blocking operations are scheduled to an I/O
bound thread pool
•  Once the blocking operation is completed,
the data is then returned to the request taking
thread, where processing can finish
•  Blocking operations are invoked when they
are subscribed to in the request-taking thread
...
ctx.blocking(() -> {
... do some blocking io ...
return result;
}).then(result -> {
... subscribe to the blocking promise ...
... process in the request-taking thread ...
})
...
Blocking with a subscription
•  Data is being delivered to web consumers in
an increasingly real time way
•  Web applications must be able to support
streaming protocols like SSE and WebSockets
•  Ratpack has built-in fixtures that make it easy
to develop real-time web applications
•  Because of its non-blocking nature, Ratpack can
support a high volume of concurrent real-time
streams
•  Valuable in app-to-app communication too, where
a consumer wants to be reactively informed about
some data
•  Ratpack’s HTTP client also supports reading
streams of data from external producers, making
stream processing a great integration
•  Ratpack applications are defined through a
handler chain
•  Handler chain is a programmatic construct
for managing the flow of request data
•  Handlers can be bound to request path
routes and HTTP verbs
import static ratpack.groovy.Groovy.ratpack!
!
ratpack {!
handlers {!
get {!
response.send "I'm the default route!"!
}!
get("route1") {!
response.send "I'm in route1"!
}!
get("route2/:param") {!
response.send "I'm in route2 and received param: ${pathTokens.param}"!
}!
}!
}!
Handler chain in a Ratpack Script-backed app
RatpackServer.start(b -> b

.config(ServerConfig.noBaseDir())

.handlers(chain -> chain

.get(ctx -> ctx.getResponse()

.send("I'm in the default route!"))

!
.get("route1", (ctx) -> ctx.getResponse()

.send("I'm in route1!"))

!
.get("route2/:param", (ctx) -> ctx.getResponse()

.send(String

.format(” received param: %s",

ctx.getPathTokens().get("param"))))

)

);"
Handler chain in using Java 8 APIs
•  Ratpack applications are defined through a
handler chain
•  Handler chain is a programmatic construct
for managing the flow of request data
•  Handlers can be bound to request path
routes and HTTP verbs
handlers {!
get { ... }!
get("route") { ... }!
!
post { ... }!
post("route") { ... }!
!
put { ... }!
put("route") { ... }!
!
delete { ... }!
delete("route") { ... }!
!
patch { ... }!
patch("route") { ... }!
}!
Semantic handler API for binding to HTTP verbs and routes
•  Handlers can be nested within a route…
handlers {

prefix("api") { ModelDAO dao ->

get {

blocking { dao.getAll() }.

then { models -> render JsonOutput.toJson(models) }

}

post {

Model model = parse(fromJson(Model))

blocking { dao.save(model) }.

then { m -> render m }

}

put(":id") {

blocking { dao.load(pathTokens.id) }.

map { model -> model.merge(parse(fromJson(Model))) }.

blockingMap { model -> dao.save(model) }.

then { model -> render model }

}

}

}!
•  There’s a special handler type for serving
static assets from the app’s baseDir!
•  Static assets must be defined as the last
handler in the chain
•  Can be scoped to routes
•  Use the assets handler to serve static content
handlers {

prefix("api") {

get {

response.send "some API data"

}

}

assets("public", "index.html”)

}!
•  You can also use a handler with byMethod to perform common processing
within a route…
handlers {

handler("api") { ModelDAO dao ->

dao.beginTransaction()

byMethod {

get {}

post {}

put {}

delete {}

}

dao.endTransaction()

}!
}!
•  Can discriminate on content type, allowing you to build HyperMedia APIs…
handlers {

handler {

byContent {

json {

response.send(toJson([msg: "regular json"]))

}

xml {

response.send(...)

}

type("application/vnd.app.org+json;v=1") {

response.send(toJson([newmsg: "hypermedia json"]))

}

}

}

}!
•  Handlers define the edge of your application
•  In Servlet API terms, handlers can be thought
of as a marriage between filters and servlets
•  Allows request introspection and
programmatic injection of handler chain
•  This allows handlers to be constructed and dependency injected, etc…
class UserHandler implements Handler {



private final String message



UserHandler(String message) {

this.message = message

}



@Override

void handle(Context context) !
!throws Exception {

context.response.send(message)

}

}!
ratpack {

bindings {

bindInstance(new UserHandler("user handler"))

}

handlers {

handler { UserHandler userHandler ->

if (request!
.headers.contains("X-Routing-Header")) {

def routingHeader = request!
.headers.get("X-Routing-Header")

if (routingHeader == "user") {

insert(userHandler)

}

}

next()

}

get {

response.send "default system handler"

}

}

}!
New	
  Handler	
  is	
  
programma1cally	
  inserted	
  
into	
  the	
  processing	
  chain	
  
•  Dependency injection is an abstraction in
Ratpack, through the concept of a Registry
•  Components are bound to, and resolvable
from, a Registry instance
•  Registries can be backed in a DI framework
•  Out of the box support for Guice and Spring
Boot
•  Registries can be inherited, allowing
components to be resolved in a cascading
manner
•  Every request context gets a registry that
components can be extracted from
•  In a Groovy script that uses closures as
handlers, the variable arguments to that
closure are “injected” from the registry
•  In Java 8, they are able to be resolved from
the request context object
•  You don’t need to use a DI framework to get injection support, you can build
your own registry from objects you construct…
public static void main(String[] args) throws Exception {

Registry registry = Registries.registry()

.add(new ModelDAO()).add(new DB()).build();



RatpackServer.start(spec -> spec

.config(ServerConfig.noBaseDir())

.handlers(chain -> {

chain.register(registry);

chain.handler(":id", ctx -> {

ModelDAO dao = ctx.get(ModelDAO.class);

ctx.blocking(() ->

dao.load(ctx.getPathTokens().get("id")))

.then(ctx::render);

});

})

);

}!
•  Variables arguments to Groovy closure handlers are resolved from the
registry
def myRegistry = Registries.registry()

.add(new ModelDAO())

.build()



ratpack {

handlers {

register(myRegistry)



prefix("api") {

get(":id") { ModelDAO dao ->

render dao.load(pathTokens.id)

}

}

assets("public", "index.html”)

}

}!
•  In Groovy, you get a bindings block, which you can use to bind components
to the Registry. With Guice, annotations can be used to Inject
class UserHandler implements Handler {



private final ModelDAO dao



@javax.inject.Inject!
UserHandler(ModelDAO dao) {

this.message = message

}



@Override

void handle(Context ctx) !
!throws Exception {

ctx.blocking {!
dao.getAll()!
} then { ctx.render(it) }

}

}!
ratpack {

bindings {

binder { b ->

b.bind(ModelDAO).in(Scopes.SINGLETON)

b.bind(UserHandler).in(Scopes.SINGLETON)

}

}!
handlers {

handler { UserHandler userHandler ->

if (request!
.headers.contains("X-Routing-Header")) {

def routingHeader = request!
.headers.get("X-Routing-Header")

if (routingHeader == "user") {

insert(userHandler)

}

}

next()

}

get {

response.send "default system handler"

}

}

}!
Can	
  get	
  a	
  handle	
  on	
  a	
  Guice	
  
binder	
  to	
  perform	
  
annota1on-­‐based	
  Injec1ng	
  
•  Likewise, a Guice Module can be “added” to the registry…
ratpack {

bindings {!
// Any Guice module can be added this way!
// this is how Ratpack modules are"
// introduced... "
add(new SqlModule())

}!
handlers {

...!
}

}!
•  Spring application context can be used to
back a registry using the
ratpack.spring.Spring class
h>p://www.ratpack.io/manual/0.9.13/api/ratpack/spring/Spring.html	
  
	
  
•  Like handlers, registries can be
programmatically registered into the
handler chain based on request data
•  Can allow your app to resolve components
specific to the context of a request
•  Likewise, a Guice Module can be “added” to the registry…
def baseRegistry = Registries.registry()

.add(new ModelDAO("jdbc:mysql://default"))

.build()



def cust1Registry = Registries.registry()

.add(new ModelDAO("jdbc:mysql://cust1"))

.build()



ratpack {

bindings {

bindInstance(new DefaultDevelopmentErrorHandler())

}

handlers {

handler {

next(get(PublicAddress).getAddress(it).host == "cust1" ? cust1Registry : baseRegistry)

}

prefix("api") {

get(":id") { ModelDAO dao ->

render blocking { dao.load(pathTokens.id) }

}

}

assets("public", "index.html”)

}

}!
•  Including framework modules in your
Gradle based project is really easy
•  Can utilize helper methods from the
Ratpack Gradle plugin to include named
modules
•  Allows framework versions to stay in sync
•  The Ratpack Gradle plugin provides the ratpack.dependency() helper
...!
!
dependencies {

compile ratpack.dependency("jackson”)

compile ratpack.dependency(”rxjava”)!
compile ratpack.dependency(”codahale-metrics”)!
testCompile ratpack.dependency(”remote-test”) !
}!
!
...!
•  Including framework modules in your
Gradle based project is really easy
•  Can utilize helper methods from the
Ratpack Gradle plugin to include named
modules
•  Allows framework versions to stay in sync
•  Static fixtures for mapping a multitude of external and environmental configuration
sources to POJOs
Configuration Module: ratpack-config
// build.gradle"
dependencies {!
...

compile ratpack.dependency(”config”)!
...

}!
import ratpack.config.*;!
!
ConfigurationData configData =
Configurations.config()

.yaml(Main.class.getResource("/app.yml"))

.json(Main.class.getResource("/app.json"))

.props("/etc/app/file.properties")

.sysProps()

.env()

.build();!
!
ServerConfig config = configData!
.get("/server", ServerConfig.class);



RatpackServer.start(spec -> spec

.config(config)

.handlers(...)

);!
// classpath:/app.yml"
server:!
port: 8080!
!
myAppStuff:!
anyConfigData: 1234!
•  Environment-derivable configuration
follows the principle of the Twelve Factor
App
Great Support for building MICROSERVICES!!
•  NetflixOSS Hystrix support, via the ratpack-
hystrix module
•  Calls to remote services can be made fault
tolerant
•  Ability to stream Hystrix metrics to the Hystrix
Dashboard
Great Support for building MICROSERVICES!!
•  The ratpack-hikari module uses HikariCP
to create a super fast pooled SQL DataSource
•  Can be used in conjunction with Groovy SQL
to query databases
•  Configurable using the fixtures from the
ratpack-config module
Great Support for DATABASES!!
•  The ratpack-jackson module provides
request data parsing and object rendering
from and to JSON
•  Data can be worked with in free-form nodes,
or bound to command objects
•  Arbitrary models can be rendered as JSON
using simply context.render(obj)!
Great Support for DATA BINDING!!
•  Ratpack’s Promise API is an implementation of
Reactive Streams Specification
•  The ratpack-rxjava module provides a
bridge between a Ratpack Promise and an
RxJava Observable
•  The ratpack-reactor module allows data
to be processed using Project Reactor
Great Support for REACTIVE PROGRAMMING!!
•  View templates can be rendered through a variety
of means
•  Support for server-side templating with
Handlebars, Thymeleaf, Groovy Templates, and
Groovy Markup
•  Ongoing work to integrate @davydotcom’s asset-
pipeline, which will give robust support for all types
of static content
Great Support for FULL-STACK FEATURES!!
•  Ratpack has been built from the ground-up with
testing considered at every turn
•  Even more-so – considering testing from the
perspective of the developer
•  The concept of the Registry gives the framework
control over components
•  Makes it easy to provide fixtures for mocking and
stubbing data
•  The EmbeddedApp class from the ratpack-
test module supports functional and
integration testing
•  Can be used to test an application module
or a subset of handlers and functionality
•  Can be used outside of Ratpack too!
•  Spock is the choice framework, though
there’s no strict integration there
•  Functional tests are easy to bootstrap and
the TestHttpClient helper makes it easy to
programmatically craft test calls
•  Great resource for seeing Ratpack’s testing
in action is the example-books project
•  Rus Hart keeps this up to date with changes
to the framework.
•  https://github.com/ratpack/example-books
Twitter people to follow:!
!
•  @ldaley!
•  @rus_hart!
•  @varzof!
•  @Lspacewalker!
•  @marcinerdmann!
•  @ratpackweb!
•  @davydotcom!
•  @johnrengelman!
•  @rfletcherEW!
•  @beckje01!

Contenu connexe

Tendances

Reactive Applications with Apache Pulsar and Spring Boot
Reactive Applications with Apache Pulsar and Spring BootReactive Applications with Apache Pulsar and Spring Boot
Reactive Applications with Apache Pulsar and Spring BootVMware Tanzu
 
There's more to Ratpack than non-blocking
There's more to Ratpack than non-blockingThere's more to Ratpack than non-blocking
There's more to Ratpack than non-blockingMarcin Erdmann
 
Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012
Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012
Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012kennethaliu
 
Migrating from Grails 2 to Grails 3
Migrating from Grails 2 to Grails 3Migrating from Grails 2 to Grails 3
Migrating from Grails 2 to Grails 3Michael Plöd
 
The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchron...
The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchron...The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchron...
The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchron...VMware Tanzu
 
Aprende, contribuye, y surfea Cloud Native Java - GuateJUG 2021
Aprende, contribuye, y surfea Cloud Native Java - GuateJUG 2021Aprende, contribuye, y surfea Cloud Native Java - GuateJUG 2021
Aprende, contribuye, y surfea Cloud Native Java - GuateJUG 2021César Hernández
 
Spring Boot on Amazon Web Services with Spring Cloud AWS
Spring Boot on Amazon Web Services with Spring Cloud AWSSpring Boot on Amazon Web Services with Spring Cloud AWS
Spring Boot on Amazon Web Services with Spring Cloud AWSVMware Tanzu
 
What’s new in grails framework 5?
What’s new in grails framework 5?What’s new in grails framework 5?
What’s new in grails framework 5?Puneet Behl
 
Hadoop Summit 2013 : Continuous Integration on top of hadoop
Hadoop Summit 2013 : Continuous Integration on top of hadoopHadoop Summit 2013 : Continuous Integration on top of hadoop
Hadoop Summit 2013 : Continuous Integration on top of hadoopWisely chen
 
Gradle - Build system evolved
Gradle - Build system evolvedGradle - Build system evolved
Gradle - Build system evolvedBhagwat Kumar
 
Working with Xcode and Swift Package Manager
Working with Xcode and Swift Package ManagerWorking with Xcode and Swift Package Manager
Working with Xcode and Swift Package ManagerJens Ravens
 
Polygot Java EE on the GraalVM
Polygot Java EE on the GraalVMPolygot Java EE on the GraalVM
Polygot Java EE on the GraalVMRyan Cuprak
 
Gitlab ci, cncf.sk
Gitlab ci, cncf.skGitlab ci, cncf.sk
Gitlab ci, cncf.skJuraj Hantak
 
My "Perfect" Toolchain Setup for Grails Projects
My "Perfect" Toolchain Setup for Grails ProjectsMy "Perfect" Toolchain Setup for Grails Projects
My "Perfect" Toolchain Setup for Grails ProjectsGR8Conf
 
7 recomendaciones para migrar tus aplicaciones a Jakarta EE utilizando Apache...
7 recomendaciones para migrar tus aplicaciones a Jakarta EE utilizando Apache...7 recomendaciones para migrar tus aplicaciones a Jakarta EE utilizando Apache...
7 recomendaciones para migrar tus aplicaciones a Jakarta EE utilizando Apache...César Hernández
 
Modular Java applications with OSGi on Apache Karaf
Modular Java applications with OSGi on Apache KarafModular Java applications with OSGi on Apache Karaf
Modular Java applications with OSGi on Apache KarafIoan Eugen Stan
 

Tendances (20)

Reactive Applications with Apache Pulsar and Spring Boot
Reactive Applications with Apache Pulsar and Spring BootReactive Applications with Apache Pulsar and Spring Boot
Reactive Applications with Apache Pulsar and Spring Boot
 
There's more to Ratpack than non-blocking
There's more to Ratpack than non-blockingThere's more to Ratpack than non-blocking
There's more to Ratpack than non-blocking
 
Gradle
GradleGradle
Gradle
 
Introduction to gradle
Introduction to gradleIntroduction to gradle
Introduction to gradle
 
Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012
Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012
Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012
 
Migrating from Grails 2 to Grails 3
Migrating from Grails 2 to Grails 3Migrating from Grails 2 to Grails 3
Migrating from Grails 2 to Grails 3
 
The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchron...
The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchron...The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchron...
The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchron...
 
Aprende, contribuye, y surfea Cloud Native Java - GuateJUG 2021
Aprende, contribuye, y surfea Cloud Native Java - GuateJUG 2021Aprende, contribuye, y surfea Cloud Native Java - GuateJUG 2021
Aprende, contribuye, y surfea Cloud Native Java - GuateJUG 2021
 
Spring Boot on Amazon Web Services with Spring Cloud AWS
Spring Boot on Amazon Web Services with Spring Cloud AWSSpring Boot on Amazon Web Services with Spring Cloud AWS
Spring Boot on Amazon Web Services with Spring Cloud AWS
 
What’s new in grails framework 5?
What’s new in grails framework 5?What’s new in grails framework 5?
What’s new in grails framework 5?
 
Implementing your own Google App Engine
Implementing your own Google App Engine Implementing your own Google App Engine
Implementing your own Google App Engine
 
Hadoop Summit 2013 : Continuous Integration on top of hadoop
Hadoop Summit 2013 : Continuous Integration on top of hadoopHadoop Summit 2013 : Continuous Integration on top of hadoop
Hadoop Summit 2013 : Continuous Integration on top of hadoop
 
Integration testing dropwizard
Integration testing dropwizardIntegration testing dropwizard
Integration testing dropwizard
 
Gradle - Build system evolved
Gradle - Build system evolvedGradle - Build system evolved
Gradle - Build system evolved
 
Working with Xcode and Swift Package Manager
Working with Xcode and Swift Package ManagerWorking with Xcode and Swift Package Manager
Working with Xcode and Swift Package Manager
 
Polygot Java EE on the GraalVM
Polygot Java EE on the GraalVMPolygot Java EE on the GraalVM
Polygot Java EE on the GraalVM
 
Gitlab ci, cncf.sk
Gitlab ci, cncf.skGitlab ci, cncf.sk
Gitlab ci, cncf.sk
 
My "Perfect" Toolchain Setup for Grails Projects
My "Perfect" Toolchain Setup for Grails ProjectsMy "Perfect" Toolchain Setup for Grails Projects
My "Perfect" Toolchain Setup for Grails Projects
 
7 recomendaciones para migrar tus aplicaciones a Jakarta EE utilizando Apache...
7 recomendaciones para migrar tus aplicaciones a Jakarta EE utilizando Apache...7 recomendaciones para migrar tus aplicaciones a Jakarta EE utilizando Apache...
7 recomendaciones para migrar tus aplicaciones a Jakarta EE utilizando Apache...
 
Modular Java applications with OSGi on Apache Karaf
Modular Java applications with OSGi on Apache KarafModular Java applications with OSGi on Apache Karaf
Modular Java applications with OSGi on Apache Karaf
 

En vedette

Ratpack and Grails 3
Ratpack and Grails 3Ratpack and Grails 3
Ratpack and Grails 3Lari Hotari
 
Usage concurrence in java
Usage concurrence in javaUsage concurrence in java
Usage concurrence in javaAsya Dudnik
 
Managing computational resources with Apache Mesos
Managing computational resources with Apache MesosManaging computational resources with Apache Mesos
Managing computational resources with Apache MesosJackson dos Santos Olveira
 
PC = Personal Cloud (or how to use your development machine with Vagrant and ...
PC = Personal Cloud (or how to use your development machine with Vagrant and ...PC = Personal Cloud (or how to use your development machine with Vagrant and ...
PC = Personal Cloud (or how to use your development machine with Vagrant and ...Codemotion
 
Multithreading in java past and actual
Multithreading in java past and actualMultithreading in java past and actual
Multithreading in java past and actualYevgen Levik
 
Service Oriented UI Architecture in the world of web, desktop, & mobile appli...
Service Oriented UI Architecture in the world of web, desktop, & mobile appli...Service Oriented UI Architecture in the world of web, desktop, & mobile appli...
Service Oriented UI Architecture in the world of web, desktop, & mobile appli...Axway Appcelerator
 
Dejan Pekter / Nordeus – Reactor design pattern
Dejan Pekter / Nordeus – Reactor design patternDejan Pekter / Nordeus – Reactor design pattern
Dejan Pekter / Nordeus – Reactor design patternConversionMeetup
 

En vedette (20)

Forex AutoPilot
Forex AutoPilotForex AutoPilot
Forex AutoPilot
 
Ratpack and Grails 3
Ratpack and Grails 3Ratpack and Grails 3
Ratpack and Grails 3
 
Usage concurrence in java
Usage concurrence in javaUsage concurrence in java
Usage concurrence in java
 
Java threads - part 2
Java threads - part 2Java threads - part 2
Java threads - part 2
 
Java threads - part 3
Java threads - part 3Java threads - part 3
Java threads - part 3
 
Java threads - part 1
Java threads - part 1Java threads - part 1
Java threads - part 1
 
Java 8. Thread pools
Java 8. Thread poolsJava 8. Thread pools
Java 8. Thread pools
 
Managing computational resources with Apache Mesos
Managing computational resources with Apache MesosManaging computational resources with Apache Mesos
Managing computational resources with Apache Mesos
 
Introduction to CFEngine
Introduction to CFEngineIntroduction to CFEngine
Introduction to CFEngine
 
Vagrant
VagrantVagrant
Vagrant
 
Docker cloud
Docker cloudDocker cloud
Docker cloud
 
An introduction to predictionIO
An introduction to predictionIOAn introduction to predictionIO
An introduction to predictionIO
 
Apache mahout - introduction
Apache mahout - introductionApache mahout - introduction
Apache mahout - introduction
 
Docker hub
Docker hubDocker hub
Docker hub
 
PC = Personal Cloud (or how to use your development machine with Vagrant and ...
PC = Personal Cloud (or how to use your development machine with Vagrant and ...PC = Personal Cloud (or how to use your development machine with Vagrant and ...
PC = Personal Cloud (or how to use your development machine with Vagrant and ...
 
Multithreading in java past and actual
Multithreading in java past and actualMultithreading in java past and actual
Multithreading in java past and actual
 
Service Oriented UI Architecture in the world of web, desktop, & mobile appli...
Service Oriented UI Architecture in the world of web, desktop, & mobile appli...Service Oriented UI Architecture in the world of web, desktop, & mobile appli...
Service Oriented UI Architecture in the world of web, desktop, & mobile appli...
 
Virtual box
Virtual boxVirtual box
Virtual box
 
Introduction to HashiCorp Consul
Introduction to HashiCorp ConsulIntroduction to HashiCorp Consul
Introduction to HashiCorp Consul
 
Dejan Pekter / Nordeus – Reactor design pattern
Dejan Pekter / Nordeus – Reactor design patternDejan Pekter / Nordeus – Reactor design pattern
Dejan Pekter / Nordeus – Reactor design pattern
 

Similaire à Ratpack Web Framework

introduction to node.js
introduction to node.jsintroduction to node.js
introduction to node.jsorkaplan
 
Advanced technic for OS upgrading in 3 minutes
Advanced technic for OS upgrading in 3 minutesAdvanced technic for OS upgrading in 3 minutes
Advanced technic for OS upgrading in 3 minutesHiroshi SHIBATA
 
Play Framework and Activator
Play Framework and ActivatorPlay Framework and Activator
Play Framework and ActivatorKevin Webber
 
WTF is Twisted?
WTF is Twisted?WTF is Twisted?
WTF is Twisted?hawkowl
 
Scorex, the Modular Blockchain Framework
Scorex, the Modular Blockchain FrameworkScorex, the Modular Blockchain Framework
Scorex, the Modular Blockchain FrameworkAlex Chepurnoy
 
Struts2-Spring=Hibernate
Struts2-Spring=HibernateStruts2-Spring=Hibernate
Struts2-Spring=HibernateJay Shah
 
Intro to node.js - Ran Mizrahi (27/8/2014)
Intro to node.js - Ran Mizrahi (27/8/2014)Intro to node.js - Ran Mizrahi (27/8/2014)
Intro to node.js - Ran Mizrahi (27/8/2014)Ran Mizrahi
 
Intro to node.js - Ran Mizrahi (28/8/14)
Intro to node.js - Ran Mizrahi (28/8/14)Intro to node.js - Ran Mizrahi (28/8/14)
Intro to node.js - Ran Mizrahi (28/8/14)Ran Mizrahi
 
Lessons Learned From PayPal: Implementing Back-Pressure With Akka Streams And...
Lessons Learned From PayPal: Implementing Back-Pressure With Akka Streams And...Lessons Learned From PayPal: Implementing Back-Pressure With Akka Streams And...
Lessons Learned From PayPal: Implementing Back-Pressure With Akka Streams And...Lightbend
 
Spark Streaming @ Scale (Clicktale)
Spark Streaming @ Scale (Clicktale)Spark Streaming @ Scale (Clicktale)
Spark Streaming @ Scale (Clicktale)Yuval Itzchakov
 
End to-end async and await
End to-end async and awaitEnd to-end async and await
End to-end async and awaitvfabro
 
Virtual Flink Forward 2020: How Streaming Helps Your Staging Environment and ...
Virtual Flink Forward 2020: How Streaming Helps Your Staging Environment and ...Virtual Flink Forward 2020: How Streaming Helps Your Staging Environment and ...
Virtual Flink Forward 2020: How Streaming Helps Your Staging Environment and ...Flink Forward
 
Modern application development with oracle cloud sangam17
Modern application development with oracle cloud sangam17Modern application development with oracle cloud sangam17
Modern application development with oracle cloud sangam17Vinay Kumar
 
Typesafe stack - Scala, Akka and Play
Typesafe stack - Scala, Akka and PlayTypesafe stack - Scala, Akka and Play
Typesafe stack - Scala, Akka and PlayLuka Zakrajšek
 
Solid And Sustainable Development in Scala
Solid And Sustainable Development in ScalaSolid And Sustainable Development in Scala
Solid And Sustainable Development in ScalaKazuhiro Sera
 

Similaire à Ratpack Web Framework (20)

introduction to node.js
introduction to node.jsintroduction to node.js
introduction to node.js
 
Advanced technic for OS upgrading in 3 minutes
Advanced technic for OS upgrading in 3 minutesAdvanced technic for OS upgrading in 3 minutes
Advanced technic for OS upgrading in 3 minutes
 
Play Framework and Activator
Play Framework and ActivatorPlay Framework and Activator
Play Framework and Activator
 
WTF is Twisted?
WTF is Twisted?WTF is Twisted?
WTF is Twisted?
 
Scorex, the Modular Blockchain Framework
Scorex, the Modular Blockchain FrameworkScorex, the Modular Blockchain Framework
Scorex, the Modular Blockchain Framework
 
Intro to CakePHP
Intro to CakePHPIntro to CakePHP
Intro to CakePHP
 
Struts2-Spring=Hibernate
Struts2-Spring=HibernateStruts2-Spring=Hibernate
Struts2-Spring=Hibernate
 
About Clack
About ClackAbout Clack
About Clack
 
Intro to node.js - Ran Mizrahi (27/8/2014)
Intro to node.js - Ran Mizrahi (27/8/2014)Intro to node.js - Ran Mizrahi (27/8/2014)
Intro to node.js - Ran Mizrahi (27/8/2014)
 
Intro to node.js - Ran Mizrahi (28/8/14)
Intro to node.js - Ran Mizrahi (28/8/14)Intro to node.js - Ran Mizrahi (28/8/14)
Intro to node.js - Ran Mizrahi (28/8/14)
 
Lessons Learned From PayPal: Implementing Back-Pressure With Akka Streams And...
Lessons Learned From PayPal: Implementing Back-Pressure With Akka Streams And...Lessons Learned From PayPal: Implementing Back-Pressure With Akka Streams And...
Lessons Learned From PayPal: Implementing Back-Pressure With Akka Streams And...
 
Spark Streaming @ Scale (Clicktale)
Spark Streaming @ Scale (Clicktale)Spark Streaming @ Scale (Clicktale)
Spark Streaming @ Scale (Clicktale)
 
Function as a Service
Function as a ServiceFunction as a Service
Function as a Service
 
Giraph+Gora in ApacheCon14
Giraph+Gora in ApacheCon14Giraph+Gora in ApacheCon14
Giraph+Gora in ApacheCon14
 
End to-end async and await
End to-end async and awaitEnd to-end async and await
End to-end async and await
 
Apache Drill (ver. 0.2)
Apache Drill (ver. 0.2)Apache Drill (ver. 0.2)
Apache Drill (ver. 0.2)
 
Virtual Flink Forward 2020: How Streaming Helps Your Staging Environment and ...
Virtual Flink Forward 2020: How Streaming Helps Your Staging Environment and ...Virtual Flink Forward 2020: How Streaming Helps Your Staging Environment and ...
Virtual Flink Forward 2020: How Streaming Helps Your Staging Environment and ...
 
Modern application development with oracle cloud sangam17
Modern application development with oracle cloud sangam17Modern application development with oracle cloud sangam17
Modern application development with oracle cloud sangam17
 
Typesafe stack - Scala, Akka and Play
Typesafe stack - Scala, Akka and PlayTypesafe stack - Scala, Akka and Play
Typesafe stack - Scala, Akka and Play
 
Solid And Sustainable Development in Scala
Solid And Sustainable Development in ScalaSolid And Sustainable Development in Scala
Solid And Sustainable Development in Scala
 

Plus de Daniel Woods

Continuous Delivery with Spinnaker and OpenStack
Continuous Delivery with Spinnaker and OpenStackContinuous Delivery with Spinnaker and OpenStack
Continuous Delivery with Spinnaker and OpenStackDaniel Woods
 
Microservices: The Right Way
Microservices: The Right WayMicroservices: The Right Way
Microservices: The Right WayDaniel Woods
 
Facilitating Continuous Delivery at Scale
Facilitating Continuous Delivery at ScaleFacilitating Continuous Delivery at Scale
Facilitating Continuous Delivery at ScaleDaniel Woods
 
Continuous Delivery with NetflixOSS
Continuous Delivery with NetflixOSSContinuous Delivery with NetflixOSS
Continuous Delivery with NetflixOSSDaniel Woods
 
Server-Side JavaScript with Nashorn
Server-Side JavaScript with NashornServer-Side JavaScript with Nashorn
Server-Side JavaScript with NashornDaniel Woods
 
Groovy for System Administrators
Groovy for System AdministratorsGroovy for System Administrators
Groovy for System AdministratorsDaniel Woods
 
Message Driven Architecture in Grails
Message Driven Architecture in GrailsMessage Driven Architecture in Grails
Message Driven Architecture in GrailsDaniel Woods
 
Gainesville Web Developer Group, Sept 2012
Gainesville Web Developer Group, Sept 2012Gainesville Web Developer Group, Sept 2012
Gainesville Web Developer Group, Sept 2012Daniel Woods
 

Plus de Daniel Woods (8)

Continuous Delivery with Spinnaker and OpenStack
Continuous Delivery with Spinnaker and OpenStackContinuous Delivery with Spinnaker and OpenStack
Continuous Delivery with Spinnaker and OpenStack
 
Microservices: The Right Way
Microservices: The Right WayMicroservices: The Right Way
Microservices: The Right Way
 
Facilitating Continuous Delivery at Scale
Facilitating Continuous Delivery at ScaleFacilitating Continuous Delivery at Scale
Facilitating Continuous Delivery at Scale
 
Continuous Delivery with NetflixOSS
Continuous Delivery with NetflixOSSContinuous Delivery with NetflixOSS
Continuous Delivery with NetflixOSS
 
Server-Side JavaScript with Nashorn
Server-Side JavaScript with NashornServer-Side JavaScript with Nashorn
Server-Side JavaScript with Nashorn
 
Groovy for System Administrators
Groovy for System AdministratorsGroovy for System Administrators
Groovy for System Administrators
 
Message Driven Architecture in Grails
Message Driven Architecture in GrailsMessage Driven Architecture in Grails
Message Driven Architecture in Grails
 
Gainesville Web Developer Group, Sept 2012
Gainesville Web Developer Group, Sept 2012Gainesville Web Developer Group, Sept 2012
Gainesville Web Developer Group, Sept 2012
 

Dernier

Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 

Dernier (20)

Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 

Ratpack Web Framework

  • 2. •  Member of the Ratpack core team •  Work at Netflix •  Writing Learning Ratpack for O’Reilly •  Follow me on Twitter: @danveloper
  • 3. •  A full-stack, high throughput, non-blocking web framework •  Built entirely on Java 8 •  Specialized support for writing apps in Groovy
  • 4. •  Groovy has come a long way over the last few years… •  Static compilation and (optional) compile time type checking •  Excellent language for writing concise DSLs •  DSLs can be statically compiled! Why Groovy?
  • 5. •  Groovy’s three compilation modes give applications a lot of flexibility •  Parallels Java performance using Invoke Dynamic or Static Compilation •  Pick-and-choose static or dynamic, depending on the use-case! Why Groovy?
  • 6. •  Requires Groovy 2.3.6+ •  Utilize advanced static compilation and type checking features of Groovy, like @DelegatesTo •  Allows you to define your application structure in a ratpack.groovy file Why Groovy?
  • 7. @GrabResolver(name='netty', root='http://clinker.netty.io/ nexus/content/repositories/snapshots')! @Grab('io.ratpack:ratpack-groovy:0.9.13-SNAPSHOT')! ! import static ratpack.groovy.Groovy.ratpack! ! ratpack {! handlers {! handler { ! response.send ”Hello World!"! }! }! }! Simple Groovy Script* * @GrabResolver will not be required after 4.1.0-Beta4 is published; * Ratpack 0.9.13 will be released on Feb 1, 2014
  • 8. •  There are no plugins in Ratpack, instead the framework provides functionality through modules •  Modules are built in Guice* •  DI is an abstraction in Ratpack, so even though the framework uses Guice, you don’t have to *  h$ps://github.com/google/guice  
  • 9. •  A set of composable libraries for building unopinionated, rich web applications •  Pick-and-choose what aspects of the framework you want •  No lock-in to a single way of doing things
  • 10. •  Emphasis on Performance and Efficiency in both applications and development experience •  Hot reloading is available during development time •  Beautiful development-time error pages •  Extreme emphasis on developer testing, especially functional and integration •  Support for mocking nearly all aspects of the framework
  • 11. Example of a development-time error:
  • 12. •  Convention over configuration taken too far doesn’t let you wire things together •  Ratpack makes wiring modules a “one-liner”, so there’s not a lot of work to get new features integrated •  Out of the box support for Guice and Spring (Spring Boot) DI
  • 13. •  Gradle integration makes building robust projects easy to do •  Simple apps can be run entirely through the Groovy command-line
  • 14. buildscript { repositories { jcenter() maven { url "http://oss.jfrog.org/oss-snapshot-local" } maven { url "http://clinker.netty.io/nexus/content/repositories/snapshots" } } dependencies { classpath 'io.ratpack:ratpack-gradle:0.9.13-SNAPSHOT' } } apply plugin: 'io.ratpack.ratpack-java' Simple Gradle Build Script* * Ratpack 0.9.13 will be released on Feb 1, 2014
  • 15. •  Any non-trivial application needs build and packaging capabilities •  The Ratpack Gradle plugin provides all the fixtures to support building web application projects
  • 16. •  Ratpack is built on Netty, which provides the infrastructure for highly performant, non-blocking networking
  • 17. •  Netty is an extremely mature, super low-level networking library •  Excellent documentation, very involved community •  Heavy emphasis on high throughput and performance
  • 18. •  Netty provides the infrastructure for non- blocking networking, but doesn’t help much in the way of web application structure •  Provides an asynchronous API for working with network data (including HTTP)
  • 19. •  Computers “think” very good in asynchronous terms; humans do not… •  Without app structure, programming toward this paradigm is difficult •  Ratpack ensures the most performant structures of Netty are being utilized, while providing a sensible app structure and programming model
  • 20. •  Ratpack provides applications with a Netty-based, non- blocking HTTP client •  Can be used to integrate with external RESTful services •  Utilizes the same event loop as the server, so resources are appropriately utilized •  Provides a robust API for programmatically crafting requests
  • 21. Above all else… Ratpack is your GATEWAY DRUG to non-blocking
  • 22.
  • 23. •  The JVM doesn’t have any concept of continuations, so the only option we have is asynchronous APIs •  Async APIs allow callers to provide a completion handler (or callback), which is to be invoked when some processing has finished •  There is no temporal relationship between the caller and the invocation of the callback
  • 24. handler { req, res ->! ... (1) do some work ...! ! async {! ... (2) do some async work ...! }! async {! ... (3) do some more async ...! }! ! ... (4) send response ...! }! (1)  – Definitely finishes first (2)  – May finish before or after (3) and (4) (3)  – May finish before or after (2) or (4) (4)  – May finish before or after (2) or (3) Async APIs create non-determinism in control flow
  • 25. •  The temporal disconnect creates non-determinism in request processing •  This is a big problem for web applications, because they demand a deterministic control flow •  Ratpack provides the concept of an Execution, which creates determinism in asynchronous processing
  • 26. handler { req, res ->! ... (1) do some work ...! ! async {! ... (3) do some async work ...! }! async {! ... (4) do some more async ...! }! ! ... (2) send response ...! }! (1) – Definitely finishes first (3) – Definitely finishes third (4) – Definitely finishes fourth (2) – Definitely finishes second Ratpack creates a deterministic control flow
  • 27. •  Through Ratpack’s promise API, the Execution is able to schedule async segments to be invoked after the handler code has finished •  Promise API ensures that developers can work with asynchronous processing in a sensible way
  • 28. •  In non-blocking, it is of paramount importance to not block the thread •  Since a single thread is handling processing for many clients, blocking one blocks all •  Need to adopt libraries that are non-blocking or provide async APIs •  This is not always practical…
  • 29. •  Not all interfaces are able to be non-blocking or asynchronous •  Most non-blocking frameworks force you to be either entirely async or wholesale define your handlers as blocking •  This is limiting and makes it difficult to work with legacy APIs or those not crafted for non-blocking work •  Ratpack gives you a mechanism to define blocking execution segments in your handler code
  • 30. handler(r -> (ctx) -> { ModelDAO dao = ctx.get(ModelDAO.class); ctx.blocking(() -> dao.load(ctx.getPathTokens().get("id"))) .then(model -> { ... do some work with the data ... ctx.render(model); }); }) Handler with blocking operation
  • 31. •  Blocking operations are scheduled to an I/O bound thread pool •  Once the blocking operation is completed, the data is then returned to the request taking thread, where processing can finish •  Blocking operations are invoked when they are subscribed to in the request-taking thread
  • 32. ... ctx.blocking(() -> { ... do some blocking io ... return result; }).then(result -> { ... subscribe to the blocking promise ... ... process in the request-taking thread ... }) ... Blocking with a subscription
  • 33. •  Data is being delivered to web consumers in an increasingly real time way •  Web applications must be able to support streaming protocols like SSE and WebSockets •  Ratpack has built-in fixtures that make it easy to develop real-time web applications
  • 34. •  Because of its non-blocking nature, Ratpack can support a high volume of concurrent real-time streams •  Valuable in app-to-app communication too, where a consumer wants to be reactively informed about some data •  Ratpack’s HTTP client also supports reading streams of data from external producers, making stream processing a great integration
  • 35.
  • 36. •  Ratpack applications are defined through a handler chain •  Handler chain is a programmatic construct for managing the flow of request data •  Handlers can be bound to request path routes and HTTP verbs
  • 37. import static ratpack.groovy.Groovy.ratpack! ! ratpack {! handlers {! get {! response.send "I'm the default route!"! }! get("route1") {! response.send "I'm in route1"! }! get("route2/:param") {! response.send "I'm in route2 and received param: ${pathTokens.param}"! }! }! }! Handler chain in a Ratpack Script-backed app
  • 38. RatpackServer.start(b -> b
 .config(ServerConfig.noBaseDir())
 .handlers(chain -> chain
 .get(ctx -> ctx.getResponse()
 .send("I'm in the default route!"))
 ! .get("route1", (ctx) -> ctx.getResponse()
 .send("I'm in route1!"))
 ! .get("route2/:param", (ctx) -> ctx.getResponse()
 .send(String
 .format(” received param: %s",
 ctx.getPathTokens().get("param"))))
 )
 );" Handler chain in using Java 8 APIs
  • 39. •  Ratpack applications are defined through a handler chain •  Handler chain is a programmatic construct for managing the flow of request data •  Handlers can be bound to request path routes and HTTP verbs
  • 40. handlers {! get { ... }! get("route") { ... }! ! post { ... }! post("route") { ... }! ! put { ... }! put("route") { ... }! ! delete { ... }! delete("route") { ... }! ! patch { ... }! patch("route") { ... }! }! Semantic handler API for binding to HTTP verbs and routes
  • 41. •  Handlers can be nested within a route… handlers {
 prefix("api") { ModelDAO dao ->
 get {
 blocking { dao.getAll() }.
 then { models -> render JsonOutput.toJson(models) }
 }
 post {
 Model model = parse(fromJson(Model))
 blocking { dao.save(model) }.
 then { m -> render m }
 }
 put(":id") {
 blocking { dao.load(pathTokens.id) }.
 map { model -> model.merge(parse(fromJson(Model))) }.
 blockingMap { model -> dao.save(model) }.
 then { model -> render model }
 }
 }
 }!
  • 42. •  There’s a special handler type for serving static assets from the app’s baseDir! •  Static assets must be defined as the last handler in the chain •  Can be scoped to routes
  • 43. •  Use the assets handler to serve static content handlers {
 prefix("api") {
 get {
 response.send "some API data"
 }
 }
 assets("public", "index.html”)
 }!
  • 44. •  You can also use a handler with byMethod to perform common processing within a route… handlers {
 handler("api") { ModelDAO dao ->
 dao.beginTransaction()
 byMethod {
 get {}
 post {}
 put {}
 delete {}
 }
 dao.endTransaction()
 }! }!
  • 45. •  Can discriminate on content type, allowing you to build HyperMedia APIs… handlers {
 handler {
 byContent {
 json {
 response.send(toJson([msg: "regular json"]))
 }
 xml {
 response.send(...)
 }
 type("application/vnd.app.org+json;v=1") {
 response.send(toJson([newmsg: "hypermedia json"]))
 }
 }
 }
 }!
  • 46. •  Handlers define the edge of your application •  In Servlet API terms, handlers can be thought of as a marriage between filters and servlets •  Allows request introspection and programmatic injection of handler chain
  • 47. •  This allows handlers to be constructed and dependency injected, etc… class UserHandler implements Handler {
 
 private final String message
 
 UserHandler(String message) {
 this.message = message
 }
 
 @Override
 void handle(Context context) ! !throws Exception {
 context.response.send(message)
 }
 }! ratpack {
 bindings {
 bindInstance(new UserHandler("user handler"))
 }
 handlers {
 handler { UserHandler userHandler ->
 if (request! .headers.contains("X-Routing-Header")) {
 def routingHeader = request! .headers.get("X-Routing-Header")
 if (routingHeader == "user") {
 insert(userHandler)
 }
 }
 next()
 }
 get {
 response.send "default system handler"
 }
 }
 }! New  Handler  is   programma1cally  inserted   into  the  processing  chain  
  • 48.
  • 49. •  Dependency injection is an abstraction in Ratpack, through the concept of a Registry •  Components are bound to, and resolvable from, a Registry instance •  Registries can be backed in a DI framework
  • 50. •  Out of the box support for Guice and Spring Boot •  Registries can be inherited, allowing components to be resolved in a cascading manner •  Every request context gets a registry that components can be extracted from
  • 51. •  In a Groovy script that uses closures as handlers, the variable arguments to that closure are “injected” from the registry •  In Java 8, they are able to be resolved from the request context object
  • 52. •  You don’t need to use a DI framework to get injection support, you can build your own registry from objects you construct… public static void main(String[] args) throws Exception {
 Registry registry = Registries.registry()
 .add(new ModelDAO()).add(new DB()).build();
 
 RatpackServer.start(spec -> spec
 .config(ServerConfig.noBaseDir())
 .handlers(chain -> {
 chain.register(registry);
 chain.handler(":id", ctx -> {
 ModelDAO dao = ctx.get(ModelDAO.class);
 ctx.blocking(() ->
 dao.load(ctx.getPathTokens().get("id")))
 .then(ctx::render);
 });
 })
 );
 }!
  • 53. •  Variables arguments to Groovy closure handlers are resolved from the registry def myRegistry = Registries.registry()
 .add(new ModelDAO())
 .build()
 
 ratpack {
 handlers {
 register(myRegistry)
 
 prefix("api") {
 get(":id") { ModelDAO dao ->
 render dao.load(pathTokens.id)
 }
 }
 assets("public", "index.html”)
 }
 }!
  • 54. •  In Groovy, you get a bindings block, which you can use to bind components to the Registry. With Guice, annotations can be used to Inject class UserHandler implements Handler {
 
 private final ModelDAO dao
 
 @javax.inject.Inject! UserHandler(ModelDAO dao) {
 this.message = message
 }
 
 @Override
 void handle(Context ctx) ! !throws Exception {
 ctx.blocking {! dao.getAll()! } then { ctx.render(it) }
 }
 }! ratpack {
 bindings {
 binder { b ->
 b.bind(ModelDAO).in(Scopes.SINGLETON)
 b.bind(UserHandler).in(Scopes.SINGLETON)
 }
 }! handlers {
 handler { UserHandler userHandler ->
 if (request! .headers.contains("X-Routing-Header")) {
 def routingHeader = request! .headers.get("X-Routing-Header")
 if (routingHeader == "user") {
 insert(userHandler)
 }
 }
 next()
 }
 get {
 response.send "default system handler"
 }
 }
 }! Can  get  a  handle  on  a  Guice   binder  to  perform   annota1on-­‐based  Injec1ng  
  • 55. •  Likewise, a Guice Module can be “added” to the registry… ratpack {
 bindings {! // Any Guice module can be added this way! // this is how Ratpack modules are" // introduced... " add(new SqlModule())
 }! handlers {
 ...! }
 }!
  • 56. •  Spring application context can be used to back a registry using the ratpack.spring.Spring class h>p://www.ratpack.io/manual/0.9.13/api/ratpack/spring/Spring.html    
  • 57. •  Like handlers, registries can be programmatically registered into the handler chain based on request data •  Can allow your app to resolve components specific to the context of a request
  • 58. •  Likewise, a Guice Module can be “added” to the registry… def baseRegistry = Registries.registry()
 .add(new ModelDAO("jdbc:mysql://default"))
 .build()
 
 def cust1Registry = Registries.registry()
 .add(new ModelDAO("jdbc:mysql://cust1"))
 .build()
 
 ratpack {
 bindings {
 bindInstance(new DefaultDevelopmentErrorHandler())
 }
 handlers {
 handler {
 next(get(PublicAddress).getAddress(it).host == "cust1" ? cust1Registry : baseRegistry)
 }
 prefix("api") {
 get(":id") { ModelDAO dao ->
 render blocking { dao.load(pathTokens.id) }
 }
 }
 assets("public", "index.html”)
 }
 }!
  • 59.
  • 60. •  Including framework modules in your Gradle based project is really easy •  Can utilize helper methods from the Ratpack Gradle plugin to include named modules •  Allows framework versions to stay in sync
  • 61. •  The Ratpack Gradle plugin provides the ratpack.dependency() helper ...! ! dependencies {
 compile ratpack.dependency("jackson”)
 compile ratpack.dependency(”rxjava”)! compile ratpack.dependency(”codahale-metrics”)! testCompile ratpack.dependency(”remote-test”) ! }! ! ...!
  • 62. •  Including framework modules in your Gradle based project is really easy •  Can utilize helper methods from the Ratpack Gradle plugin to include named modules •  Allows framework versions to stay in sync
  • 63. •  Static fixtures for mapping a multitude of external and environmental configuration sources to POJOs Configuration Module: ratpack-config // build.gradle" dependencies {! ...
 compile ratpack.dependency(”config”)! ...
 }! import ratpack.config.*;! ! ConfigurationData configData = Configurations.config()
 .yaml(Main.class.getResource("/app.yml"))
 .json(Main.class.getResource("/app.json"))
 .props("/etc/app/file.properties")
 .sysProps()
 .env()
 .build();! ! ServerConfig config = configData! .get("/server", ServerConfig.class);
 
 RatpackServer.start(spec -> spec
 .config(config)
 .handlers(...)
 );! // classpath:/app.yml" server:! port: 8080! ! myAppStuff:! anyConfigData: 1234!
  • 64. •  Environment-derivable configuration follows the principle of the Twelve Factor App Great Support for building MICROSERVICES!!
  • 65. •  NetflixOSS Hystrix support, via the ratpack- hystrix module •  Calls to remote services can be made fault tolerant •  Ability to stream Hystrix metrics to the Hystrix Dashboard Great Support for building MICROSERVICES!!
  • 66. •  The ratpack-hikari module uses HikariCP to create a super fast pooled SQL DataSource •  Can be used in conjunction with Groovy SQL to query databases •  Configurable using the fixtures from the ratpack-config module Great Support for DATABASES!!
  • 67. •  The ratpack-jackson module provides request data parsing and object rendering from and to JSON •  Data can be worked with in free-form nodes, or bound to command objects •  Arbitrary models can be rendered as JSON using simply context.render(obj)! Great Support for DATA BINDING!!
  • 68. •  Ratpack’s Promise API is an implementation of Reactive Streams Specification •  The ratpack-rxjava module provides a bridge between a Ratpack Promise and an RxJava Observable •  The ratpack-reactor module allows data to be processed using Project Reactor Great Support for REACTIVE PROGRAMMING!!
  • 69. •  View templates can be rendered through a variety of means •  Support for server-side templating with Handlebars, Thymeleaf, Groovy Templates, and Groovy Markup •  Ongoing work to integrate @davydotcom’s asset- pipeline, which will give robust support for all types of static content Great Support for FULL-STACK FEATURES!!
  • 70.
  • 71. •  Ratpack has been built from the ground-up with testing considered at every turn •  Even more-so – considering testing from the perspective of the developer •  The concept of the Registry gives the framework control over components •  Makes it easy to provide fixtures for mocking and stubbing data
  • 72. •  The EmbeddedApp class from the ratpack- test module supports functional and integration testing •  Can be used to test an application module or a subset of handlers and functionality •  Can be used outside of Ratpack too!
  • 73. •  Spock is the choice framework, though there’s no strict integration there •  Functional tests are easy to bootstrap and the TestHttpClient helper makes it easy to programmatically craft test calls
  • 74. •  Great resource for seeing Ratpack’s testing in action is the example-books project •  Rus Hart keeps this up to date with changes to the framework. •  https://github.com/ratpack/example-books
  • 75. Twitter people to follow:! ! •  @ldaley! •  @rus_hart! •  @varzof! •  @Lspacewalker! •  @marcinerdmann! •  @ratpackweb! •  @davydotcom! •  @johnrengelman! •  @rfletcherEW! •  @beckje01!