SlideShare une entreprise Scribd logo
1  sur  39
Télécharger pour lire hors ligne
Operating
Microservices
with
Andrés Viedma
@andres_viedma
Andrés ViedmaAndrés Viedma
@andres_viedma@andres_viedma
Andrés ViedmaAndrés Viedma
@andres_viedma@andres_viedma
curl 
-u "jsonrpc:19ffd9709d03ce50675c3a43d1c49c1ac207f4bc45f06c5b2701fbdf8929" 
-d '{"jsonrpc": "2.0", "id": 1, 
"method": "getAllTasks", "params": , {"project_id": 1, "status_id": 1} }' 
http://demo.kanboard.net/jsonrpc.php
01 LET'S PLAY!
(IN THE MUD)
Our weapon: the Groovy shell groovysh
Our basic Groovy Client
class JsonRpcClient {
(...)
def makeCall(String method, Map params = [:]) {
try {
(... json call ...)
return json.result
} catch (HttpResponseException e) {
(...)
}
}
}
class JsonRpcClient {
def methodMissing(String name, args) {
return makeCall(name, args)
}
def makeCall(String method, Map params = [:]) {
(...)
}
(...)
}
Our dynamic Groovy Client
class JsonRpcClient {
def methodMissing(String name, args) {
return makeCall(name, args)
}
def makeCall(String method, Map params = [:]) {
(...)
}
(...)
}
groovy:000> client = new JsonRpcClient(...)
===> jsonrpc.JsonRpcClient@a0a9fa5
groovy:000> client.getAllTasks(project_id: 1, status_id: 2)
Our dynamic Groovy Client
Our dynamic REST Groovy Client
blog.posts.”37”.comments()
blog.posts.”37”.delete()
blog.posts.”37” = [text: 'xxx', ...]
GET
POST
PUT
DELETE
blog.posts.”37”.comments << [text: 'xxx', …]
blog.posts.”37”.comments.add(text: 'xxx', …)
class RestGroovyClient extends RestGroovyClientPath {
String base
(...)
private doGet(String path, params = [:]) { … }
private doPut(String path, params = [:]) { … }
private doPost(String path, params = [:]) { … }
private doDelete(String path, params = [:]) { … }
}
class RestGroovyClientPath {
RestGroovyClient client = null
String path = ''
(...)
}
Our dynamic REST Groovy Client
class RestGroovyClientPath {
def propertyMissing(String name) {
newPath(name)
}
def getAt(name) {
newPath(name.toString())
}
private RestGroovyClientPath newPath(String name) {
return new RestGroovyClientPath(
client: client, path: nextpath(name))
}
(...)
}
Our dynamic REST Groovy Client
blog.posts.”37”.comments()
blog['posts'][37].comments()
class RestGroovyClientPath {
def methodMissing(String name, args) {
return client.doGet(nextpath(name), args)
}
def propertyMissing(String name, value) {
return client.doPut(nextpath(name), args)
}
def leftShift(value) {
return client.doPost(path, value)
}
def delete() {
return client.doDelete(path)
}
}
Our dynamic REST Groovy Client
blog.posts.”37”.comments()
blog.posts.”37” = [...]
blog.posts << [...]
blog.posts.”37”.delete()
02 YOUR LITTLE
BLACK BOOK
What if we create a directory of our services?
Organized as a tree
Grouped by features, by environment...
Register as shell variables
The ConfigSlurper
import dynapiclient.rest.*
jsonrpc {
kanboard = new JsonRpcClient(
base: 'http://demo.kanboard.net/jsonrpc.php',
clientHandler: { it.auth.basic 'demo', 'demo123' } )
}
rest {
(...)
marvel = new RestDynClient(
base: 'http://gateway.marvel.com/', path: '/v1/public',
paramsHandler: this.&marvelAuthenticate)
}
void marvelAuthenticate(Map callParams, String method) {
(...)
}
jsonrpc.kanboard.getMyProjects()
The ConfigSlurper
import dynapiclient.rest.*
jsonrpc {
kanboard = new JsonRpcClient(
base: 'http://demo.kanboard.net/jsonrpc.php',
clientHandler: { it.auth.basic 'demo', 'demo123' } )
}
rest {
(...)
marvel = new RestDynClient(
base: 'http://gateway.marvel.com/', path: '/v1/public',
paramsHandler: this.&marvelAuthenticate)
}
void marvelAuthenticate(Map callParams, String method) {
(...)
}
Available on startup: ~/.groovy/groovysh.profile
groovyUserHome = new File(System.getProperty('user.home'), '.groovy')
file = new File(groovyUserHome, 'assets.groovy')
binding.variables <<
new ConfigSlurper().parse(file.toURI().toURL())
Teamwork: share the directory
@Grab(group='org.springframework',
module='spring-orm',
version='3.2.5.RELEASE')
Teamwork: share the directory
Fast release cycle
@Grab(group='org.springframework',
module='spring-orm',
version='3.2.5.RELEASE')
@SourceGrab(
'https://github.com/andresviedma/
groovy-assets-directory-example.git')
AST transformation
Source Grapes Available in
Classpath
@SourceGrab('<url>')
public class myscript extends Script {
static {
SourceGrape.grab("<url>");
}
(...)
}
TRICK Add the sources directory to the classpath
in runtime and... it just works!
Merge directory parts (ConfigSlurper)
1. Passwords (local)
2. The main directory (git)
3. Personal / dev assets (local)
TRICK Merge config files: append all the files
and then parse them
03 I NEVER FORGET
A FACE
(BUT IN YOUR CASE, I'LL MAKE
AN EXCEPTION)
Asking for help
marvel.characters(doc)
groovy:000> rest.marvel.characters
===> **** /v1/public/characters
** GET: Fetches lists of characters.
Params: name, nameStartsWith, modifiedSince, comics, series, events,
stories, orderBy, limit, offset
Next: {characterId}
groovy:000>
marvel.characters()GET
marvel.characters.help()(doc)
Asking for help
groovy:000> rest.marvel.characters."1010354"
===> **** /v1/public/characters/{characterId}
** GET: Fetches a single character by id.
[characterId(*)]
Next: comics, events, series, stories
groovy:000>
Replaceable URL path sections
What about Autocomplete?
We have the ExpandoMetaClass!
groovy:000> x = 2
===> 2
groovy:000> x.metaClass.sayHello = { args -> println 'hello' }
===> groovysh_evaluate$_run_closure1@57adfab0
groovy:000> x.sayHello()
hello
===> null
groovy:000> x.
abs() byteValue() compareTo( doubleValue() downto(
floatValue()
intValue() longValue() power( shortValue() times(
upto(
groovy:000>
What about Autocomplete?
We have the ExpandoMetaClass!
groovy:000> x = 2
===> 2
groovy:000> x.metaClass.sayHello = { args -> println 'hello' }
===> groovysh_evaluate$_run_closure1@57adfab0
groovy:000> x.sayHello()
hello
===> null
groovy:000> x.
abs() byteValue() compareTo( doubleValue() downto(
floatValue()
intValue() longValue() power( shortValue() times(
upto(
groovy:000>
What about Autocomplete?
The shell wraps the Expando In a HandleMetaClass
groovy:000> x.metaClass
===> HandleMetaClass[MetaClassImpl[class java.lang.String]]
groovy:000> x.metaClass."hello" = { name -> "Hello ${name}" }
===> groovysh_evaluate$_run_closure1@feba70e
groovy:000> x.metaClass
===> HandleMetaClass[ExpandoMetaClass[class java.lang.String]]
groovy:000> x.metaClass.getMetaMethods()*.name.findAll { it.startsWith('h') }
===> [hasProperty]
TRICK Use InvokerHelper.getMetaClass(x)
instead of x.metaClass
class AutocompleteMetaClass extends DelegatingMetaClass {
static void addFakeMethodsToObject(Object object, methods, properties) {
def autocomplete = configureMetaClass(object)
def innerMeta = autocomplete.originalMetaClass
addFakeMethodsToExpando(innerMeta, object, methods, properties)
}
private static MetaClass configureMetaClass(Object object) {
def metaOld = InvokerHelper.getMetaClass(object)
if (metaOld.getClass().name != AutocompleteMetaClass.class.name) {
object.metaClass = new AutocompleteMetaClass(metaOld)
}
return InvokerHelper.getMetaClass(object)
}
(...)
}
Create your own brand AutocompleteMetaClass
class AutocompleteMetaClass extends DelegatingMetaClass {
(...)
final MetaClass expando
AutocompleteMetaClass(MetaClass originalMetaClass) {
super(originalMetaClass)
this.expando = originalMetaClass
}
List<MetaMethod> getMetaMethods() {
return expando.getExpandoMethods()
}
List<MetaBeanProperty> getProperties() {
return expando.getExpandoProperties()
}
}
Create your own brand AutocompleteMetaClass
Let's demo!!!
04 So...?
(JUST ENDING, I PROMISE...)
Give me the code!!!
https://github.com/andresviedma/sourcegrape
https://github.com/andresviedma/dynapiclient-groovy
https://github.com/andresviedma/groovy-assets-directory-example
Where did all this led us?
Shared microservices directory
Dynamic service calls
Autocomplete
Integrated help
A powerful shell
But, in the way there, mostly...
Learning about Groovy scripting black magic
Having fun!
Andrés ViedmaAndrés Viedma
@andres_viedma@andres_viedma
Questions?

Contenu connexe

En vedette

Groovy - Grails as a modern scripting language for Web applications
Groovy - Grails as a modern scripting language for Web applicationsGroovy - Grails as a modern scripting language for Web applications
Groovy - Grails as a modern scripting language for Web applicationsIndicThreads
 
Madrid GUG - Grails Plugins: Exporter
Madrid GUG - Grails Plugins: ExporterMadrid GUG - Grails Plugins: Exporter
Madrid GUG - Grails Plugins: ExporterIván López Martín
 
Hacking the Grails Spring Security Plugins
Hacking the Grails Spring Security PluginsHacking the Grails Spring Security Plugins
Hacking the Grails Spring Security PluginsGR8Conf
 
Greach 2014 - Metaprogramming with groovy
Greach 2014 - Metaprogramming with groovyGreach 2014 - Metaprogramming with groovy
Greach 2014 - Metaprogramming with groovyIván López Martín
 
Hacking the Grails Spring Security 2.0 Plugin
Hacking the Grails Spring Security 2.0 PluginHacking the Grails Spring Security 2.0 Plugin
Hacking the Grails Spring Security 2.0 PluginBurt Beckwith
 
T3chFest 2016 - De Java a Groovy: ¡Hora de Aventuras!
T3chFest 2016 - De Java a Groovy: ¡Hora de Aventuras!T3chFest 2016 - De Java a Groovy: ¡Hora de Aventuras!
T3chFest 2016 - De Java a Groovy: ¡Hora de Aventuras!Iván López Martín
 
Advanced GORM - Performance, Customization and Monitoring
Advanced GORM - Performance, Customization and MonitoringAdvanced GORM - Performance, Customization and Monitoring
Advanced GORM - Performance, Customization and MonitoringBurt Beckwith
 
Little Did He Know ...
Little Did He Know ...Little Did He Know ...
Little Did He Know ...Burt Beckwith
 
Codemotion 2013 - Quiero tiempo real y lo quiero para ayer
Codemotion 2013 - Quiero tiempo real y lo quiero para ayerCodemotion 2013 - Quiero tiempo real y lo quiero para ayer
Codemotion 2013 - Quiero tiempo real y lo quiero para ayerIván López Martín
 
Fun With Spring Security
Fun With Spring SecurityFun With Spring Security
Fun With Spring SecurityBurt Beckwith
 
Dropwizard and Groovy
Dropwizard and GroovyDropwizard and Groovy
Dropwizard and Groovytomaslin
 
Reactive Microservice Architecture with Groovy and Grails
Reactive Microservice Architecture with Groovy and GrailsReactive Microservice Architecture with Groovy and Grails
Reactive Microservice Architecture with Groovy and GrailsSteve Pember
 
Building Micro-Services with Scala
Building Micro-Services with ScalaBuilding Micro-Services with Scala
Building Micro-Services with ScalaYardena Meymann
 
Metaprogramming with Groovy
Metaprogramming with GroovyMetaprogramming with Groovy
Metaprogramming with GroovyGR8Conf
 
Groovy Powered Clean Code
Groovy Powered Clean CodeGroovy Powered Clean Code
Groovy Powered Clean CodeGR8Conf
 
Groovy in the Cloud
Groovy in the CloudGroovy in the Cloud
Groovy in the CloudDaniel Woods
 
Metaprogramming with Groovy
Metaprogramming with GroovyMetaprogramming with Groovy
Metaprogramming with GroovyAli Tanwir
 

En vedette (18)

Groovy - Grails as a modern scripting language for Web applications
Groovy - Grails as a modern scripting language for Web applicationsGroovy - Grails as a modern scripting language for Web applications
Groovy - Grails as a modern scripting language for Web applications
 
Madrid GUG - Grails Plugins: Exporter
Madrid GUG - Grails Plugins: ExporterMadrid GUG - Grails Plugins: Exporter
Madrid GUG - Grails Plugins: Exporter
 
Hacking the Grails Spring Security Plugins
Hacking the Grails Spring Security PluginsHacking the Grails Spring Security Plugins
Hacking the Grails Spring Security Plugins
 
Greach 2014 - Metaprogramming with groovy
Greach 2014 - Metaprogramming with groovyGreach 2014 - Metaprogramming with groovy
Greach 2014 - Metaprogramming with groovy
 
Hacking the Grails Spring Security 2.0 Plugin
Hacking the Grails Spring Security 2.0 PluginHacking the Grails Spring Security 2.0 Plugin
Hacking the Grails Spring Security 2.0 Plugin
 
T3chFest 2016 - De Java a Groovy: ¡Hora de Aventuras!
T3chFest 2016 - De Java a Groovy: ¡Hora de Aventuras!T3chFest 2016 - De Java a Groovy: ¡Hora de Aventuras!
T3chFest 2016 - De Java a Groovy: ¡Hora de Aventuras!
 
Advanced GORM - Performance, Customization and Monitoring
Advanced GORM - Performance, Customization and MonitoringAdvanced GORM - Performance, Customization and Monitoring
Advanced GORM - Performance, Customization and Monitoring
 
Little Did He Know ...
Little Did He Know ...Little Did He Know ...
Little Did He Know ...
 
Codemotion 2013 - Quiero tiempo real y lo quiero para ayer
Codemotion 2013 - Quiero tiempo real y lo quiero para ayerCodemotion 2013 - Quiero tiempo real y lo quiero para ayer
Codemotion 2013 - Quiero tiempo real y lo quiero para ayer
 
Fun With Spring Security
Fun With Spring SecurityFun With Spring Security
Fun With Spring Security
 
Dropwizard and Groovy
Dropwizard and GroovyDropwizard and Groovy
Dropwizard and Groovy
 
Reactive Microservice Architecture with Groovy and Grails
Reactive Microservice Architecture with Groovy and GrailsReactive Microservice Architecture with Groovy and Grails
Reactive Microservice Architecture with Groovy and Grails
 
Building Micro-Services with Scala
Building Micro-Services with ScalaBuilding Micro-Services with Scala
Building Micro-Services with Scala
 
Metaprogramming with Groovy
Metaprogramming with GroovyMetaprogramming with Groovy
Metaprogramming with Groovy
 
Groovy Powered Clean Code
Groovy Powered Clean CodeGroovy Powered Clean Code
Groovy Powered Clean Code
 
Groovy on Android
Groovy on AndroidGroovy on Android
Groovy on Android
 
Groovy in the Cloud
Groovy in the CloudGroovy in the Cloud
Groovy in the Cloud
 
Metaprogramming with Groovy
Metaprogramming with GroovyMetaprogramming with Groovy
Metaprogramming with Groovy
 

Dernier

Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Hr365.us smith
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfMarharyta Nedzelska
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfDrew Moseley
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf31events.com
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Angel Borroy López
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
cpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptcpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptrcbcrtm
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalLionel Briand
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commercemanigoyal112
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
Software Coding for software engineering
Software Coding for software engineeringSoftware Coding for software engineering
Software Coding for software engineeringssuserb3a23b
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentationvaddepallysandeep122
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 

Dernier (20)

Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdf
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdf
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
cpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptcpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.ppt
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive Goal
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commerce
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
Software Coding for software engineering
Software Coding for software engineeringSoftware Coding for software engineering
Software Coding for software engineering
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentation
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 

Operating Microservices with Groovy

  • 4.
  • 5. curl -u "jsonrpc:19ffd9709d03ce50675c3a43d1c49c1ac207f4bc45f06c5b2701fbdf8929" -d '{"jsonrpc": "2.0", "id": 1, "method": "getAllTasks", "params": , {"project_id": 1, "status_id": 1} }' http://demo.kanboard.net/jsonrpc.php
  • 7. Our weapon: the Groovy shell groovysh
  • 8. Our basic Groovy Client class JsonRpcClient { (...) def makeCall(String method, Map params = [:]) { try { (... json call ...) return json.result } catch (HttpResponseException e) { (...) } } }
  • 9. class JsonRpcClient { def methodMissing(String name, args) { return makeCall(name, args) } def makeCall(String method, Map params = [:]) { (...) } (...) } Our dynamic Groovy Client
  • 10. class JsonRpcClient { def methodMissing(String name, args) { return makeCall(name, args) } def makeCall(String method, Map params = [:]) { (...) } (...) } groovy:000> client = new JsonRpcClient(...) ===> jsonrpc.JsonRpcClient@a0a9fa5 groovy:000> client.getAllTasks(project_id: 1, status_id: 2) Our dynamic Groovy Client
  • 11. Our dynamic REST Groovy Client blog.posts.”37”.comments() blog.posts.”37”.delete() blog.posts.”37” = [text: 'xxx', ...] GET POST PUT DELETE blog.posts.”37”.comments << [text: 'xxx', …] blog.posts.”37”.comments.add(text: 'xxx', …)
  • 12. class RestGroovyClient extends RestGroovyClientPath { String base (...) private doGet(String path, params = [:]) { … } private doPut(String path, params = [:]) { … } private doPost(String path, params = [:]) { … } private doDelete(String path, params = [:]) { … } } class RestGroovyClientPath { RestGroovyClient client = null String path = '' (...) } Our dynamic REST Groovy Client
  • 13. class RestGroovyClientPath { def propertyMissing(String name) { newPath(name) } def getAt(name) { newPath(name.toString()) } private RestGroovyClientPath newPath(String name) { return new RestGroovyClientPath( client: client, path: nextpath(name)) } (...) } Our dynamic REST Groovy Client blog.posts.”37”.comments() blog['posts'][37].comments()
  • 14. class RestGroovyClientPath { def methodMissing(String name, args) { return client.doGet(nextpath(name), args) } def propertyMissing(String name, value) { return client.doPut(nextpath(name), args) } def leftShift(value) { return client.doPost(path, value) } def delete() { return client.doDelete(path) } } Our dynamic REST Groovy Client blog.posts.”37”.comments() blog.posts.”37” = [...] blog.posts << [...] blog.posts.”37”.delete()
  • 16.
  • 17. What if we create a directory of our services? Organized as a tree Grouped by features, by environment... Register as shell variables
  • 18. The ConfigSlurper import dynapiclient.rest.* jsonrpc { kanboard = new JsonRpcClient( base: 'http://demo.kanboard.net/jsonrpc.php', clientHandler: { it.auth.basic 'demo', 'demo123' } ) } rest { (...) marvel = new RestDynClient( base: 'http://gateway.marvel.com/', path: '/v1/public', paramsHandler: this.&marvelAuthenticate) } void marvelAuthenticate(Map callParams, String method) { (...) } jsonrpc.kanboard.getMyProjects()
  • 19. The ConfigSlurper import dynapiclient.rest.* jsonrpc { kanboard = new JsonRpcClient( base: 'http://demo.kanboard.net/jsonrpc.php', clientHandler: { it.auth.basic 'demo', 'demo123' } ) } rest { (...) marvel = new RestDynClient( base: 'http://gateway.marvel.com/', path: '/v1/public', paramsHandler: this.&marvelAuthenticate) } void marvelAuthenticate(Map callParams, String method) { (...) }
  • 20. Available on startup: ~/.groovy/groovysh.profile groovyUserHome = new File(System.getProperty('user.home'), '.groovy') file = new File(groovyUserHome, 'assets.groovy') binding.variables << new ConfigSlurper().parse(file.toURI().toURL())
  • 21. Teamwork: share the directory @Grab(group='org.springframework', module='spring-orm', version='3.2.5.RELEASE')
  • 22. Teamwork: share the directory Fast release cycle @Grab(group='org.springframework', module='spring-orm', version='3.2.5.RELEASE') @SourceGrab( 'https://github.com/andresviedma/ groovy-assets-directory-example.git')
  • 23. AST transformation Source Grapes Available in Classpath @SourceGrab('<url>') public class myscript extends Script { static { SourceGrape.grab("<url>"); } (...) } TRICK Add the sources directory to the classpath in runtime and... it just works!
  • 24. Merge directory parts (ConfigSlurper) 1. Passwords (local) 2. The main directory (git) 3. Personal / dev assets (local) TRICK Merge config files: append all the files and then parse them
  • 25. 03 I NEVER FORGET A FACE (BUT IN YOUR CASE, I'LL MAKE AN EXCEPTION)
  • 26.
  • 27.
  • 28. Asking for help marvel.characters(doc) groovy:000> rest.marvel.characters ===> **** /v1/public/characters ** GET: Fetches lists of characters. Params: name, nameStartsWith, modifiedSince, comics, series, events, stories, orderBy, limit, offset Next: {characterId} groovy:000> marvel.characters()GET marvel.characters.help()(doc)
  • 29. Asking for help groovy:000> rest.marvel.characters."1010354" ===> **** /v1/public/characters/{characterId} ** GET: Fetches a single character by id. [characterId(*)] Next: comics, events, series, stories groovy:000> Replaceable URL path sections
  • 30. What about Autocomplete? We have the ExpandoMetaClass! groovy:000> x = 2 ===> 2 groovy:000> x.metaClass.sayHello = { args -> println 'hello' } ===> groovysh_evaluate$_run_closure1@57adfab0 groovy:000> x.sayHello() hello ===> null groovy:000> x. abs() byteValue() compareTo( doubleValue() downto( floatValue() intValue() longValue() power( shortValue() times( upto( groovy:000>
  • 31. What about Autocomplete? We have the ExpandoMetaClass! groovy:000> x = 2 ===> 2 groovy:000> x.metaClass.sayHello = { args -> println 'hello' } ===> groovysh_evaluate$_run_closure1@57adfab0 groovy:000> x.sayHello() hello ===> null groovy:000> x. abs() byteValue() compareTo( doubleValue() downto( floatValue() intValue() longValue() power( shortValue() times( upto( groovy:000>
  • 32. What about Autocomplete? The shell wraps the Expando In a HandleMetaClass groovy:000> x.metaClass ===> HandleMetaClass[MetaClassImpl[class java.lang.String]] groovy:000> x.metaClass."hello" = { name -> "Hello ${name}" } ===> groovysh_evaluate$_run_closure1@feba70e groovy:000> x.metaClass ===> HandleMetaClass[ExpandoMetaClass[class java.lang.String]] groovy:000> x.metaClass.getMetaMethods()*.name.findAll { it.startsWith('h') } ===> [hasProperty] TRICK Use InvokerHelper.getMetaClass(x) instead of x.metaClass
  • 33. class AutocompleteMetaClass extends DelegatingMetaClass { static void addFakeMethodsToObject(Object object, methods, properties) { def autocomplete = configureMetaClass(object) def innerMeta = autocomplete.originalMetaClass addFakeMethodsToExpando(innerMeta, object, methods, properties) } private static MetaClass configureMetaClass(Object object) { def metaOld = InvokerHelper.getMetaClass(object) if (metaOld.getClass().name != AutocompleteMetaClass.class.name) { object.metaClass = new AutocompleteMetaClass(metaOld) } return InvokerHelper.getMetaClass(object) } (...) } Create your own brand AutocompleteMetaClass
  • 34. class AutocompleteMetaClass extends DelegatingMetaClass { (...) final MetaClass expando AutocompleteMetaClass(MetaClass originalMetaClass) { super(originalMetaClass) this.expando = originalMetaClass } List<MetaMethod> getMetaMethods() { return expando.getExpandoMethods() } List<MetaBeanProperty> getProperties() { return expando.getExpandoProperties() } } Create your own brand AutocompleteMetaClass
  • 36. 04 So...? (JUST ENDING, I PROMISE...)
  • 37. Give me the code!!! https://github.com/andresviedma/sourcegrape https://github.com/andresviedma/dynapiclient-groovy https://github.com/andresviedma/groovy-assets-directory-example
  • 38. Where did all this led us? Shared microservices directory Dynamic service calls Autocomplete Integrated help A powerful shell
  • 39. But, in the way there, mostly... Learning about Groovy scripting black magic Having fun! Andrés ViedmaAndrés Viedma @andres_viedma@andres_viedma Questions?