Grooscript
Grails

Introduction

This plugin convert your groovy code to javascript, allowing to use your groovy code in your browser. You can convert groovy classes, scripts, or pieces of groovy code in your gsp’s. Also, you can use your domain classes in your browser, bind inputs to groovy objects, create html code with a groovy builder, …

So, your groovy code running in your browser, sound good!

Important

This plugin deprecate old grooscript vert.x plugin. So, use this one from Grails 2.4. You can see in action in this guide.

I want to say thank you to @graemerocher, @marioggar and @burtbeckwith for helping at some point with this plugin. Also thanks for feedback at @gr8conf. I have to learn a lot about Grails, any help is always welcome.

I have a lot of ideas to improve this plugin, compile static your templates, improve phantomJs tests or domain classes options,… but I don’t know if people use or is interested in this plugin. So, if you want or need something, just open the issue or improvement in Github or grooscript@gmail.com

I have created this documentation with asciidoctor!

Requisites

It requires Grails 2.4+, assets pipeline and cache plugin.

  • Use <asset:deferredScripts/> in your gsp’s with grooscript tags.

  • You have to import grosscript-grails.js when you use grooscript.

  • Plugin use jquery, so remember add that dependency.

  • Work with domain classes still experimental, don’t use in production.

What is new in 0.8

  • Upgrade to grooscript 1.0.0

  • Helper classes are now HtmlBuilder, GQuery and Observable, removed binder

  • Remove daemon, now convert files or use daemons is managed by gradle plugin

What is new in 0.7

  • Upgrade to last changes in grooscript 0.6.2

What is new in 0.6

What is new in 0.5

  • Convert groovy code to javascript in your gsp’s.

  • Convert groovy files to javascript with conversion daemon.

  • Use your domain classes in your browser.

  • Create html code with a html builder dsl.

  • Use grooscript helper classes as binder.

Grooscript

This little framework is the engine of the plugin. It converts Groovy code to javascript. You don’t need to know Grooscript, the plugin do the work for you. But you can take a look to http://grooscript.org/doc.html to get more info. Grooscript compile the code, inspect the AST tree, and generate the javascript code.

Just remember you need grooscript-grails.js to run converted code. Add <asset:javascript src="grooscript-grails.js"/ to your gsp.

Spring bean

There is grooscriptConverter bean, that you can inject in your grails artifacts:

class MyController {

    def grooscriptConverter

    def index() {
        def jsCode = grooscriptConverter.toJavascript('any groovy code')
        def jsCode = grooscriptConverter.toJavascript('any groovy code', conversionOptions)
    }
}

All conversion done with bean or tags, use classPath 'src/groovy' by default.

Grails helpers

Grooscript and this plugin offer some helpers to work with html, javascript or grails from your groovy code.

You can use GrooscriptGrails class from your groovy code:

package org.grooscript.grails.util

class GrooscriptGrails {
    static sendClientMessage(String channel, message) (1)
    static doRemoteCall(String controller, String action, Map params, Closure onSuccess, Closure onFailure) (2)
}
1 Send a message to event listeners
2 Do a remote ajax call

Tags

<grooscript:code>

You can put your Groovy code in gsp’s using this tag. The groovy code is converted to javascript code and inserted in your page with a asset.script tag. In Groovy code inside, maybe Grails can try use it, for example if you put ${something}. If your code use other sources of your application, then that dependency will be converted too. A little cleanup is done in generated code, if your code references something that don’t find in the context, then be sure will be available in execution time in the client side.

Generated code is prepared to run with other generated code, not for be called from javascript. For example if you create a function that expects a groovy map, then you can have problems if a javascript object is passed. There is no problem with strings or numbers, but if you get a javascript array or object, then no groovy map and list functions. Also if you convert an object, and you want to create in your javascript code, var item = new Item(); doesn’t work, you have to do var item = Item();. All goes smooth if you do all in Groovy, for example converting a script like:

<grooscript:code>
    def sing = { name ->
        console.log 'Singing...' + name
    }

    def doSomething = { mapOfClosures ->
        mapOfClosures.each { key, value ->
            value(key)
        }
    }

    $(document).ready doSomething([groovy: sing, grails: sing, grooscript: sing])
</grooscript:code>

<grooscript:onEvent>

You can react to events launched in the client. In your gsp, there is a variable called gsEvents that implements this:

interface EventHandler {
    void sendMessage(String channel, Map data)
    void onEvent(String channel, Closure action)
    void close()
}

Can react or launch events at any point, using gsEvents variable:

<grooscript:code>
    $(document).ready {
        def eventData = 'Application started.'
        gsEvents.sendMessage('newEvent', eventData)
        gsEvents.onEvent('delete', { book ->
            $('#deleteEvent').html 'Deleted ' + book.title
        })
    }
</grooscript:code>

Also can use grooscript:onEvent to react to any event launched. Param name of the event is mandatory. A variable called event is available inside with the data of the event.

<grooscript:onEvent name="myCustomEvent">
    console.log event
</grooscript:onEvent>

<grooscript:template>

You can create html templates using this tag. A template is a piece of groovy code that will be executed inside a html builder. So you generate javascript code that will run as a DSL(HtmlBuilder). In groovy exists some html builders, this is a simple one, that is available inside grooscript js libs. For example:

