Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
by Andrés Viedma
scripts
with
Restless Java lover
Software dinosaur
more than 20 years nagging
Working at
Usual suspect of MadridGUG
and MadridJUG
Arquitecture at
Service
DB
TService
TuentiNg
DBs
tuenti-ng
Micro serviceTService
Micro serviceTService
Micro serviceTServi...
Arquitecture at
Service
DB
TService
TuentiNg
DBs
tuenti-ng
Micro serviceTService
Micro serviceTService
Micro serviceTServi...
About Groovy
● Dynamic Language, prepared for scripting
● Runs in the JVM
o Lots of Java libraries
o Can use the code of o...
Arquitecture at
Service
DB
TService
TuentiNg
DBs
tuenti-ng
Micro serviceTService
Micro serviceTService
Micro serviceTServi...
Arquitecture at
Service
DB
TService
TuentiNg
DBs
tuenti-ng
Micro serviceTService
Micro serviceTService
Micro serviceTServi...
Arquitecture at
Service
DB
TService
TuentiNg
DBs
tuenti-ng
Micro serviceTService
Micro serviceTService
Micro serviceTServi...
Mix your Production code
with direct accesses to the
DB, config, TServices...
Hello World (Java, but works also as
Groovy)
import utils.*;
World world = new World();
world.setId("mongo");
world.setNam...
Hello World (Groovy style)
def world = new World(id: "mongo", name: "Mongo")
println "Hello ${world.name}!"
class World {
...
Hello World (Groovy style)
def world = new World(id: "mongo", name: "Mongo")
println "Hello ${world.name}!"
class World {
...
Hello World (Groovy style)
def world = new World(id: "mongo", name: "Mongo")
println "Hello ${world.name}!"
class World {
...
Hello World (Groovy style)
def world = new World(id: "mongo", name: "Mongo")
println "Hello ${world.name}!"
class World {
...
Closures / collections
def worlds = [
new World(id: "mongo", name: "Mongo"),
new World(id: "mars", name: "Mars"),
new Worl...
Closures / collections
def worlds = [
new World(id: "mongo", name: "Mongo"),
new World(id: "mars", name: "Mars"),
new Worl...
Closures / collections
def worlds = [
new World(id: "mongo", name: "Mongo"),
new World(id: "mars", name: "Mars"),
new Worl...
Closures / collections
def worlds = [
new World(id: "mongo", name: "Mongo"),
new World(id: "mars", name: "Mars"),
new Worl...
Closures / collections
def worlds = [
new World(id: "mongo", name: "Mongo"),
new World(id: "mars", name: "Mars"),
new Worl...
Functions and scope of variables
def worlds = [ … ]
def heroesByWorld = [ … ]
eachWorld { world, heroes ->
println "*** Wo...
Functions and scope of variables
def worlds = [ … ]
def heroesByWorld = [ … ]
eachWorld { world, heroes ->
println "*** Wo...
Functions and scope of variables
def worlds = [ … ]
def heroesByWorld = [ … ]
eachWorld { world, heroes ->
println "*** Wo...
Functions and scope of variables
def worlds = [ … ]
def heroesByWorld = [ … ]
eachWorld { world, heroes ->
println "*** Wo...
Functions and scope of variables
def worlds = [ … ]
def heroesByWorld = [ … ]
eachWorld { world, heroes ->
println "*** Wo...
Grape: libraries from Maven repos
@Grab(group='org.apache.commons', module='commons-email', version='1.3.3')
import org.ap...
<ivysettings>
<settings defaultResolver="downloadGrapes"/>
<resolvers>
<chain name="downloadGrapes">
<filesystem name="cac...
<ivysettings>
<settings defaultResolver="downloadGrapes"/>
<resolvers>
<chain name="downloadGrapes">
<filesystem name="cac...
<ivysettings>
<settings defaultResolver="downloadGrapes"/>
<resolvers>
<chain name="downloadGrapes">
<filesystem name="cac...
Grape: add your repository
<ivysettings>
<settings defaultResolver="downloadGrapes"/>
<credentials host="nexus.xxx.xxx"
re...
Grape: add your repository
<ivysettings>
<settings defaultResolver="downloadGrapes"/>
<credentials host="nexus.xxx.xxx"
re...
Grape: updatable snapshots
<ivysettings>
<settings defaultResolver="downloadGrapes"/>
<credentials host="nexus.xxx.xxx"
re...
Grape: updatable snapshots
<ivysettings>
<settings defaultResolver="downloadGrapes"/>
<credentials host="nexus.xxx.xxx"
re...
Databases: Sql object
@Grab('mysql:mysql-connector-java')
@GrabConfig(systemClassLoader=true)
import groovy.sql.Sql
def sq...
Databases: Sql object
@Grab('mysql:mysql-connector-java')
@GrabConfig(systemClassLoader=true)
import groovy.sql.Sql
def sq...
Databases: Sql object
@Grab('mysql:mysql-connector-java')
@GrabConfig(systemClassLoader=true)
import groovy.sql.Sql
def sq...
Databases: Sql object
@Grab('mysql:mysql-connector-java')
@GrabConfig(systemClassLoader=true)
import groovy.sql.Sql
def sq...
Script arguments: CliBuilder
def cli = new CliBuilder(usage:'simpleHtmlServer -p PORT -d DIRECTORY')
cli.with {
h longOpt:...
Script arguments: CliBuilder
def cli = new CliBuilder(usage:'simpleHtmlServer -p PORT -d DIRECTORY')
cli.with {
h longOpt:...
Script arguments: CliBuilder
def cli = new CliBuilder(usage:'simpleHtmlServer -p PORT -d DIRECTORY')
cli.with {
h longOpt:...
Create your own utility classes
Grapes in reusable files
import utils.*
PlatformLibs.load()
(...)
package utils
@Grab('commons-logging:commons-logging:1.1...
“Clean” Services Clients
import utils.*
TServiceClient subscriptionService = new TServiceClient(
base: "http://xxxxx/Subsc...
“Clean” clients trick
@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-
builder', version='0.7')
(...)...
“Clean” clients trick
@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-
builder', version='0.7')
(...)...
Classes for named access to the
environment
import utils.*
import groovy.sql.*
def chargingService = TuentiEnv.jsc.prod.ch...
Environment helper
package utils
@GrabConfig(systemClassLoader=true, initContextClassLoader=true)
@Grab('mysql:mysql-conne...
Environment helper
package utils
@GrabConfig(systemClassLoader=true, initContextClassLoader=true)
@Grab('mysql:mysql-conne...
Environment helper
package utils
@GrabConfig(systemClassLoader=true, initContextClassLoader=true)
@Grab('mysql:mysql-conne...
Services Console: easily test your
services
aviedma@dev6:~$ groovysh
Groovy Shell (2.2.2, JVM: 1.6.0_26)
Type ':help' or '...
Services Console: easily test your
services
aviedma@dev6:~$ groovysh
Groovy Shell (2.2.2, JVM: 1.6.0_26)
Type ':help' or '...
Services Console: easily test your
services
aviedma@dev6:~$ groovysh
Groovy Shell (2.2.2, JVM: 1.6.0_26)
Type ':help' or '...
Tracking scripts execution
import utils.*
TuScript.track("Say hello to the world”)
println "Hello world!"
(...)
● A single...
Tracking scripts execution
class TuScript {
public static void track(String description) {
if (metadata != null) {
finishC...
Tracking scripts execution
class TuScript {
public static void track(String description) {
if (metadata != null) {
finishC...
Tracking scripts execution
class TuScript {
public static void track(String description) {
if (metadata != null) {
finishC...
Split execution in steps
sql.eachRow("""
<loooooong SQL>
""") { row ->
processRow(row)
}
void processRow(row) {
println "$...
Split execution in steps
sql.eachRow("""
<loooooong SQL>
""") { row ->
processRow(row)
}
void processRow(row) {
println "$...
Split execution in steps
void step1(String file) {
Dump dump = new Dump(file)
dump.withWriter(fieldNames) { out ->
sql.eac...
Split execution in steps
void step1(String file) {
Dump dump = new Dump(file)
dump.withWriter(fieldNames) { out ->
sql.eac...
Split execution in steps
void step1(String file) {
Dump dump = new Dump(file)
dump.withWriter(fieldNames) { out ->
sql.eac...
Running Shell commands
def process = 'ls /home/andres'.execute()
def procOutput = new InputStreamReader(process.in)
procOu...
Running Shell commands
def process = 'ls /home/andres'.execute()
def procOutput = new InputStreamReader(process.in)
procOu...
Running Shell commands
def process = 'ls /home/andres'.execute()
def procOutput = new InputStreamReader(process.in)
procOu...
Running Shell commands
def process = 'ls /home/andres'.execute()
def procOutput = new InputStreamReader(process.in)
procOu...
Running Shell commands
def process = 'ls /home/andres'.execute()
def procOutput = new InputStreamReader(process.in)
procOu...
Running Shell commands
class Shell {
File currentDir = new File('.')
final Map environment = [:]
Process run(String comman...
Running Shell commands
class Shell {
File currentDir = new File('.')
final Map environment = [:]
Process run(String comman...
Thanks!
Questions?
Groovy scripts with Groovy
Groovy scripts with Groovy
Groovy scripts with Groovy
Upcoming SlideShare
Loading in …5
×

Groovy scripts with Groovy

0 views

Published on

Some times we can forget that one of the most interesting uses of a language like Groovy is to make small scripts, beyond the need of playing with the rules and peculiarities of monster frameworks like Grails. This point is interesting not only for Groovy programmers, but also (specially) for Java programmers afraid of using Groovy in production code for being "dirty".

In this talk we'll see how Groovy is a language specially prepared for scripting, and very easy to handle for programmers with a Java background. We'll also explore some peculiarities of Groovy scripts in comparison to complete applications, and some interesting ideas which can be applied to scripts, based on my experience, and can be useful to anyone.

Published in: Software
  • Be the first to comment

Groovy scripts with Groovy

  1. 1. by Andrés Viedma scripts with
  2. 2. Restless Java lover Software dinosaur more than 20 years nagging Working at Usual suspect of MadridGUG and MadridJUG
  3. 3. Arquitecture at Service DB TService TuentiNg DBs tuenti-ng Micro serviceTService Micro serviceTService Micro serviceTService
  4. 4. Arquitecture at Service DB TService TuentiNg DBs tuenti-ng Micro serviceTService Micro serviceTService Micro serviceTService PHP Script
  5. 5. About Groovy ● Dynamic Language, prepared for scripting ● Runs in the JVM o Lots of Java libraries o Can use the code of our Java services ● Source code “almost” compatible with Java o Main difference: == operator means equals() o If you make your script in Java, it’ll WORK ● Other “cool” features, mainly inspired by Python
  6. 6. Arquitecture at Service DB TService TuentiNg DBs tuenti-ng Micro serviceTService Micro serviceTService Micro serviceTService
  7. 7. Arquitecture at Service DB TService TuentiNg DBs tuenti-ng Micro serviceTService Micro serviceTService Micro serviceTService Groovy Script
  8. 8. Arquitecture at Service DB TService TuentiNg DBs tuenti-ng Micro serviceTService Micro serviceTService Micro serviceTService Groovy Script
  9. 9. Mix your Production code with direct accesses to the DB, config, TServices...
  10. 10. Hello World (Java, but works also as Groovy) import utils.*; World world = new World(); world.setId("mongo"); world.setName("Mongo"); System.out.println("Hello " + world.getName() + "!"); package utils; public class World { private String id; private String name; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } $GRSCRIPTS/helloworld.groovy $GRSCRIPTS/utils/World.groovy
  11. 11. Hello World (Groovy style) def world = new World(id: "mongo", name: "Mongo") println "Hello ${world.name}!" class World { String id String name } $GRSCRIPTS/helloworld.groovy $ cd $GRSCRIPTS $ groovy helloworld.groovy Hello Mongo! $
  12. 12. Hello World (Groovy style) def world = new World(id: "mongo", name: "Mongo") println "Hello ${world.name}!" class World { String id String name } $GRSCRIPTS/helloworld.groovy $ cd $GRSCRIPTS $ groovy helloworld.groovy Hello Mongo! $
  13. 13. Hello World (Groovy style) def world = new World(id: "mongo", name: "Mongo") println "Hello ${world.name}!" class World { String id String name } $GRSCRIPTS/helloworld.groovy $ cd $GRSCRIPTS $ groovy helloworld.groovy Hello Mongo! $
  14. 14. Hello World (Groovy style) def world = new World(id: "mongo", name: "Mongo") println "Hello ${world.name}!" class World { String id String name } $GRSCRIPTS/helloworld.groovy $ cd $GRSCRIPTS $ groovy helloworld.groovy Hello Mongo! $
  15. 15. Closures / collections def worlds = [ new World(id: "mongo", name: "Mongo"), new World(id: "mars", name: "Mars"), new World(id: "wonderland", name: "Wonderland") ] as ArrayList def heroesByWorld = [ mongo: ["Flash Gordon", "Prince Barin"], mars: ["John Carter"], wonderland: ["Alice", "Queen of Hearts"] ] heroesByWorld.each { worldEntry -> def worldId = worldEntry.key def world = worlds.find { it.id == worldId } println "*** World: ${world.name}" def heroList = worldEntry.value heroList.each { hero -> println hero } }
  16. 16. Closures / collections def worlds = [ new World(id: "mongo", name: "Mongo"), new World(id: "mars", name: "Mars"), new World(id: "wonderland", name: "Wonderland") ] as ArrayList def heroesByWorld = [ mongo: ["Flash Gordon", "Prince Barin"], mars: ["John Carter"], wonderland: ["Alice", "Queen of Hearts"] ] heroesByWorld.each { worldEntry -> def worldId = worldEntry.key def world = worlds.find { it.id == worldId } println "*** World: ${world.name}" def heroList = worldEntry.value heroList.each { hero -> println hero } }
  17. 17. Closures / collections def worlds = [ new World(id: "mongo", name: "Mongo"), new World(id: "mars", name: "Mars"), new World(id: "wonderland", name: "Wonderland") ] as ArrayList def heroesByWorld = [ mongo: ["Flash Gordon", "Prince Barin"], mars: ["John Carter"], wonderland: ["Alice", "Queen of Hearts"] ] heroesByWorld.each { worldEntry -> def worldId = worldEntry.key def world = worlds.find { it.id == worldId } println "*** World: ${world.name}" def heroList = worldEntry.value heroList.each { hero -> println hero } }
  18. 18. Closures / collections def worlds = [ new World(id: "mongo", name: "Mongo"), new World(id: "mars", name: "Mars"), new World(id: "wonderland", name: "Wonderland") ] as ArrayList def heroesByWorld = [ mongo: ["Flash Gordon", "Prince Barin"], mars: ["John Carter"], wonderland: ["Alice", "Queen of Hearts"] ] heroesByWorld.each { worldEntry -> def worldId = worldEntry.key def world = worlds.find { it.id == worldId } println "*** World: ${world.name}" def heroList = worldEntry.value heroList.each { hero -> println hero } }
  19. 19. Closures / collections def worlds = [ new World(id: "mongo", name: "Mongo"), new World(id: "mars", name: "Mars"), new World(id: "wonderland", name: "Wonderland") ] as ArrayList def heroesByWorld = [ mongo: ["Flash Gordon", "Prince Barin"], mars: ["John Carter"], wonderland: ["Alice", "Queen of Hearts"] ] heroesByWorld.each { worldEntry -> def worldId = worldEntry.key def world = worlds.find { it.id == worldId } println "*** World: ${world.name}" def heroList = worldEntry.value heroList.each { hero -> println hero } }
  20. 20. Functions and scope of variables def worlds = [ … ] def heroesByWorld = [ … ] eachWorld { world, heroes -> println "*** World: ${world.name}" heroes.each { hero -> println hero } } void eachWorld(Closure closure) { heroesByWorld.each { worldEntry -> def worldId = worldEntry.key def world = worlds.find { it.id == worldId } def heroList = worldEntry.value closure(world, heroList) } }
  21. 21. Functions and scope of variables def worlds = [ … ] def heroesByWorld = [ … ] eachWorld { world, heroes -> println "*** World: ${world.name}" heroes.each { hero -> println hero } } void eachWorld(Closure closure) { heroesByWorld.each { worldEntry -> def worldId = worldEntry.key def world = worlds.find { it.id == worldId } def heroList = worldEntry.value closure(world, heroList) } }
  22. 22. Functions and scope of variables def worlds = [ … ] def heroesByWorld = [ … ] eachWorld { world, heroes -> println "*** World: ${world.name}" heroes.each { hero -> println hero } } void eachWorld(Closure closure) { heroesByWorld.each { worldEntry -> def worldId = worldEntry.key def world = worlds.find { it.id == worldId } def heroList = worldEntry.value closure(world, heroList) } }
  23. 23. Functions and scope of variables def worlds = [ … ] def heroesByWorld = [ … ] eachWorld { world, heroes -> println "*** World: ${world.name}" heroes.each { hero -> println hero } } void eachWorld(Closure closure) { heroesByWorld.each { worldEntry -> def worldId = worldEntry.key def world = worlds.find { it.id == worldId } def heroList = worldEntry.value closure(world, heroList) } }
  24. 24. Functions and scope of variables def worlds = [ … ] def heroesByWorld = [ … ] eachWorld { world, heroes -> println "*** World: ${world.name}" heroes.each { hero -> println hero } } void eachWorld(Closure closure) { heroesByWorld.each { worldEntry -> def worldId = worldEntry.key def world = worlds.find { it.id == worldId } def heroList = worldEntry.value closure(world, heroList) } } ● worlds = [ … ] ● @Field def worlds = [ … ] ● @Field List<World> worlds = [ … ]
  25. 25. Grape: libraries from Maven repos @Grab(group='org.apache.commons', module='commons-email', version='1.3.3') import org.apache.commons.mail.* def usr, pwd, toAddress = [ … ] println "Creating email object" Email email = new SimpleEmail( hostName: "smtp.googlemail.com", smtpPort: 465, authenticator: new DefaultAuthenticator(usr, pwd), SSLOnConnect: true, from: usr, subject: "Groovy mail!", msg: "You're hot and you know it ... :-)" ) email.addTo(toAddress); println "Sending email..." email.send() println "OK"
  26. 26. <ivysettings> <settings defaultResolver="downloadGrapes"/> <resolvers> <chain name="downloadGrapes"> <filesystem name="cachedGrapes"> <ivy pattern="${user.home}/.groovy/grapes/[organisation]/[module]/ivy- [revision].xml"/> <artifact pattern="${user.home}/.groovy/grapes/[organisation]/[module]/ [type]s/[artifact]-[revision].[ext]"/> </filesystem> <ibiblio name="codehaus" root="http://repository.codehaus.org/" m2compatible="true"/> <ibiblio name="ibiblio" m2compatible="true"/> <ibiblio name="java.net2" root="http://download.java.net/maven/2/" m2compatible="true"/> </chain> </resolvers> </ivysettings> Grape: default config
  27. 27. <ivysettings> <settings defaultResolver="downloadGrapes"/> <resolvers> <chain name="downloadGrapes"> <filesystem name="cachedGrapes"> <ivy pattern="${user.home}/.groovy/grapes/[organisation]/[module]/ivy- [revision].xml"/> <artifact pattern="${user.home}/.groovy/grapes/[organisation]/[module]/ [type]s/[artifact]-[revision].[ext]"/> </filesystem> <ibiblio name="codehaus" root="http://repository.codehaus.org/" m2compatible="true"/> <ibiblio name="ibiblio" m2compatible="true"/> <ibiblio name="java.net2" root="http://download.java.net/maven/2/" m2compatible="true"/> </chain> </resolvers> </ivysettings> Grape: default config
  28. 28. <ivysettings> <settings defaultResolver="downloadGrapes"/> <resolvers> <chain name="downloadGrapes"> <filesystem name="cachedGrapes"> <ivy pattern="${user.home}/.groovy/grapes/[organisation]/[module]/ivy- [revision].xml"/> <artifact pattern="${user.home}/.groovy/grapes/[organisation]/[module]/ [type]s/[artifact]-[revision].[ext]"/> </filesystem> <ibiblio name="codehaus" root="http://repository.codehaus.org/" m2compatible="true"/> <ibiblio name="ibiblio" m2compatible="true"/> <ibiblio name="java.net2" root="http://download.java.net/maven/2/" m2compatible="true"/> </chain> </resolvers> </ivysettings> Grape: default config
  29. 29. Grape: add your repository <ivysettings> <settings defaultResolver="downloadGrapes"/> <credentials host="nexus.xxx.xxx" realm="Sonatype Nexus Repository Manager" username="xxxx" passwd="xxxx"/> <property name="nexus-root" value="http://nexus.xxx.xxx/content/groups/public/"/> <resolvers> <chain name="downloadGrapes"> <ibiblio name="nexus" root="${nexus-root}" m2compatible="true" /> (...) </chain> </resolvers> </ivysettings>
  30. 30. Grape: add your repository <ivysettings> <settings defaultResolver="downloadGrapes"/> <credentials host="nexus.xxx.xxx" realm="Sonatype Nexus Repository Manager" username="xxxx" passwd="xxxx"/> <property name="nexus-root" value="http://nexus.xxx.xxx/content/groups/public/"/> <resolvers> <chain name="downloadGrapes"> <ibiblio name="nexus" root="${nexus-root}" m2compatible="true" /> (...) </chain> </resolvers> </ivysettings>
  31. 31. Grape: updatable snapshots <ivysettings> <settings defaultResolver="downloadGrapes"/> <credentials host="nexus.xxx.xxx" realm="Sonatype Nexus Repository Manager" username="xxxx" passwd="xxxx"/> <property name="nexus-root" value="http://nexus.xxx.xxx/content/groups/public/"/> <resolvers> <ibiblio name="downloadGrapes" root="${nexus-root}" m2compatible="true" /> </resolvers> </ivysettings>
  32. 32. Grape: updatable snapshots <ivysettings> <settings defaultResolver="downloadGrapes"/> <credentials host="nexus.xxx.xxx" realm="Sonatype Nexus Repository Manager" username="xxxx" passwd="xxxx"/> <property name="nexus-root" value="http://nexus.xxx.xxx/content/groups/public/"/> <resolvers> <ibiblio name="downloadGrapes" root="${nexus-root}" m2compatible="true" /> </resolvers> </ivysettings>
  33. 33. Databases: Sql object @Grab('mysql:mysql-connector-java') @GrabConfig(systemClassLoader=true) import groovy.sql.Sql def sql = Sql.newInstance("jdbc:mysql://localhost:3306/simfonics_charging", "tuenti_developer", "lalala", "com.mysql.jdbc.Driver") sql.resultSetConcurrency = java.sql.ResultSet.CONCUR_UPDATABLE def version = 2 def newVersion = 3 def type = "BUNDLEDEF" sql.eachRow("""select * from charging_element_definition where version = ${version} and element_type = ${type}""" ) { row -> if (row.element_id.startsWith("PG0.")) { println "Bundle ${row.element_id} version ${row.version}" + " to ${newVersion}" row.version = newVersion } }
  34. 34. Databases: Sql object @Grab('mysql:mysql-connector-java') @GrabConfig(systemClassLoader=true) import groovy.sql.Sql def sql = Sql.newInstance("jdbc:mysql://localhost:3306/simfonics_charging", "tuenti_developer", "lalala", "com.mysql.jdbc.Driver") sql.resultSetConcurrency = java.sql.ResultSet.CONCUR_UPDATABLE def version = 2 def newVersion = 3 def type = "BUNDLEDEF" sql.eachRow("""select * from charging_element_definition where version = ${version} and element_type = ${type}""" ) { row -> if (row.element_id.startsWith("PG0.")) { println "Bundle ${row.element_id} version ${row.version}" + " to ${newVersion}" row.version = newVersion } }
  35. 35. Databases: Sql object @Grab('mysql:mysql-connector-java') @GrabConfig(systemClassLoader=true) import groovy.sql.Sql def sql = Sql.newInstance("jdbc:mysql://localhost:3306/simfonics_charging", "tuenti_developer", "lalala", "com.mysql.jdbc.Driver") sql.resultSetConcurrency = java.sql.ResultSet.CONCUR_UPDATABLE def version = 2 def newVersion = 3 def type = "BUNDLEDEF" sql.eachRow("""select * from charging_element_definition where version = ${version} and element_type = ${type}""" ) { row -> if (row.element_id.startsWith("PG0.")) { println "Bundle ${row.element_id} version ${row.version}" + " to ${newVersion}" row.version = newVersion } }
  36. 36. Databases: Sql object @Grab('mysql:mysql-connector-java') @GrabConfig(systemClassLoader=true) import groovy.sql.Sql def sql = Sql.newInstance("jdbc:mysql://localhost:3306/simfonics_charging", "tuenti_developer", "lalala", "com.mysql.jdbc.Driver") sql.resultSetConcurrency = java.sql.ResultSet.CONCUR_UPDATABLE def version = 2 def newVersion = 3 def type = "BUNDLEDEF" sql.eachRow("""select * from charging_element_definition where version = ${version} and element_type = ${type}""" ) { row -> if (row.element_id.startsWith("PG0.")) { println "Bundle ${row.element_id} version ${row.version}" + " to ${newVersion}" row.version = newVersion } }
  37. 37. Script arguments: CliBuilder def cli = new CliBuilder(usage:'simpleHtmlServer -p PORT -d DIRECTORY') cli.with { h longOpt:'help', 'Usage information' p longOpt:'port',argName:'port', args:1, type:Number.class,'Def is 8080' d longOpt:'dir', argName:'directory', args:1, 'Default is .' } def opts = cli.parse(args) if(!opts) return if(opts.help) { cli.usage() return } def directory = opts.d def port = opts.port (...)
  38. 38. Script arguments: CliBuilder def cli = new CliBuilder(usage:'simpleHtmlServer -p PORT -d DIRECTORY') cli.with { h longOpt:'help', 'Usage information' p longOpt:'port',argName:'port', args:1, type:Number.class,'Def is 8080' d longOpt:'dir', argName:'directory', args:1, 'Default is .' } def opts = cli.parse(args) if(!opts) return if(opts.help) { cli.usage() return } def directory = opts.d def port = opts.port (...)
  39. 39. Script arguments: CliBuilder def cli = new CliBuilder(usage:'simpleHtmlServer -p PORT -d DIRECTORY') cli.with { h longOpt:'help', 'Usage information' p longOpt:'port',argName:'port', args:1, type:Number.class,'Def is 8080' d longOpt:'dir', argName:'directory', args:1, 'Default is .' } def opts = cli.parse(args) if(!opts) return if(opts.help) { cli.usage() return } def directory = opts.d def port = opts.port (...)
  40. 40. Create your own utility classes
  41. 41. Grapes in reusable files import utils.* PlatformLibs.load() (...) package utils @Grab('commons-logging:commons-logging:1.1.3') @Grab('org.apache.logging.log4j:log4j-api:2.1') @Grab('...') (...) class PlatformLibs { static void load() {} } (Script) utils/PlatformLibs.groovy
  42. 42. “Clean” Services Clients import utils.* TServiceClient subscriptionService = new TServiceClient( base: "http://xxxxx/SubscriptionService/") def statusData = subscriptionService.getSubscriptionStatus([id: 80644970]) println "Result of the call: ${statusData}" println "Subscription status: ${statusData.status}" ● Generic, equivalent to CURLs ● Using dynamic Groovy features ● Methods of the service are used transparently as if it were a “real” client interface
  43. 43. “Clean” clients trick @Grab(group='org.codehaus.groovy.modules.http-builder', module='http- builder', version='0.7') (...) class TServiceClient { (...) def methodMissing(String name, args) { def jsonResult = jsonCall(name, args) (...) } String jsonCall(String name, args) { def http = getHttpClient() def json = http.request(POST, JSON) { req -> body = [ "jsonrpc": "2.0", "id": callId, "method": interface + "." + version + "." + name, "params": [ "params": args, "gid": gid, "rid": rid ] ] } return json } }
  44. 44. “Clean” clients trick @Grab(group='org.codehaus.groovy.modules.http-builder', module='http- builder', version='0.7') (...) class TServiceClient { (...) def methodMissing(String name, args) { def jsonResult = jsonCall(name, args) (...) } String jsonCall(String name, args) { def http = getHttpClient() def json = http.request(POST, JSON) { req -> body = [ "jsonrpc": "2.0", "id": callId, "method": interface + "." + version + "." + name, "params": [ "params": args, "gid": gid, "rid": rid ] ] } return json } }
  45. 45. Classes for named access to the environment import utils.* import groovy.sql.* def chargingService = TuentiEnv.jsc.prod.charging def balanceData = chargingService.getBalance([id: 80644970], "es") Sql chargingDb = TuentiEnv.jsc.prod.charging.sql ● Easy named access to: o Databases o Service clients o For every environment
  46. 46. Environment helper package utils @GrabConfig(systemClassLoader=true, initContextClassLoader=true) @Grab('mysql:mysql-connector-java') @GrabExclude('xml-apis:xml-apis') import groovy.sql.Sql class TuentiEnv { (... properties with common configuration ...) static void initConsole() { Object.metaClass.tu = TuentiEnv.metaClass Object.metaClass.sim = TuentiEnv.simfonics Object.metaClass.jsc = TuentiEnv.jsc (...) Object.metaClass.pretty = { obj -> (new groovy.json.JsonBuilder(obj)).toPrettyString() } Object.metaClass.tservice = { String base, String iface = null -> return new TServiceClient(base: base, iface: iface) } } }
  47. 47. Environment helper package utils @GrabConfig(systemClassLoader=true, initContextClassLoader=true) @Grab('mysql:mysql-connector-java') @GrabExclude('xml-apis:xml-apis') import groovy.sql.Sql class TuentiEnv { (... properties with common configuration ...) static void initConsole() { Object.metaClass.tu = TuentiEnv.metaClass Object.metaClass.sim = TuentiEnv.simfonics Object.metaClass.jsc = TuentiEnv.jsc (...) Object.metaClass.pretty = { obj -> (new groovy.json.JsonBuilder(obj)).toPrettyString() } Object.metaClass.tservice = { String base, String iface = null -> return new TServiceClient(base: base, iface: iface) } } }
  48. 48. Environment helper package utils @GrabConfig(systemClassLoader=true, initContextClassLoader=true) @Grab('mysql:mysql-connector-java') @GrabExclude('xml-apis:xml-apis') import groovy.sql.Sql class TuentiEnv { (... properties with common configuration ...) static void initConsole() { Object.metaClass.tu = TuentiEnv.metaClass Object.metaClass.sim = TuentiEnv.simfonics Object.metaClass.jsc = TuentiEnv.jsc (...) Object.metaClass.pretty = { obj -> (new groovy.json.JsonBuilder(obj)).toPrettyString() } Object.metaClass.tservice = { String base, String iface = null -> return new TServiceClient(base: base, iface: iface) } } }
  49. 49. Services Console: easily test your services aviedma@dev6:~$ groovysh Groovy Shell (2.2.2, JVM: 1.6.0_26) Type ':help' or ':h' for help. --------------------------------------------------------------------- groovy:000> utils.TuentiEnv.initConsole() ===> null groovy:000> jsc.prod.charging.getBalance([id: 80644970], "es") ===> [amount:[amountInMillieuros:0], isAvailable:true] groovy:000> pretty jsc.prod.subscription.getSubscriptionStatus([id: 80644970]) ===> { "isAvailable": true, "lastUpdateTime": 1423501862, "status": "active" } groovy:000>
  50. 50. Services Console: easily test your services aviedma@dev6:~$ groovysh Groovy Shell (2.2.2, JVM: 1.6.0_26) Type ':help' or ':h' for help. --------------------------------------------------------------------- groovy:000> utils.TuentiEnv.initConsole() ===> null groovy:000> jsc.prod.charging.getBalance([id: 80644970], "es") ===> [amount:[amountInMillieuros:0], isAvailable:true] groovy:000> pretty jsc.prod.subscription.getSubscriptionStatus([id: 80644970]) ===> { "isAvailable": true, "lastUpdateTime": 1423501862, "status": "active" } groovy:000>
  51. 51. Services Console: easily test your services aviedma@dev6:~$ groovysh Groovy Shell (2.2.2, JVM: 1.6.0_26) Type ':help' or ':h' for help. --------------------------------------------------------------------- groovy:000> utils.TuentiEnv.initConsole() ===> null groovy:000> jsc.prod.charging.getBalance([id: 80644970], "es") ===> [amount:[amountInMillieuros:0], isAvailable:true] groovy:000> pretty jsc.prod.subscription.getSubscriptionStatus([id: 80644970]) ===> { "isAvailable": true, "lastUpdateTime": 1423501862, "status": "active" } groovy:000>
  52. 52. Tracking scripts execution import utils.* TuScript.track("Say hello to the world”) println "Hello world!" (...) ● A single line at the beginning of the script o Logs start-end time and duration of the run (even if it fails or is killed) o Without changes in the scripts, it can be used to register the script execution for monitoring
  53. 53. Tracking scripts execution class TuScript { public static void track(String description) { if (metadata != null) { finishCurrentScript() } else { addShutdownHook { finishCurrentScript() } captureSignal("INT") captureSignal("TERM") } metadata = new ScriptMetadata(description: description) logScriptStart() } public static void finishCurrentScript() { if (metadata != null) { logScriptEnd() } metadata = null } private static void captureSignal(String signal) { def oldHandler = Signal.handle(new Signal(signal), [handle: { sig -> logSignal(signal) if (oldHandler) oldHandler.handle(sig) }] as SignalHandler); } (...)
  54. 54. Tracking scripts execution class TuScript { public static void track(String description) { if (metadata != null) { finishCurrentScript() } else { addShutdownHook { finishCurrentScript() } captureSignal("INT") captureSignal("TERM") } metadata = new ScriptMetadata(description: description) logScriptStart() } public static void finishCurrentScript() { if (metadata != null) { logScriptEnd() } metadata = null } private static void captureSignal(String signal) { def oldHandler = Signal.handle(new Signal(signal), [handle: { sig -> logSignal(signal) if (oldHandler) oldHandler.handle(sig) }] as SignalHandler); } (...)
  55. 55. Tracking scripts execution class TuScript { public static void track(String description) { if (metadata != null) { finishCurrentScript() } else { addShutdownHook { finishCurrentScript() } captureSignal("INT") captureSignal("TERM") } metadata = new ScriptMetadata(description: description) logScriptStart() } public static void finishCurrentScript() { if (metadata != null) { logScriptEnd() } metadata = null } private static void captureSignal(String signal) { def oldHandler = Signal.handle(new Signal(signal), [handle: { sig -> logSignal(signal) if (oldHandler) oldHandler.handle(sig) }] as SignalHandler); } (...)
  56. 56. Split execution in steps sql.eachRow(""" <loooooong SQL> """) { row -> processRow(row) } void processRow(row) { println "${row.id}: ${row.name} ${row.surname}" (... lots and lots of processing ...) }
  57. 57. Split execution in steps sql.eachRow(""" <loooooong SQL> """) { row -> processRow(row) } void processRow(row) { println "${row.id}: ${row.name} ${row.surname}" (... lots and lots of processing ...) }
  58. 58. Split execution in steps void step1(String file) { Dump dump = new Dump(file) dump.withWriter(fieldNames) { out -> sql.eachRow(""" <loooooong SQL> """) { row -> out.insert(row) } } } void step2(String file) { Dump dump = new Dump(file) dump.eachRow { out -> processRow(row) } } void processRow(row) { println "${row.id}: ${row.name} ${row.surname}" (... lots and lots of processing ...) }
  59. 59. Split execution in steps void step1(String file) { Dump dump = new Dump(file) dump.withWriter(fieldNames) { out -> sql.eachRow(""" <loooooong SQL> """) { row -> out.insert(row) } } } void step2(String file) { Dump dump = new Dump(file) dump.eachRow { out -> processRow(row) } } void processRow(row) { println "${row.id}: ${row.name} ${row.surname}" (... lots and lots of processing ...) }
  60. 60. Split execution in steps void step1(String file) { Dump dump = new Dump(file) dump.withWriter(fieldNames) { out -> sql.eachRow(""" <loooooong SQL> """) { row -> out.insert(row) } } } void step2(String file) { Dump dump = new Dump(file) dump.eachRow { out -> processRow(row) } } void processRow(row) { println "${row.id}: ${row.name} ${row.surname}" (... lots and lots of processing ...) } Same processing code, no changes needed
  61. 61. Running Shell commands def process = 'ls /home/andres'.execute() def procOutput = new InputStreamReader(process.in) procOutput.eachLine { line -> println line } process.waitFor() println "** Return code: ${process.exitValue()}"
  62. 62. Running Shell commands def process = 'ls /home/andres'.execute() def procOutput = new InputStreamReader(process.in) procOutput.eachLine { line -> println line } process.waitFor() println "** Return code: ${process.exitValue()}"
  63. 63. Running Shell commands def process = 'ls /home/andres'.execute() def procOutput = new InputStreamReader(process.in) procOutput.eachLine { line -> println line } process.waitFor() println "** Return code: ${process.exitValue()}" def process = 'echo "Hola caracola"'.execute() println process.text def process = ['echo', 'Hola caracola'].execute()
  64. 64. Running Shell commands def process = 'ls /home/andres'.execute() def procOutput = new InputStreamReader(process.in) procOutput.eachLine { line -> println line } process.waitFor() println "** Return code: ${process.exitValue()}" def process = 'echo "Hola caracola"'.execute() println process.text def process = ['echo', 'Hola caracola'].execute() def process = 'ls /home/andres/*'.execute() def process = ['sh', '-c', 'ls /home/andres/*'].execute()
  65. 65. Running Shell commands def process = 'ls /home/andres'.execute() def procOutput = new InputStreamReader(process.in) procOutput.eachLine { line -> println line } process.waitFor() println "** Return code: ${process.exitValue()}" def process = 'echo "Hola caracola"'.execute() println process.text def process = ['echo', 'Hola caracola'].execute() def process = 'ls /home/andres/*'.execute() def process = ['sh', '-c', 'ls /home/andres/*'].execute() def process = 'ls'.execute() def process = 'ls'.execute([], new File('/home/andres'))
  66. 66. Running Shell commands class Shell { File currentDir = new File('.') final Map environment = [:] Process run(String command) { return ['sh', '-c', command].execute( environment.collect { "${it.key}=${it.value}" }, currentDir) } String runAndGet(String command) { def proc = run(command) proc.waitFor() return proc.text } } Shell shell = new Shell(currentDir: new File("/home/andres/temp")) shell.environment["GREETINGS"] = "Hi!" print shell.runAndGet('echo $GREETINGS') print shell.runAndGet("ls i*") print shell.runAndGet('echo "Hola caracola"')
  67. 67. Running Shell commands class Shell { File currentDir = new File('.') final Map environment = [:] Process run(String command) { return ['sh', '-c', command].execute( environment.collect { "${it.key}=${it.value}" }, currentDir) } String runAndGet(String command) { def proc = run(command) proc.waitFor() return proc.text } } Shell shell = new Shell(currentDir: new File("/home/andres/temp")) shell.environment["GREETINGS"] = "Hi!" print shell.runAndGet('echo $GREETINGS') print shell.runAndGet("ls i*") print shell.runAndGet('echo "Hola caracola"')
  68. 68. Thanks! Questions?

×