SlideShare ist ein Scribd-Unternehmen logo
1 von 49
Downloaden Sie, um offline zu lesen
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
}
}
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()
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
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>"
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
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
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
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'
}
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.
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.
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.
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.
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.
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.
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.
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
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
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>
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>
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.
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.
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.
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
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 });
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
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
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']);
});
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
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
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
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
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

Weitere ähnliche Inhalte

Was ist angesagt?

Embedding Groovy in a Java Application
Embedding Groovy in a Java ApplicationEmbedding Groovy in a Java Application
Embedding Groovy in a Java ApplicationPaolo Predonzani
 
Apache Groovy: the language and the ecosystem
Apache Groovy: the language and the ecosystemApache Groovy: the language and the ecosystem
Apache Groovy: the language and the ecosystemKostas Saidis
 
Groovy on the shell
Groovy on the shellGroovy on the shell
Groovy on the shellsascha_klein
 
GraphQL IN Golang
GraphQL IN GolangGraphQL IN Golang
GraphQL IN GolangBo-Yi Wu
 
Introduction to Griffon
Introduction to GriffonIntroduction to Griffon
Introduction to GriffonJames Williams
 
"How to Use Bazel to Manage Monorepos: The Grammarly Front-End Team’s Experie...
"How to Use Bazel to Manage Monorepos: The Grammarly Front-End Team’s Experie..."How to Use Bazel to Manage Monorepos: The Grammarly Front-End Team’s Experie...
"How to Use Bazel to Manage Monorepos: The Grammarly Front-End Team’s Experie...Fwdays
 
