There is no special integration support for Ratpack, just with the grooscript gradle plugin you can convert your groovy files to javascript and use in your browser. You can use this plugin with any other framework or library, for example Grails.

The source code of this demo is available in github. A similar application done with Spring Boot is deployed in http://ecosystem-gr8.rhcloud.com/, and the source code also here. This is my first application using Ratpack, any pull request to improve it is more than welcome. I don’t use any database, only a little static class with the frameworks added.

Is a single page, to see a list of groovy libraries o frameworks. You can add new frameworks filling at least name and url, can include link to external image for logo.

Demo

Setup

I’m using Ratpack gradle plugin, and I have added grooscript gradle plugin in build.gradle:

apply plugin: 'org.grooscript.conversion'
apply plugin: "io.ratpack.ratpack-groovy"
apply plugin: "idea"

repositories {
    jcenter()
}

dependencies {
    runtime "org.slf4j:slf4j-simple:1.7.12"
    compile('org.grooscript:grooscript:1.2.1') {
        exclude module: 'groovy'
        exclude module: 'groovy-json'
    }

    testCompile "org.spockframework:spock-core:1.0-groovy-2.4"
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.7'
}

grooscript {
    source = ['src/main/groovy/frameworks/FrameworksPresenter.groovy'] (1)
    destination = 'src/ratpack/public/scripts' (2)
    classpath = ['src/main/groovy'] (3)
    includeDependencies = true (4)
}

run.dependsOn convertThread (5)
1 The groovy file that will be converted to javascript.
2 Folder where FrameworksPresenter.js will be saved.
3 Classpath needed to compile groovy file.
4 If you use any other groovy class in FrameworksPresenter.groovy, that classes will be converted too, and added to .js file.
5 While Ratpack application is running in development, any modification done in FrameworksPresenter.groovy, will convert a new .js file.

Ratpack server

The server does two things, serve the index page, and add the new frameworks to the database.

import frameworks.*
import ratpack.form.Form
import ratpack.groovy.template.MarkupTemplateModule

import static ratpack.groovy.Groovy.groovyMarkupTemplate
import static ratpack.groovy.Groovy.ratpack
import static ratpack.jackson.Jackson.json

ratpack {
    bindings {
        module MarkupTemplateModule (1)
    }

    handlers {
        get {
            def htmlFrameworks = FrameworksView.htmlFrameworks(FrameworksDb.listFrameworks)(2)
            render groovyMarkupTemplate([htmlFrameworks: htmlFrameworks], "index.gtpl")(3)
        }

        post('addFramework') {
            parse(Form).then { readForm ->
                Framework framework = new Framework(readForm)
                def valErrors = framework.validate() (4)
                if (!valErrors && FrameworksDb.addNewFramework(framework)) {
                    render json(framework) (5)
                } else {
                    render null
                }
            }
        }

        files { dir "public" } (6)
    }
}
1 Module to use groovy template engine.
2 Get the html of all the frameworks in the 'database'.
3 Render the groovy template, sending the frameworks html.
4 Validate the framework in the server.
5 Send the validated framework back to client.
6 Location of static files (css, js, …​).

Index page

For more info about groovy templates engine go here. Our index page index.gtpl:

body {
  head {
        div(id: "newFramework") {
        p { (1)
          yield 'Name:';input(type: 'text', id: 'nameFramework');yield '*'
        }
        p {
          yield 'Url framework:';input(type: 'text', id: 'urlFramework');yield '*'
        }
        p {
          yield 'Url image framework:';input(type: 'text', id: 'urlImageFramework')
        }
        input(type:"button", class:"doButton", id:"buttonAddFramework", value:"Add framework",
               'data-anijs': "if: mousedown, do: shake animated, to: #validationError") {} (2)
        div(id: "validationError") {} (3)
        div(id: "mainTitle", 'data-anijs':"if: mouseenter, do: tada animated") {
          yield 'Groovy Frameworks'
        }
        }
  }

  section {
      div model.htmlFrameworks (4)
  }

  ["lib/jquery-1.11.1.min.js", "lib/anijs-min.js", "lib/grooscript.min.js",
      "lib/grooscript-tools.js", "scripts/FrameworksPresenter.js"].each {
      script(src: it) {} (5)
  }
  script {
      yield '''
          jQuery(document).ready(function() {
              FrameworksPresenter({gQuery: GQueryImpl()}).start(); (6)
          });
      '''
  }
}
1 New framework input fields.
2 Button to validate the input fields and send to the server.
3 Where validation and error messages are shown.
4 Draw the frameworks list html from the model passed to the template.
5 Javascript libraries needed.
6 Javascript code to start the presenter.

Anijs is used for nice animations, jQuery is used by grooscript-tools to do jQuery stuff, FrameworksPresenter.js is the javascript conversion of FrameworksPresenter.groovy and finally grooscript.js is needed to run any javascript code converted by grooscript.

