SlideShare a Scribd company logo
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!

More Related Content

What's hot

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
VMware 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-blocking
Marcin Erdmann
 
Gradle
GradleGradle
Introduction to gradle
Introduction to gradleIntroduction to gradle
Introduction to gradle
NexThoughts Technologies
 
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
kennethaliu
 
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
Michael 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 2021
Cé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 AWS
VMware 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
 
Implementing your own Google App Engine
Implementing your own Google App Engine Implementing your own Google App Engine
Implementing your own Google App Engine
Virtual JBoss User Group
 
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
Wisely chen
 
Integration testing dropwizard
Integration testing dropwizardIntegration testing dropwizard
Integration testing dropwizard
Michal Rutkowski, Ph.D.
 
Gradle - Build system evolved
Gradle - Build system evolvedGradle - Build system evolved
Gradle - Build system evolved
Bhagwat 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 Manager
Jens Ravens
 
Polygot Java EE on the GraalVM
Polygot Java EE on the GraalVMPolygot Java EE on the GraalVM
Polygot Java EE on the GraalVM
Ryan Cuprak
 
Gitlab ci, cncf.sk
Gitlab ci, cncf.skGitlab ci, cncf.sk
Gitlab ci, cncf.sk
Juraj 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 Projects
GR8Conf
 
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 Karaf
Ioan Eugen Stan
 

What's hot (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
 

Viewers also liked

Forex AutoPilot
Forex AutoPilotForex AutoPilot
Forex AutoPilot
Rosli Shafiee
 
Ratpack and Grails 3
Ratpack and Grails 3Ratpack and Grails 3
Ratpack and Grails 3
Lari Hotari
 
Usage concurrence in java
Usage concurrence in javaUsage concurrence in java
Usage concurrence in java
Asya Dudnik
 
Java threads - part 2
Java threads - part 2Java threads - part 2
Java threads - part 2
Nakraynikov Oleg
 
Java threads - part 3
Java threads - part 3Java threads - part 3
Java threads - part 3
Nakraynikov Oleg
 
Java threads - part 1
Java threads - part 1Java threads - part 1
Java threads - part 1
Nakraynikov Oleg
 
Java 8. Thread pools
Java 8. Thread poolsJava 8. Thread pools
Java 8. Thread pools
Nakraynikov Oleg
 
Managing computational resources with Apache Mesos
Managing computational resources with Apache MesosManaging computational resources with Apache Mesos
Managing computational resources with Apache Mesos
Jackson dos Santos Olveira
 
Introduction to CFEngine
Introduction to CFEngineIntroduction to CFEngine
Introduction to CFEngine
Jackson dos Santos Olveira
 
Vagrant
VagrantVagrant
Docker cloud
Docker cloudDocker cloud
An introduction to predictionIO
An introduction to predictionIOAn introduction to predictionIO
An introduction to predictionIO
Jackson dos Santos Olveira
 
Apache mahout - introduction
Apache mahout - introductionApache mahout - introduction
Apache mahout - introduction
Jackson dos Santos Olveira
 
Docker hub
Docker hubDocker 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 ...
Codemotion
 
Multithreading in java past and actual
Multithreading in java past and actualMultithreading in java past and actual
Multithreading in java past and actual
Yevgen 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
 
Virtual box
Virtual boxVirtual box
Introduction to HashiCorp Consul
Introduction to HashiCorp ConsulIntroduction to HashiCorp Consul
Introduction to HashiCorp Consul
Jackson dos Santos Olveira
 
Dejan Pekter / Nordeus – Reactor design pattern
Dejan Pekter / Nordeus – Reactor design patternDejan Pekter / Nordeus – Reactor design pattern
Dejan Pekter / Nordeus – Reactor design pattern
ConversionMeetup
 