<grooscript:template>
    ul {
        5.times { number ->
            li "${number} li item"
        }
    }
</grooscript:template>

This tag transform the code in a javascript function that returns html code. The options of this tag are:

onLoad

by default is true, so the function runs on document ready, and then you html code appears.

functionName

by default a random name is used. But you can define name of the function and use it.

itemSelector

jquery selector of the dom object where html code will be injected.

onEvent

to execute the function when event or events are launched.

You can combine grooscript tags to create dynamic applications in the client side using groovy. The variable data is available inside the template tag, that is the param used in the template function call.

<div id="list"></div>

<grooscript:template onLoad="false" functionName="refreshList" itemSelector="#list">
    ul {
        data.each { book ->
            li {
                p 'Id: ' + book.id + ' Name: ' + book.title
            }
        }
    }
</grooscript:template>

<grooscript:code>
    $(document).ready {
        refreshList [[id: 1, title:'Groovy in Action'], [id: 2, title:'Grails in Action']]
    }
</grooscript:code>

<grooscript:initSpringWebsocket>

Websocket support explained here

If you want to use websockets support, with spring websocket plugin, then you have to activate it in your Config.groovy:

grooscript {
    websockets = 'springWebsocketPlugin'
}

Then, in your gsp, you have to init with:

<grooscript:initSpringWebsocket/>

<!-- or -->

<grooscript:initSpringWebsocket>
    println 'Websocket is up!'
</grooscript:initSpringWebsocket>

You can put groovy code inside the tag, and that code will run in your browser after websocket connection done.

<grooscript:onServerEvent>

You can react to websocket events from the server:

<grooscript:onServerEvent path="/topic/hello">
    $("#helloDiv").append '<p>'+data+'</p>'
</grooscript:onServerEvent>

<grooscript:onServerEvent path="/topic/books" type="Book">
    data.each { book ->
        $("#helloDiv").append '<p>'+book.coolFormat()+'</p>'
    }
</grooscript:onServerEvent>

type is optional parameter with the type name of the data that come from the server.

<grooscript:model>

With this tag you can use your domain classes in the browser / client. Just use the domain classes properties and methods, but data will not be saved in the server. You have like a database in your browser.

This tag is still experimental, don’t use in production.

package test

class Actor {

    String name
    Date birth
    int oscars = 0

    static constraints = {
        name blank: false
    }

    boolean goodActor() {
        oscars > 0
    }
}

Activate use in your gsp’s with:

<grooscript:model domainClass="Actor"/>

In the domainClass you have to put the name of the domain class. The code of the domain class is converted to javascript, and you can use properties and methods in the client. Methods injected to the domain class are:

  • Actor.list()

  • actor.save()

  • Actor.get(id)

  • actor.validate() - only constraint blank is implemented

  • actor.hasErrors()

  • actor.errors() - gets a map of validation errors

  • Actor.count()

  • actor.delete()

Let’s see in action, if you execute it, only first actor will be added to actor list.

<grooscript:code>
    import test.Actor

    def actors = [[name: 'Good Actor', oscars: 2], [name: 'Not so good actor', oscars: 0], [name: '', oscars: 35]]

    actors.each {
        def actor = new Actor(it)
        if (actor.validate() && actor.goodActor()) {
            actor.save()
        }
    }

    Actor.list().each {
        $('#actorList').append '<li>'+it.name+'</li>'
    }
</grooscript:code>

<grooscript:remoteModel>

With this tag you can use your domain classes in the browser / client. The domain class is available in your groovy code and actions on that domain will be performed asynchronous in your server. You have to annotate your domain class as a REST resource with @Resource(uri=/anyUrl). The access to the data is controlled by grails, you can use spring secure rest plugin to secure access to your data.

This tag is still experimental, don’t use in production.

package rest

import grails.rest.Resource

@Resource(uri='/books')
class Book {

    String title
    String author

    static constraints = {
        author nullable: true
    }
}

Activate use in your gsp’s with:

<grooscript:remoteModel domainClass="Book"/>

In the domainClass you have to put the name of the domain class annotated with @Resource. The code of the domain class is converted to javascript, and you can use properties and methods in the client. If you want to see in action, please take a look at this guide.

PhantomJs Tests

The plugin adds a new testing phase, phantomJs, you can run with grails test-app functional:phantomJs or grails test-app :phantomJs. The suffix of this tests are PhantomTest or PhantomTests, that tests have to be in test/functional folder. Just this is a functional testing phase, where you can execute your tests with application up. Is the perfect fit to run your @PhantomJsTest’s. That annotation runs a PhantomJs test, evaluating then code inside the method (converted to javascript). You need PhantomJs installed in your system and setup path in your Config.groovy:

phantomjs.path = '/anyPath/phantomjs'

You have to put complete url of your test environment.

import org.grooscript.asts.PhantomJsTest

class MyPhantomTests extends GroovyTestCase {

    @PhantomJsTest(url='http://localhost:8080/grooscript/main/test')
    void testDefaultController() {
        def title = $("title")
        assert title[0].text=='Title Test',"Title is ${title[0].text}"
    }
}

If you use in Spock, then annotate a private method, and then use from your Spock test. Spock where: clause not working well with phantom test annotation.

For each @PhantomJsTest, a browser is open. If you need create a lot or complex tests, better use Geb that has amazing grails plugin.