2018 (codeone) Graal VM and MicroProfile a polyglot microservices solution [d...
2018 (codeone) Graal VM and MicroProfile a polyglot microservices solution [d...2018 (codeone) Graal VM and MicroProfile a polyglot microservices solution [d...
2018 (codeone) Graal VM and MicroProfile a polyglot microservices solution [d...César Hernández
 
PyCon Korea 2019 REST API Document Generation
PyCon Korea 2019 REST API Document GenerationPyCon Korea 2019 REST API Document Generation
PyCon Korea 2019 REST API Document Generation용선 이
 
Golang Project Layout and Practice
Golang Project Layout and PracticeGolang Project Layout and Practice
Golang Project Layout and PracticeBo-Yi Wu
 
Build microservice with gRPC in golang
Build microservice with gRPC in golangBuild microservice with gRPC in golang
Build microservice with gRPC in golangTing-Li Chou
 
Groovy And Grails Introduction
Groovy And Grails IntroductionGroovy And Grails Introduction
Groovy And Grails IntroductionEric Weimer
 
Understanding how concurrency work in os
Understanding how concurrency work in osUnderstanding how concurrency work in os
Understanding how concurrency work in osGenchiLu1
 
really really really awesome php application with bdd behat and iterfaces
really really really awesome php application with bdd behat and iterfacesreally really really awesome php application with bdd behat and iterfaces
really really really awesome php application with bdd behat and iterfacesGiulio De Donato
 
When third parties stop being polite... and start getting real
When third parties stop being polite... and start getting realWhen third parties stop being polite... and start getting real
When third parties stop being polite... and start getting realCharles Vazac
 
Ratpack - Classy and Compact Groovy Web Apps
Ratpack - Classy and Compact Groovy Web AppsRatpack - Classy and Compact Groovy Web Apps
Ratpack - Classy and Compact Groovy Web AppsJames Williams
 

Was ist angesagt? (20)

Embedding Groovy in a Java Application
Embedding Groovy in a Java ApplicationEmbedding Groovy in a Java Application
Embedding Groovy in a Java Application
 
Rest, sockets em golang
Rest, sockets em golangRest, sockets em golang
Rest, sockets em golang
 
Apache Groovy: the language and the ecosystem
Apache Groovy: the language and the ecosystemApache Groovy: the language and the ecosystem
Apache Groovy: the language and the ecosystem
 
Groovy on the shell
Groovy on the shellGroovy on the shell
Groovy on the shell
 
GraphQL IN Golang
GraphQL IN GolangGraphQL IN Golang
GraphQL IN Golang
 
Introduction to Griffon
Introduction to GriffonIntroduction to Griffon
Introduction to Griffon
 
"How to Use Bazel to Manage Monorepos: The Grammarly Front-End Team’s Experie...
"How to Use Bazel to Manage Monorepos: The Grammarly Front-End Team’s Experie..."How to Use Bazel to Manage Monorepos: The Grammarly Front-End Team’s Experie...
"How to Use Bazel to Manage Monorepos: The Grammarly Front-End Team’s Experie...
 
Golang
GolangGolang
Golang
 
2018 (codeone) Graal VM and MicroProfile a polyglot microservices solution [d...
2018 (codeone) Graal VM and MicroProfile a polyglot microservices solution [d...2018 (codeone) Graal VM and MicroProfile a polyglot microservices solution [d...
2018 (codeone) Graal VM and MicroProfile a polyglot microservices solution [d...
 
Griffon @ Svwjug
Griffon @ SvwjugGriffon @ Svwjug
Griffon @ Svwjug
 
PyCon Korea 2019 REST API Document Generation
PyCon Korea 2019 REST API Document GenerationPyCon Korea 2019 REST API Document Generation
PyCon Korea 2019 REST API Document Generation
 
Golang Project Layout and Practice
Golang Project Layout and PracticeGolang Project Layout and Practice
Golang Project Layout and Practice
 
Gradle in 45min
Gradle in 45minGradle in 45min
Gradle in 45min
 
Build microservice with gRPC in golang
Build microservice with gRPC in golangBuild microservice with gRPC in golang
Build microservice with gRPC in golang
 
Groovy And Grails Introduction
Groovy And Grails IntroductionGroovy And Grails Introduction
Groovy And Grails Introduction
 
Understanding how concurrency work in os
Understanding how concurrency work in osUnderstanding how concurrency work in os
Understanding how concurrency work in os
 
really really really awesome php application with bdd behat and iterfaces
really really really awesome php application with bdd behat and iterfacesreally really really awesome php application with bdd behat and iterfaces
really really really awesome php application with bdd behat and iterfaces
 
Go at Openprovider
Go at OpenproviderGo at Openprovider
Go at Openprovider
 
When third parties stop being polite... and start getting real
When third parties stop being polite... and start getting realWhen third parties stop being polite... and start getting real
When third parties stop being polite... and start getting real
 
Ratpack - Classy and Compact Groovy Web Apps
Ratpack - Classy and Compact Groovy Web AppsRatpack - Classy and Compact Groovy Web Apps
Ratpack - Classy and Compact Groovy Web Apps
 

Ähnlich wie Grooscript in Action SpringOne2gx 2015

Groovy 3 and the new Groovy Meta Object Protocol in examples
Groovy 3 and the new Groovy Meta Object Protocol in examplesGroovy 3 and the new Groovy Meta Object Protocol in examples
Groovy 3 and the new Groovy Meta Object Protocol in examplesGR8Conf
 
Becoming an Advanced Groovy Developer Spring One 2gx 2015
Becoming an Advanced Groovy Developer Spring One 2gx 2015Becoming an Advanced Groovy Developer Spring One 2gx 2015
Becoming an Advanced Groovy Developer Spring One 2gx 2015Tom Henricksen
 
groovy transforms
groovy transformsgroovy transforms
groovy transformsPaul King
 
SpringOne 2GX 2015 - Fullstack Groovy developer
SpringOne 2GX 2015 - Fullstack Groovy developerSpringOne 2GX 2015 - Fullstack Groovy developer
SpringOne 2GX 2015 - Fullstack Groovy developerIván López Martín
 
Migrating from Grails 2 to Grails 3
Migrating from Grails 2 to Grails 3Migrating from Grails 2 to Grails 3
Migrating from Grails 2 to Grails 3Michael Plöd
 
Better Than BASH: Scripting Kotlin
Better Than BASH: Scripting KotlinBetter Than BASH: Scripting Kotlin
Better Than BASH: Scripting KotlinVMware Tanzu
 
Lessons learned from upgrading Thymeleaf
Lessons learned from upgrading ThymeleafLessons learned from upgrading Thymeleaf
Lessons learned from upgrading ThymeleafVMware Tanzu
 
Reactive frontends with RxJS and Angular
Reactive frontends with RxJS and AngularReactive frontends with RxJS and Angular
Reactive frontends with RxJS and AngularVMware Tanzu
 
Not Only Reactive - Data Access with Spring Data
Not Only Reactive - Data Access with Spring DataNot Only Reactive - Data Access with Spring Data
Not Only Reactive - Data Access with Spring DataVMware Tanzu
 
Springone2gx 2015 Cassandra and Grails
Springone2gx 2015 Cassandra and GrailsSpringone2gx 2015 Cassandra and Grails
Springone2gx 2015 Cassandra and GrailsJeff Beck
 
Leveling up your JavaScipt - DrupalJam 2017
Leveling up your JavaScipt - DrupalJam 2017Leveling up your JavaScipt - DrupalJam 2017
Leveling up your JavaScipt - DrupalJam 2017Christian Heilmann
 
Reactive Data Access with Spring Data
Reactive Data Access with Spring DataReactive Data Access with Spring Data
Reactive Data Access with Spring DataVMware Tanzu
 
Under the Hood of Reactive Data Access (1/2)
Under the Hood of Reactive Data Access (1/2)Under the Hood of Reactive Data Access (1/2)
Under the Hood of Reactive Data Access (1/2)VMware Tanzu
 
Zero-config JavaScript apps with RaveJS -- SVCC fall 2014
Zero-config JavaScript apps with RaveJS -- SVCC fall 2014Zero-config JavaScript apps with RaveJS -- SVCC fall 2014
Zero-config JavaScript apps with RaveJS -- SVCC fall 2014John Hann
 
Continuous delivery w projekcie open source - Marcin Stachniuk
Continuous delivery w projekcie open source - Marcin StachniukContinuous delivery w projekcie open source - Marcin Stachniuk
Continuous delivery w projekcie open source - Marcin StachniukMarcinStachniuk
 
New in Spring Framework 5.0: Functional Web Framework
New in Spring Framework 5.0: Functional Web FrameworkNew in Spring Framework 5.0: Functional Web Framework
New in Spring Framework 5.0: Functional Web FrameworkVMware Tanzu
 
Migrating to Angular 5 for Spring Developers
Migrating to Angular 5 for Spring DevelopersMigrating to Angular 5 for Spring Developers
Migrating to Angular 5 for Spring DevelopersGunnar Hillert
 
Migrating to Angular 4 for Spring Developers
Migrating to Angular 4 for Spring Developers Migrating to Angular 4 for Spring Developers
Migrating to Angular 4 for Spring Developers VMware Tanzu
 
[convergese] Adaptive Images in Responsive Web Design
[convergese] Adaptive Images in Responsive Web Design[convergese] Adaptive Images in Responsive Web Design
[convergese] Adaptive Images in Responsive Web DesignChristopher Schmitt
 
Reactor 3.0, a reactive foundation for java 8 and Spring
Reactor 3.0, a reactive foundation for java 8 and SpringReactor 3.0, a reactive foundation for java 8 and Spring
Reactor 3.0, a reactive foundation for java 8 and SpringStéphane Maldini
 

Ähnlich wie Grooscript in Action SpringOne2gx 2015 (20)

Groovy 3 and the new Groovy Meta Object Protocol in examples
Groovy 3 and the new Groovy Meta Object Protocol in examplesGroovy 3 and the new Groovy Meta Object Protocol in examples
Groovy 3 and the new Groovy Meta Object Protocol in examples
 
Becoming an Advanced Groovy Developer Spring One 2gx 2015
Becoming an Advanced Groovy Developer Spring One 2gx 2015Becoming an Advanced Groovy Developer Spring One 2gx 2015
Becoming an Advanced Groovy Developer Spring One 2gx 2015
 
groovy transforms
groovy transformsgroovy transforms
groovy transforms
 
SpringOne 2GX 2015 - Fullstack Groovy developer
SpringOne 2GX 2015 - Fullstack Groovy developerSpringOne 2GX 2015 - Fullstack Groovy developer
SpringOne 2GX 2015 - Fullstack Groovy developer
 
Migrating from Grails 2 to Grails 3
Migrating from Grails 2 to Grails 3Migrating from Grails 2 to Grails 3
Migrating from Grails 2 to Grails 3
 
Better Than BASH: Scripting Kotlin
Better Than BASH: Scripting KotlinBetter Than BASH: Scripting Kotlin
Better Than BASH: Scripting Kotlin
 
Lessons learned from upgrading Thymeleaf
Lessons learned from upgrading ThymeleafLessons learned from upgrading Thymeleaf
Lessons learned from upgrading Thymeleaf
 
Reactive frontends with RxJS and Angular
Reactive frontends with RxJS and AngularReactive frontends with RxJS and Angular
Reactive frontends with RxJS and Angular
 
Not Only Reactive - Data Access with Spring Data
Not Only Reactive - Data Access with Spring DataNot Only Reactive - Data Access with Spring Data
Not Only Reactive - Data Access with Spring Data
 
Springone2gx 2015 Cassandra and Grails
Springone2gx 2015 Cassandra and GrailsSpringone2gx 2015 Cassandra and Grails
Springone2gx 2015 Cassandra and Grails
 
Leveling up your JavaScipt - DrupalJam 2017
Leveling up your JavaScipt - DrupalJam 2017Leveling up your JavaScipt - DrupalJam 2017
Leveling up your JavaScipt - DrupalJam 2017
 
Reactive Data Access with Spring Data
Reactive Data Access with Spring DataReactive Data Access with Spring Data
Reactive Data Access with Spring Data
 
Under the Hood of Reactive Data Access (1/2)
Under the Hood of Reactive Data Access (1/2)Under the Hood of Reactive Data Access (1/2)
Under the Hood of Reactive Data Access (1/2)
 
Zero-config JavaScript apps with RaveJS -- SVCC fall 2014
Zero-config JavaScript apps with RaveJS -- SVCC fall 2014Zero-config JavaScript apps with RaveJS -- SVCC fall 2014
Zero-config JavaScript apps with RaveJS -- SVCC fall 2014
 
Continuous delivery w projekcie open source - Marcin Stachniuk
Continuous delivery w projekcie open source - Marcin StachniukContinuous delivery w projekcie open source - Marcin Stachniuk
Continuous delivery w projekcie open source - Marcin Stachniuk
 
New in Spring Framework 5.0: Functional Web Framework
New in Spring Framework 5.0: Functional Web FrameworkNew in Spring Framework 5.0: Functional Web Framework
New in Spring Framework 5.0: Functional Web Framework
 
Migrating to Angular 5 for Spring Developers
Migrating to Angular 5 for Spring DevelopersMigrating to Angular 5 for Spring Developers
Migrating to Angular 5 for Spring Developers
 
Migrating to Angular 4 for Spring Developers
Migrating to Angular 4 for Spring Developers Migrating to Angular 4 for Spring Developers
Migrating to Angular 4 for Spring Developers
 
[convergese] Adaptive Images in Responsive Web Design
[convergese] Adaptive Images in Responsive Web Design[convergese] Adaptive Images in Responsive Web Design
[convergese] Adaptive Images in Responsive Web Design
 
Reactor 3.0, a reactive foundation for java 8 and Spring
Reactor 3.0, a reactive foundation for java 8 and SpringReactor 3.0, a reactive foundation for java 8 and Spring
Reactor 3.0, a reactive foundation for java 8 and Spring
 

Kürzlich hochgeladen

08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 

Kürzlich hochgeladen (20)

08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 

Grooscript in Action SpringOne2gx 2015

  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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