grooscript gr8conf
DESCRIPTION
Grooscript is an open source project, a little framework that convert groovy code to javascript, more info in grooscript.org. Javascript is cool now, a vibrant community with many new developments. Web development is moving to client size and you must be start to worry about javascript and all the new awesome tools for it. With grooscript, you can join this new wave with our lovely groovy. You can code all the logic of your application in groovy, test with spock, use gradle or any other java or groovy framework. Grooscript will convert your application code to javascript and then you can use it in the browser or Node.js. In this talk I will introduce about grooscript, how started, how can be used, explore its limitations,… Also I will show grooscript grails plugin, and what do you can do with it. We will take a look at Node.js plugin and gradle plugin, and how to use this tools. I will show some demos of different ways to use grooscript.TRANSCRIPT
About me
Developer, I love it
Lazy in english at school
Living in Madrid
Working at Osoco
Grooscript developer
@jfrancoleza
The players
Web developer
Leave your comfort zone
Move to the client side
Doesn’t run!
on browsers
Do something! No excuses
You can do a library, resolve issues, create a plugin, give feedback,
help other projects, … !
You will learn a lot
The wire
Groovy to Javascript converter
Groovy 2 to Javascript ECMAScript 5
Open source project, Apache 2 license
Library with Groovy and GPars dependencies
No special Javascript objects or functions
Converted code requires grooscript.js to run
Different conversion options
Grails plugin, npm package, gradle plugin
What is grooscript?
File.groovy File.js
Conversion!Options
grooscript.js
Convert Groovy files
Groovy code
def sayHello = { -> println "Hello ${it}!" }[‘Groovy', ‘JavaScript', 'GrooScript'].each sayHello!assert [1, 2, 3].size() == 3class Amazing {}!amazing = new Amazing()amazing.metaClass.who = []amazing.metaClass.add = { who << it}!amazing.add 'Rafa Nadal'assert amazing.who.size() == 1
Javascript result
function Amazing() { var gSobject = gs.inherit(gs.baseClass,'Amazing'); gSobject.clazz = { name: 'Amazing', simpleName: 'Amazing'}; gSobject.clazz.superclass = { name: 'java.lang.Object', simpleName: 'Object'}; if (arguments.length == 1) {gs.passMapToObject(arguments[0],gSobject);}; return gSobject;};var sayHello = function(it) { return gs.println("Hello " + (it) + "!");};gs.mc(gs.list(["Groovy" , "JavaScript" , "GrooScript"]),"each",[sayHello]);gs.assert(gs.equals(gs.mc(gs.list([1 , 2 , 3]),"size",[]), 3), null);amazing = Amazing();gs.sp((amazing = gs.metaClass(amazing)),"who",gs.list([]));gs.sp((amazing = gs.metaClass(amazing)),"add",function(it) { return gs.mc(gs.fs('who', this),'leftShift', gs.list([it]));});gs.mc(amazing,"add",["Rafa Nadal"]);gs.assert(gs.equals(gs.mc(gs.gp(amazing,"who"),"size",[]), 1), null);
Class
Default constructor
Function
New
Javascript
GroovyJava
More Ja
vasc
ript fr
iendly
Types, inheritance, java 8, …
metaClass
Lists
Closures
Operators
Dsl’s
Expando
Maps
beans
methodMissing
Mixins
Categories
Traits
delegate
propertyMissing
Using converted code in javascript
Create classes NameClass();
Default constructor with js object NameClass({property: value, data: 1});
Call methods, basic parameters myObject.method(params);
Access properties myObject.property = 4;
Use functions as closures list.each(function () { … });
Traits
Metaprogramming
Mixins, Categories
Groovy types gs.map({});
gs.set(); gs.range(1, 5);
gs.date(); gs.regExp();
gs.stringBuffer(); …
Groovy list functions added to js lists
Added some functions to numbers and strings (1).times(function () {}); “Groovy”.startsWith(); “Hello”.replaceAll();
Added curry to functions
Convert objects ‘to groovy’ or ‘to javascript’ gs.toGroovy(javaScriptList, NameClass);
gs.toJavascript(myGroovyObject);
Operators Groovy truth
equals getters and setters
Conversions gs.toGroovy(obj, Type);
gs.toJavascript();
LimitationsGroovy / Java not fully supported Working in groovy-core No good support for inheritance (super) No methods with same name Basic support in metaClass No packages, no classes with same name No metainfo, expandoMetaClass, … Only AST transformations applied in semantic phase No complex Java / Groovy types (LinkedList,…) … see documentation for more info on grooscript.org
Directly convert code
@Grab(‘org.grooscript:grooscript:0.5’)!import org.grooscript.GrooScript!//Convert a fragment codeString jsResult = GrooScript.convert(“println ‘Hello!’”)!//Convert some file or folder, generate .js files with same nameGrooScript.convert(‘path/to/file.groovy’, ‘destination/folder’)GrooScript.convert(‘path/to/folder’, ‘destination/folder’)GrooScript.convert(listOfFilesAndOrFolders, ‘destination/folder’)
Conversion options
convertDependencies - boolean - default true
classPath - List<String> or String - default null - Ex: ‘src/groovy’
customization - Closure - default null
mainContextScope - List<String> - default null
initialText / finalText - String - default null
recursive - boolean - default false
//Set a conversion propertyGrooScript.setConversionProperty(‘convertDependencies’, false)GrooScript.setConversionProperty(‘customization’, { ast(TypeChecked)})
Convert dependencies option
Car.groovy
Wheel.groovy
Car.jsconvert
== optionwheel code
included
Main context scope
Customization
• Requires Groovy 2.1, the closure is passed to withConfig(conf)
• More info in http://docs.codehaus.org/display/GROOVY/Advanced+compiler+configuration
• Sometimes you don’t know where to find a variable
• When conversion is done, some variables come from other contexts
• grooscript.js sometimes tries to find missed variables with eval
• Node.js eval not working same way that browsers do
• You can define variables or function names with this option
• Ex. [‘$’, ‘myAwesomeFunction’, ‘myMissedVariable’]
Feature: Annotations
@GsNotConvert @GsNative
Feature: Daemon
>phantomjs myTest.js
Inject grooscript.js and jquery
Use Groovy script abilities
I want to be Groovy
@AST
http://phantomjs.org/
Please code in Groovy!
Mandatory Screen capture Before start test
More console infoAccept basic parameters
Works fine in GroovyTestCaseNot so well in Spock
Have to define
Phantom.js path
Feature: PhantomJsTest
Example
@GrabConfig(systemClassLoader = true)@Grab(‘org.grooscript:grooscript:0.5’)!import org.grooscript.asts.PhantomJsTest!//Need phantoms installedSystem.setProperty(‘PHANTOMJS_HOME’, ‘path/to/phantomjs’)!@PhantomJsTest(url = ‘http://www.grails.org’)void grailsSiteChecks() { assert $(‘a’).size() > 50, “Not enough links ${$(‘a’).size()}” def title = $(“title”) assert title[0].text == ‘Grails - The search is over.’ $(‘a’).each { println it }}!//Run phantomjs testgrailsSiteChecks()
package org.grooscript.builder!class HtmlBuilder {! String html! static String build(@DelegatesTo(HtmlBuilder) Closure closure) { def mc = new ExpandoMetaClass(HtmlBuilder, false, true) mc.initialize() def builder = new HtmlBuilder() builder.metaClass = mc closure.delegate = builder closure()! builder.html }! def yield(String text) { html += text }! def methodMissing(String name, args) { … }}
Feature: html builder
def result = HtmlBuilder.build { body { ul(class: 'list', id: 'mainList') { 2.times { number -> li number + 'Hello!' } } }}!assert result == ‘<body><ul class='list' id='mainList'><li>0Hello!</li><li>1Hello!</li></ul></body>’
grooscript-builder.js
Feature: jquery toolspackage org.grooscript.jquery!interface GQuery { def bind(String selector, target, String nameProperty) def bind(String selector, target, String nameProperty, Closure closure) boolean existsId(String id) boolean existsName(String name) boolean existsGroup(String name) void bindEvent(String id, String name, Closure func) void doRemoteCall(String url, String type, params, Closure onSuccess, Closure onFailure) void doRemoteCall(String url, String type, params, Closure onSuccess, Closure onFailure, objectResult) void onReady(Closure func) void html(String selector, String text)}
import org.grooscript.jquery!GQuery gQuery = new GQueryImpl()
gQueryImpl.js
Feature: binder
grooscript-binder.jspackage org.grooscript.jquery!class Binder {! GQuery gQuery = new GQueryImpl()! def bindAllProperties(target, closure = null) { target.properties.each { name, value -> if (gQuery.existsId(name)) { gQuery.bind("#$name", target, name, closure) } if (gQuery.existsName(name)) { gQuery.bind("[name='$name']", target, name, closure) } if (gQuery.existsGroup(name)) { gQuery.bind("input:radio[name=${name}]", target, name, closure) } } }! def bindAllMethods(target) { target.metaClass.methods.each { method -> if (method.name.endsWith('Click')) { def shortName = method.name.substring(0, method.name.length() - 5) if (gQuery.existsId(shortName)) { gQuery.bindEvent(shortName, 'click', target.&"${method.name}") } } } }! def call(target, closure = null) { bindAllProperties(target, closure) bindAllMethods(target) }}
Bind an instance properties to input elements, by Id or name
Bind on click events to an instance methods
new Binder()(myInstance)
grooscript-binder.js
grooscript.js
grooscript.min.js
grooscript-builder.js
grooscript-all.js
gQueryImpl.js
inside the jar, servlet 3.0: META-INF/resourceshttp://grooscript.org/downloads.html
Websockets with Vert.xhttps://github.com/chiquitinxx/demoGroovyMeteor
http://www.meteor.com
https://vimeo.com/59395085
https://github.com/chiquitinxx/grooscript-vertx-plugin
http://www.grails.org/plugin/grooscript-vertx
v 0.4
Grooscript Vert.x Plugin
Convert Groovy code to Javascript
Run conversion daemon
Websockets
Eventbus bridge
New port openEvents in the client
Auto reload pages
Both are optional
http://grooscript.org/pluginManual/
v 1.3.1
Requires Java 1.7
Differences?Renders on server
Renders on the client
Conversions are cached with cache plugin
Grooscript tags auto - import js files needed
Grails port 8080
Vert.x port 8085
Browser gsp
eventBus
http
websockets
Config.groovy
BootStrap.groovy Chat sample
main.gsp
More eventsHtml Builder
Where
Listen events Render on load
Send event message
= println
Execute on event message
Don’t use ${} in grooscript tags
Strong dependency Resources plugin
Can put code in a .groovy file
Domain classes in the client**Experimental, it requires Groovy 2.1 (grails 2.3)
• validate, clientValidations ** • hasErrors • count • list * without params • get • save * without params • delete
Domain classes connected with the server**Experimental, it requires Groovy 2.1 (grails 2.3)
• list • get • save • delete
PhantomJs Tests**Not working in Grails 2.3, need improvements
New test phase phantomjs
Tests in test/phantomjs
More features
features, features…
next release - new plugin - remove vert.x
From resources plugin to Require.js or Asset pipeline plugin
Improve domain options
PhantomJs tests improvements
Move to websockets/sockJs/stomp with Spring 4 in grails 2.4
and many more…
Remote domain class to grails REST support
https://github.com/chiquitinxx/grooscript-gradle-plugin
v 0.3
Gradle plugin
Add in your build.gradle
http://grooscript.wordpress.com/2014/02/22/starting-with-grooscript/
buildscript { repositories { mavenCentral() } dependencies { classpath 'org.grooscript:grooscript-gradle-plugin:0.3' }}!apply plugin: 'grooscript'!//If you need to change any conversion option, can do this way, optionalgrooscript { source = [‘src/main/groovy/presenters']}
Create more conversion tasks: http://grooscript.wordpress.com/2014/01/31/61/
Converted files destination
Require.js setup file
Files to be converted
Demo springboot
http://projects.spring.io/spring-boot/
REST - Require.js - Grooscript Gradle Plugin - Websockets - Mongo
https://github.com/chiquitinxx/springboot-rest-demo
https://github.com/chiquitinxx/grooscript/tree/master/npm
Example using node.js colors npm module
Node.js is very fast!http://grooscript.wordpress.com/2014/01/10/impressive-node-js-v8-speed/
https://github.com/chiquitinxx/colors
Final topics
Why would I use grooscript?
• Create small modules to use in your views • You can continue developing in Groovy • Can use dsl’s, typeCheck, AST’s,… in the browser • You have all the java tools and IDE’s • You can work with new Javascript tools from Groovy • Don’t repeat code in two languages • Single development environment • Create your own architecture in Groovy • Don’t learn another “to Javascript” tool
Community will decide
Future
Version 0.5, you can improve
I will continue improving grooscript
Never will support full Groovy / Java
I’m learning a lot, very fun
New grails plugin in summer
Focus next version: more and better java and groovy support
Questions?
Thank you!
All people reading this
680 motivation clicks
Jetbrains for IntelliJ IDEA v13 open source license
Special thanks to René, @glaforge @marioggar
@CedricChampeau @burtbeckwith