Learning Ratpack

Keeping it classy

       Blog: Juan Vazquez
  Twitter: @javazquez
Github:  javazquez

What is Ratpack?

  1. Ratpack is a set of Java libraries for building modern HTTP applications
  2. It provides just enough for writing practical, high performance, apps
  3. It is built on Java 8, Netty and reactive principles.
  4. Huge thanks to these people



This presentation used excerpts From https://ratpack.io/

Concepts

  1. Context
  2. Registries
  3. Handlers
  4. Routes
  5. Logging
  6. Testing

Hello World

@Grapes([
@Grab('io.ratpack:ratpack-groovy:1.1.1'),
@Grab('org.slf4j:slf4j-simple:1.7.12')
	])
import static ratpack.groovy.Groovy.ratpack

ratpack {
handlers {
	get {
		render "Hello World!"
	}
	get(":name") {
		render "Hello $pathTokens.name!"
	}
}
}

Context provides

  • Access to the HTTP Request and Response
  • Delegation and flow control (via the next() and insert() methods)
  • Access to contextual objects
  • Convenience for common handler operations
  • The Context is a Registry
  • Supports partitioning application logic by providing different objects to different partitions

Registries

  • The mechanism for inter-handler collaboration in Ratpack

Handlers

  • Respond to the request
  • Method that acts on a context
  • All request processing logic is simply the composition of handlers ("Chaining")
  • Insert handlers into the Chain and immediately delegate to them
  • Delegate to the next handler
  • Handlers operate on a context

Strongly Typed

Non-Blocking

Explicit when you need to block
						// A handler that uses the API
public static class DeletingHandler extends InjectionHandler {
 void handle(final Context context, final Datastore datastore) {
	 final int days = context.getPathTokens().asInt("days");
	 Blocking.get(() -> datastore.deleteOlderThan(days))
		 .then(i -> context.render(i + " records deleted"));
 }
}
					

Look Ma.. no Plugins

  • Add-on integration with Google Guice facilitates a kind of plugin system through Guice modules

Asynchronous

Using Promises - Jeff Beck
						
import ratpack.test.embed.EmbeddedApp;
import ratpack.exec.Promise;

import static org.junit.Assert.assertEquals;

public class Example {
public static void main(String... args) throws Exception {
 EmbeddedApp.fromHandler(ctx ->
		 Promise.of((f) ->
				 new Thread(() -> f.success("hello world")).start()
		 ).then(ctx::render)
 ).test(httpClient -> {
	 assertEquals("hello world", httpClient.getText());
 });
}
}
					

routes by method

from ratpack example books project

Logging

From ratpack.io
  • No-Op - discards all logs (default)
  • Log4J
  • Logback - native SLF4J implementation with “zero memory and computational overhead”
  • Java Util Logging
  • Simple - logs messages at INFO level and higher to System.err
  • Jakarta Commons Logging

Testing

  • Spock
  • Ratpack provides its own HttpClient which can be used to make remote HTTP calls. The Ratpack provided HttpClient is fully non-blocking and is a part of the core Ratpack library. Just like the Ratpack server, the HttpClient also uses Netty under the hood and in fact shares the same EventLoopGroup as per Netty best practices.
  • show HandlerSpec

Tool Chain

Groovy Language
SDKMAN logo

Lazybones(via sdkman)

> sdk install lazybones
> lazybones create <ratpack template> <ratpack version> <app name>

> lazybones create ratpack my-ratpack-app
> cd my-ratpack-app
> ./gradlew run
							
						

Gradle Build

build.gradle
							buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath "io.ratpack:ratpack-gradle:1.1.1"
  }
}
apply plugin: "io.ratpack.ratpack-groovy"
apply plugin: "idea"

repositories {
  jcenter()
}
dependencies {
  runtime "org.slf4j:slf4j-simple:1.7.12"
}

						

Code that Gradle Wrapper runs

src/ratpack/ratpack.groovy
							import static ratpack.groovy.Groovy.ratpack

ratpack {
    handlers {
        get {
            render "Hello World!"
        }
        get(":name") {
            render "Hello $pathTokens.name!"
        }
    }
}
>[main] INFO ratpack.server.RatpackServer - Starting server...
>[main] INFO ratpack.server.RatpackServer - Building registry...
>[main] INFO ratpack.server.RatpackServer - Initializing 2 services...
>[main] INFO ratpack.server.RatpackServer - Ratpack started(development)
 for http://localhost:5050
 

Ratpack Tutorial

https://github.com/javazquez/Ratpack-Tutorial

git tags

  • Lazy_Bones
  • no_frills_site
  • API_Handlebars_ContentAware
  • BasicAuth_Example
  • Github_OAuth_Example
  • Asset_Pipeline_OAuth_Update
  • Dropwizard_Metrics

git checkout Lazy_Bones

Screen capture of running lazy_bones tag

git checkout no_frills_site

(run the app and click the below links to see examples)

git checkout API_Handlebars_ContentAware

(run the app and click the below links to see examples)
		
	<!DOCTYPE html>
	<html>
	  <head>
	    <meta charset="utf-8">
	    <title>Accept registration</title>
	  </head>
	  <body>
		<h1>Welcome @{{twitterHandle}}!</h1>
	  </body>
	</html>
	
	

API_HANDLEBARS_CONTENTAWARE

(API endpoint)

(run the app and click the below links to see examples) Successful call
			curl -d "message=Groovy is Gr8" \
		http://localhost:5050/api/sendGroupMessage/javazquez

	 user javazquez says 'Groovy is Gr8'
	
	
Custom Error

	prefix("api"){
	    //add a more specific api error handler rather than global SiteErrorHandler
	    register { add(ApiErrorHandler, new ApiErrorHandler()) }
	    post('sendGroupMessage/:user'){
	      def tokens = get(PathBinding).allTokens
	      parse(Form).then{ form ->
	        render "user ${tokens.user} says '${form.get('message')}'"
	      }
	    }		
		


Content Aware

git checkout BasicAuth_Example

(run the app and click the below links to see examples)

git checkout Github_OAuth_Example

(run the app and click the below links to see examples)

git checkout Asset_Pipeline_OAuth_Update


screen capture of web console proving asset pipeline is working

Asset Pipleline

  • Asset Bundling
  • Extensible Modules (Supports LESS, Handlebars, Coffeescript, Ember-Handlebars, SASS) via other modules.
  • Cache Digest Names (Creates cache digested names and stores aliases in a manifest.properties)
  • Js Minification
  • Js SourceMap Generation
  • Css Minification / Relative Path assertion
  • File Encoding Support
  • GZIP File Generation
  • Last-Modified Header

git checkout Dropwizard_Metrics

(run the app and click the below link to see the example)
  • http://localhost:5050/metrics
  • other topics

    • rxjava
    • springboot
    • hystrix
    • various external configuration options

    Thank you

    questions?