Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

Grooscript in Action SpringOne2gx 2015

1.749 visualizaciones

Publicado el

Slides of my presentation in Washington DC

Publicado en: Tecnología
  • Sé el primero en comentar

Grooscript in Action SpringOne2gx 2015

  1. 1. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ SPRINGONE2GX WASHINGTON, DC Grooscript in Action By Jorge Franco Leza @jfrancoleza
  2. 2. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ About me 2 Developer jorge.franco.leza@gmail.com
  3. 3. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Thank you! 3 3 years since first commit
  4. 4. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Agenda • Introduction to grooscript • Convert your groovy code to javascript • Support • PhantomJs and tools • Gradle plugin • Demo • Grails plugin • Working with javascript • Require.js • Future 4
  5. 5. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Introduction to grooscript • Library (jar) • Groovy 2.0+ to javascript ECMA 5 • Apache 2 license • Source code http://github.com/chiquitinxx/grooscript • Converted code needs grooscript.js to run • Tools around: gradle and grails plugins, npm and bower packages • Documentation http://grooscript.org/doc.html • Demos http://github.com/chiquitinxx/grooscript-demos • Try live! http://grooscript.org/conversions.html 5
  6. 6. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Why grooscript? • You have all java / groovy tools to create code in the client side. • Javascript is fast. • Enjoy javascript! Create your own magic. • Don’t repeat code in two languages, isomorphic code. • Use groovy templates everywhere. • Single development environment. • Stop learning “to javascript” things. • Static type if you want to. • But… mainly… because it is… 6
  7. 7. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Groovy 7 Readable Concise Expressive
  8. 8. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ ASTS 8 @Component
 class Counter implements Colorable {
 
 Integer number
 
 void init() {
 number = null
 }
 
 void render() {
 div(class: "widget bg-${randomColor()}") {
 if (number) {
 p 'Number of books'
 em number.toString()
 a(href:"#", class:"button", onclick: 'bookPresenter.showBooks()') {
 yield 'Show'
 }
 } else {
 p 'Counting books...'
 }
 }
 }
 } AST’s Getter / Setters
  9. 9. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ List and maps 9 def start() { def countries = loadCountries(). findAll { it.population > 100000}. unique { it.alpha3Code } countries.each { country -> customSigma.addNode id: country.alpha3Code, x: country.latlng[1], color: ‘purple’ } countries.each { country -> country.borders?.each { border -> this.&hello(border) } } updateNumberCountries countries.size() customSigma.refresh() } Lists and maps
  10. 10. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ DSL's 10 server { get('/') { render Templates.applyTemplate('index.gtpl') } on('login') { data, socket -> if (data.name && !socket.login) { socket.login = data.name socket.emit 'loginok', [name: data.name] socket.broadcast.emit 'loginok', [name: data.name] } } on('msg') { data, socket -> if (data.msg && socket.login) { socket.broadcast.emit 'msg', [msg: data.msg] } } on('disconnect') { socket -> if (socket.login) { socket.broadcast.emit 'off', [name: socket.login] } } }.start() Dsl’s
  11. 11. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Metaprogramming 11 class Hello { def methodMissing(String name, args) { println "Hello ${name}!" } } def hello = new Hello() hello.Groovy() hello.Javascript() hello.grooscript() Metaprogramming
  12. 12. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Functional 12 def plus2 = { it + 2 } def times3 = { it * 3 } def times3plus2 = plus2 << times3 assert times3plus2(3) == 11 def plus2times3 = times3 << plus2 assert plus2times3.curry(5)() == 21 Functional
  13. 13. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Convert your groovy code to javascript 13 @Grab('org.grooscript:grooscript:1.2.0') import org.grooscript.GrooScript String result = GrooScript.convert ''' def sayHello = { println "Hello ${it}!" } ['Groovy','JavaScript','GrooScript'].each sayHello ''' new File(‘out.js’) << result
  14. 14. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Convert your groovy code to javascript 14 Let’s see it in action http://grooscript.org/doc.html
  15. 15. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Conversion options • classpath • customization { -> ast(TypeChecked)} • initialText, finalText • recursive • mainContextScope [''$'', ‘'window'', ''myFunction''] • addGsLib • requireJsModule • consoleInfo • includeDependencies 15
  16. 16. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Support • Groovy core • Classes, numbers, lists, maps, sets, date, ranges, closures, (g)strings, operators, groovy truth, Expando, categories, traits, beans, switch, metaprogramming, enum, equals, multiple assignment, optional params, default constructor, pointer methods, operator overload, regular expressions, @Delegate, @Category, … • Dsl’s. (@DelegatesTo) • Ast’s at semantic analysis phase. • Packaging in js with require.js. • Be groovier! 16
  17. 17. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Not supported • Not groovy-core (json, builders, I/O, …) • Java / Groovy Types (Thread, LinkedHashMap, Stack, Optional, …) • Super except constructors. • Methods with same name (overload), classes with same name. • Java 8 stuff not supported by groovy • Module extensions, complex metaprogramming, groovy AST’s after Semantic Phase 17
  18. 18. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Annotations 18 import org.grooscript.asts.GsNotConvert @GsNotConvert class ClassNotConvert { def a } class A { @GsNotConvert def methodNoConvert() { ‘No!’ } def hello() { println ‘Hello!’ } } import org.grooscript.asts.GsNative class Data { @GsNative void saySomething(String smt) {/* console.log(smt); */} @GsNative def five() {/* return 5; */ 1 + 1 + 3 } }
  19. 19. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ PhantomJs test 19 @GrabConfig(systemClassLoader = true) @Grab(‘org.grooscript:grooscript:1.2.0’) import org.grooscript.asts.PhantomJsTest //Need phantomjs installed System.setProperty(‘PHANTOMJS_HOME’, ‘path/to/phantomjs’) @PhantomJsTest(url = 'http://beta.groovy-lang.org/') void testCountLinks() { def links = $('a') assert links.size() > 40, "Number of links: ${links.size()}" links.toArray().collect { it.toString() }.each { link -> println link } } testCountLinks()
  20. 20. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Javascript libs • grooscript.js (87 kb) (8 kb minified and gziped) • grooscript.min.js (33 kb) • grooscript-tools.js (14 kb) (GQuery, HtmlBuilder, Observable) 20
  21. 21. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ HtmlBuilder 21 given: def result = HtmlBuilder.build { body { ul(class: 'list', id: 'mainList') { 2.times { number -> li number + 'Hello!' } } } } expect: result == "<body><ul class='list' id=‘mainList'> <li>0Hello!</li><li>1Hello!</li></ul></body>"
  22. 22. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ GQuery 22 import org.grooscript.jquery.GQueryImpl def result = new Result() def gQuery = new GQueryImpl() gQuery.onReady { gQuery.doRemoteCall(“${JSON_ADDRESS}”, 'GET', null, { res -> gQuery('.result').html('OK') result = res }, { result = 'FAIL!' }, Result) } https://github.com/chiquitinxx/grooscript/blob/master/src/ main/groovy/org/grooscript/jquery/GQuery.groovy
  23. 23. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Observable 23 given: def result = [] Observable.from([1, 5, 9, 12, 3, 8]). filter { it < 5 }. map { 'H' * it }. subscribe { event -> result << event } expect: result == ['H', 'HHH'] https://github.com/chiquitinxx/grooscript/blob/master/src/ test/groovy/org/grooscript/rx/ObservableSpec.groovy
  24. 24. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Gradle plugin • Starting guide http://grooscript.org/starting_gradle.html • Listen to changes and does conversions in background. • Groovy templates in the client side. • Can use with your grails 3+ application. • Create require.js modules. • Notification of changes using websockets. • Thread tasks can block execution. • Info about tasks http://grooscript.org/gradle/tasks.html 24
  25. 25. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ task convert Convert groovy files to javascript. Can add conversion options. 25 grooscript { source = ['src/main/groovy'] destination = 'js' }
  26. 26. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 26 task convertThread grooscript { source = [‘src/main/groovy/presenters'] destination = 'js' classpath = ['src/groovy'] initialText = '//Converted file' recursive = true blockExecution = true } Listen to changes in groovy files, and convert them to javascript when modified. Can block gradle execution.
  27. 27. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 27 task initStaticWeb "## build.gradle $## src $## main "## groovy % $## Presenter.groovy $## webapp "## index.html $## js "## app $## lib "## grooscript-tools.js "## grooscript.min.js $## jquery.min.js Creates a static web project to starting play with grooscript.
  28. 28. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 28 task templatesJs class Templates { static Map<String, Closure> templates static String applyTemplate(String name, model = [:]) { Closure cl = templates[name] cl.delegate = model cl(model) } } Convert groovy templates to a javascript file.
  29. 29. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 29 task templatesThread templates { templatesPath = 'templates' templates = ['main.gtpl', 'little/small.tpl'] destinationFile = 'js/Templates.js' classpath = ['src/groovy'] customTypeChecker = 'aCustomTypeCheckerFile.groovy' } Listen to changes in groovy templates and generate a new javascript template file when something changes. Can block gradle execution.
  30. 30. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 30 task spyChanges spy { files = ['Templates.js'] onChanges = { list -> springWebsocketTo 'http://localhost:8080/demo' data 'templates' onChannel '/app/reload' } } Listen to file changes and execute groovy code when files change. Can send a message using websockets.
  31. 31. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 31 task requireJs requireJs { sourceFile = 'src/main/groovy/MyApp.groovy' destinationFolder = 'src/main/resources/web/js/app' } Convert groovy file to require.js javascript module. Also all dependencies are converted.
  32. 32. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ task requireJsThread 32 requireJs { sourceFile = ‘starting/InitialFile.groovy' classpath = ['src/main/groovy'] destinationFolder = ‘js/app' blockExecution = true } Listen to changes in groovy file or any dependency file, and generate require.js javascript modules when files change. Also can block execution.
  33. 33. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 33 Demo gradle books More action https://github.com/chiquitinxx/books-demo
  34. 34. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Grails plugin • A grails 2 version, 0.8 https://grails.org/plugin/grooscript. • Grails 3 version, version 1.1.2, documentation http://grooscript.org/grails3-plugin. • Adding tags for your gsp’s. • Converting files with gradle plugin in grails 3+. • Using your domain classes in your gsp’s. *experimental* • Uses asset pipeline and cache plugins, also jquery for some tags. • Requires <asset:javascript src="grooscript-grails.js"/> • Events in your gsp's with groovy. • Websockets support using spring websockets. • Templating in your gsp’s with HtmlBuilder. 34
  35. 35. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ grooscript:code 35 <grooscript:code> [‘groovy’, ‘javascript’].each { println “Hello $it” } </grooscript:code> <asset:script> … js code … </asset:script>
  36. 36. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ grooscript:template 36 <grooscript:template onLoad=“false" functionName=“refreshList"> ul { data.each { book -> li { p 'Id: ' + book.id + ' Name: ' + book.title } } } </grooscript:template>
  37. 37. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ websockets 37 <grooscript:initSpringWebsocket> println 'Connected! Websocket is up!’ GrooscriptGrails.sendWebsocketMessage("/app/hello", “Hello!") </grooscript:initSpringWebsocket> <grooscript:onServerEvent path="/topic/books" type="Book"> data.each { book -> $("#helloDiv").append '<p>'+book.coolFormat()+'</p>' } </grooscript:onServerEvent> Use spring websockets in your gsp’s. Have to include client libraries.
  38. 38. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ events 38 <grooscript:code> $(document).ready { def eventData = 'Application started.' gsEvents.sendMessage('newEvent', eventData) gsEvents.onEvent('delete', { book -> $('#deleteEvent').html 'Deleted ' + book.title }) } </grooscript:code> <grooscript:onEvent name="newEvent"> console.log event </grooscript:onEvent> Manage events in the client using groovy.
  39. 39. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ grooscript:remoteModel 39 <grooscript:remoteModel domainClass="Book"/> <grooscript:code> import rest.Book Book.list().then { list -> $('#bookList').html '' list.each addBook } </grooscript:code> Use your domain classes from your gsp’s. Domain classes annotated with @Resource, using json.
  40. 40. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Demo grails 3 40 Final action https://github.com/chiquitinxx/circles
  41. 41. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Working with javascript 41 class MyClass {} function MyClass() { … } var myClass = MyClass(); // NO var myClass = new MyClass(); var myClass = MyClass({prop1: ‘value’, prop2: 12 }); myClass.method(); // NO myClass.metaprogrammingMethod(); myClass.method(numberOrStringOrList); // beware maps! myClass.method({ a: 1, b: 2 });
  42. 42. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Combine both worlds 42 import static org.grooscript.GrooScript.toJavascript import static org.grooscript.GrooScript.toGroovy def map = [x: 1, y: 2] //point is a javascript object point.init(map) //[BAD] Passing a groovy object to javascript, can fail point.init(toJavascript(map)) //[GOOD] You now are passing {x: 1, y: 2} //point has a method info() that returns a javascript object def badData = point.info() //[BAD] You will have a 'javascript' object def goodData = toGroovy(point.info()) //[GOOD] goodData as a 'groovy' object
  43. 43. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Tips • Keep your groovy code tested. • If you use @GsNative, keep that code in isolated classes, that can be easy to mock them. • Don’t abuse @GsNative, is untested code. • You can activate debug console info in javascript with gs.consoleInfo = true; • You can test dom manipulation with jsoup. • Try to stay functional, don’t abuse ‘this’ or variables from other contexts. • Curry functions to inject variables rather than expecting them to be available after callbacks hell. 43
  44. 44. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Require.js • Javascript file and module loader. • Can be used in browser, rhino and Node.js environments. • Optimization using google closure compiler. 44 requirejs.config({ baseUrl: 'jsModules', paths: { lib: 'js/lib' } }); requirejs(['lib/grooscript.min'], function() { requirejs(['Initial']); });
  45. 45. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Require.js 45 import org.grooscript.GrooScript Map conversionOptions = [classpath: 'src/main/groovy'] GrooScript.convertRequireJs('src/main/groovy/Initial.groovy', 'jsModules', conversionOptions) define(function() { function Initial() { … } return Initial; }); class Initial { } src/main/groovy/Initial.groovy jsModules/Initial.js
  46. 46. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Require.js 46 define(['lib/data'], function (data) { function Require() { //.. gSobject.data = data; //.. return gSobject; }; return Require; }); package files import org.grooscript.asts.RequireJsModule class Require { @RequireJsModule(path = 'lib/data') def data } src/main/groovy/files/Require.groovy jsModules/files/Require.js
  47. 47. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Future 47 ECMAScript 2015
  48. 48. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 48 Q & A
  49. 49. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software, Inc. and licensed under a
 Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Thank you! 49 Waiting for your feedback and questions from now to Thursday

×