Source code

I’m using a MVP pattern for this little application. Is groovy code that will run in the client side, as javascript code. You can run the code in groovy and test it with any java / groovy test framework. Now I’ll show all the source code, the code itself is not important, the important thing is that is groovy and is running in your browser.

The logic on my application is in FrameworksPresenter.groovy:

package frameworks

import org.grooscript.jquery.GQuery

class FrameworksPresenter {

    String nameFramework
    String urlFramework
    String urlImageFramework
    GQuery gQuery
    View view

    void start() {
        gQuery.bindAll(this)
        if (!view) view = new FrameworksView()
    }

    void buttonAddFrameworkClick() {

        def framework = new Framework(name: nameFramework, url: urlFramework, urlImage: urlImageFramework)
        def errors = framework.validate()
        if (!errors) {
            addFramework(framework, {newFramework ->
                view.addNewFramework newFramework
            }, {error ->
                view.putError('Error from server: ' + error)
            })
        }
        view.putError errors.join(' - ')
    }

    void addFramework(Framework framework, Closure onAdded, Closure onError = null) {
        gQuery.doRemoteCall('/addFramework',
                'POST', [name: framework.name, url: framework.url, urlImage: framework.urlImage],
                onAdded, onError, Framework)
    }
}

GQuery comes with grooscript, and is a wrap to work with jQuery.

The presenter connects with the view FrameworksView.groovy:

package frameworks

import org.grooscript.asts.GsNative
import org.grooscript.builder.HtmlBuilder

class FrameworksView implements View {

    String frameworksListSelector = '#listFrameworks'
    String errorSelector = '#validationError'

    static String htmlFrameworks(List<Framework> frameworks) {
        HtmlBuilder.build {
            ul(id: 'listFrameworks') {
                frameworks.each { framework ->
                    yieldUnescaped htmlFramework(framework)
                }
            }
        }
    }

    static String htmlFramework(Framework framework) {
        HtmlBuilder.build {
            li {
                div(class: 'logo', 'data-anijs': 'if: mouseenter, do: flip animated') {
                    if (!framework.hasImage() && framework.githubUrl()) {
                        img src: 'images/github.png'
                    } else {
                        img src: framework.hasImage() ? framework.urlImage : 'images/nologo.png'
                    }
                }
                a (href: framework.url, framework.name)
            }
        }
    }

    void addNewFramework(Framework framework) {
        append frameworksListSelector, htmlFramework(framework)
    }

    void putError(String errorMessage) {
        putHtml errorSelector, errorMessage
    }

    @GsNative
    void putHtml(String selector, String html) {/*
        $(selector).html(html);
    */}

    @GsNative
    void append(String selector, String html) {/*
        $(selector).append(html);
        AniJS.run();
    */}
}

We use another grooscript feature, HtmlBuilder to create html code with a DSL, and it works in groovy and in javascript importing grooscript-tools.js. Also you can see I’m inserting javascript code with @GsNative.

Finally the framework class with validations included, validations that are used in the server and in the client side, without repeating code.

package frameworks

class Framework {

    String name
    String url
    String urlImage

    List<String> validate() {
        def validationErrors = []

        if (!name) {
            validationErrors << 'Missing name framework'
        }
        if (!url) {
            validationErrors << 'Missing url framework'
        }
        if (url && !validUrl(url)) {
            validationErrors << 'Wrong url framework'
        }
        if (urlImage && !validUrl(urlImage)) {
            validationErrors << 'Wrong url image'
        }
        if ([name, url, urlImage].any(hasEvilChars)) {
            validationErrors << 'Wrong chars'
        }
        validationErrors
    }

    boolean hasImage() {
        urlImage && ['.GIF', '.PNG', '.JPG'].any { urlImage.toUpperCase().endsWith(it)}
    }

    boolean githubUrl()  {
        url.contains('github.com')
    }

    private boolean validUrl(url) {
        ['http://', 'https://'].any { url && url.startsWith(it) }
    }

    private Closure hasEvilChars = { data ->
        data ? data.indexOf('<') >= 0 : false
    }

    boolean equals(Object other) {
        other instanceof Framework && other.name == this.name
    }
}

To play with grooscript, clone the source code and run with > ./gradlew run. Now you can modify the source groovy files, each time you update that file, the .js file will be generated again, and you can reload the page http://localhost:5050/ to see the changes.

Beyond this demo

Take a look at grooscript documentation to check what is supported by grooscript.

The grooscript gradle plugin has more features, as work with groovy templates in the browser, or create Require.js modules, or notify the server file changes using websockets. You can follow this getting starting guide to understand better grooscript and the gradle plugin.

Visit grooscript.org for more info. Thank you for your time!