Viewers also liked (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
 

Similar to Ratpack Web Framework

introduction to node.js
introduction to node.jsintroduction to node.js
introduction to node.js
orkaplan
 
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
Hiroshi SHIBATA
 
Play Framework and Activator
Play Framework and ActivatorPlay Framework and Activator
Play Framework and Activator
Kevin 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 Framework
Alex Chepurnoy
 
Intro to CakePHP
Intro to CakePHPIntro to CakePHP
Intro to CakePHP
Walther Lalk
 
Struts2-Spring=Hibernate
Struts2-Spring=HibernateStruts2-Spring=Hibernate
Struts2-Spring=Hibernate
Jay Shah
 
About Clack
About ClackAbout Clack
About Clack
fukamachi
 
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
 
Function as a Service
Function as a ServiceFunction as a Service
Function as a Service
rich fernandez
 
Giraph+Gora in ApacheCon14
Giraph+Gora in ApacheCon14Giraph+Gora in ApacheCon14
Giraph+Gora in ApacheCon14
Renato Javier Marroquín Mogrovejo
 
End to-end async and await
End to-end async and awaitEnd to-end async and await
End to-end async and await
vfabro
 
Apache Drill (ver. 0.2)
Apache Drill (ver. 0.2)Apache Drill (ver. 0.2)
Apache Drill (ver. 0.2)
Camuel Gilyadov
 
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 sangam17
Vinay Kumar
 
Typesafe stack - Scala, Akka and Play
Typesafe stack - Scala, Akka and PlayTypesafe stack - Scala, Akka and Play
Typesafe stack - Scala, Akka and Play
Luka Zakrajšek
 
Solid And Sustainable Development in Scala
Solid And Sustainable Development in ScalaSolid And Sustainable Development in Scala
Solid And Sustainable Development in Scala
Kazuhiro Sera
 

Similar to 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
 

More from Daniel Woods

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

More from 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
 

Recently uploaded

"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
Fwdays
 
A Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's ArchitectureA Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's Architecture
ScyllaDB
 
High performance Serverless Java on AWS- GoTo Amsterdam 2024
High performance Serverless Java on AWS- GoTo Amsterdam 2024High performance Serverless Java on AWS- GoTo Amsterdam 2024
High performance Serverless Java on AWS- GoTo Amsterdam 2024
Vadym Kazulkin
 
QA or the Highway - Component Testing: Bridging the gap between frontend appl...
QA or the Highway - Component Testing: Bridging the gap between frontend appl...QA or the Highway - Component Testing: Bridging the gap between frontend appl...
QA or the Highway - Component Testing: Bridging the gap between frontend appl...
zjhamm304
 
Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |
AstuteBusiness
 
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-EfficiencyFreshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
ScyllaDB
 
Demystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through StorytellingDemystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through Storytelling
Enterprise Knowledge
 
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdfHow to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
Chart Kalyan
 
ScyllaDB Tablets: Rethinking Replication
ScyllaDB Tablets: Rethinking ReplicationScyllaDB Tablets: Rethinking Replication
ScyllaDB Tablets: Rethinking Replication
ScyllaDB
 
Christine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptxChristine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptx
christinelarrosa
 
What is an RPA CoE? Session 2 – CoE Roles
What is an RPA CoE?  Session 2 – CoE RolesWhat is an RPA CoE?  Session 2 – CoE Roles
What is an RPA CoE? Session 2 – CoE Roles
DianaGray10
 
"Choosing proper type of scaling", Olena Syrota
"Choosing proper type of scaling", Olena Syrota"Choosing proper type of scaling", Olena Syrota
"Choosing proper type of scaling", Olena Syrota
Fwdays
 
Y-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PPY-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PP
c5vrf27qcz
 
"What does it really mean for your system to be available, or how to define w...
"What does it really mean for your system to be available, or how to define w..."What does it really mean for your system to be available, or how to define w...
"What does it really mean for your system to be available, or how to define w...
Fwdays
 
"Scaling RAG Applications to serve millions of users", Kevin Goedecke
"Scaling RAG Applications to serve millions of users",  Kevin Goedecke"Scaling RAG Applications to serve millions of users",  Kevin Goedecke
"Scaling RAG Applications to serve millions of users", Kevin Goedecke
Fwdays
 
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
DanBrown980551
 
Must Know Postgres Extension for DBA and Developer during Migration
Must Know Postgres Extension for DBA and Developer during MigrationMust Know Postgres Extension for DBA and Developer during Migration
Must Know Postgres Extension for DBA and Developer during Migration
Mydbops
 
Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Biomedical Knowledge Graphs for Data Scientists and BioinformaticiansBiomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Neo4j
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
DianaGray10
 
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham HillinQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
LizaNolte
 

Recently uploaded (20)

"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
 
A Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's ArchitectureA Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's Architecture
 
High performance Serverless Java on AWS- GoTo Amsterdam 2024
High performance Serverless Java on AWS- GoTo Amsterdam 2024High performance Serverless Java on AWS- GoTo Amsterdam 2024
High performance Serverless Java on AWS- GoTo Amsterdam 2024
 
QA or the Highway - Component Testing: Bridging the gap between frontend appl...
QA or the Highway - Component Testing: Bridging the gap between frontend appl...QA or the Highway - Component Testing: Bridging the gap between frontend appl...
QA or the Highway - Component Testing: Bridging the gap between frontend appl...
 
Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |
 
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-EfficiencyFreshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
 
Demystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through StorytellingDemystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through Storytelling
 
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdfHow to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
 
ScyllaDB Tablets: Rethinking Replication
ScyllaDB Tablets: Rethinking ReplicationScyllaDB Tablets: Rethinking Replication
ScyllaDB Tablets: Rethinking Replication
 
Christine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptxChristine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptx
 
What is an RPA CoE? Session 2 – CoE Roles
What is an RPA CoE?  Session 2 – CoE RolesWhat is an RPA CoE?  Session 2 – CoE Roles
What is an RPA CoE? Session 2 – CoE Roles
 
"Choosing proper type of scaling", Olena Syrota
"Choosing proper type of scaling", Olena Syrota"Choosing proper type of scaling", Olena Syrota
"Choosing proper type of scaling", Olena Syrota
 
Y-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PPY-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PP
 
"What does it really mean for your system to be available, or how to define w...
"What does it really mean for your system to be available, or how to define w..."What does it really mean for your system to be available, or how to define w...
"What does it really mean for your system to be available, or how to define w...
 
"Scaling RAG Applications to serve millions of users", Kevin Goedecke
"Scaling RAG Applications to serve millions of users",  Kevin Goedecke"Scaling RAG Applications to serve millions of users",  Kevin Goedecke
"Scaling RAG Applications to serve millions of users", Kevin Goedecke
 
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
 
Must Know Postgres Extension for DBA and Developer during Migration
Must Know Postgres Extension for DBA and Developer during MigrationMust Know Postgres Extension for DBA and Developer during Migration
Must Know Postgres Extension for DBA and Developer during Migration
 
Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Biomedical Knowledge Graphs for Data Scientists and BioinformaticiansBiomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
 
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham HillinQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
 

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!