SlideShare una empresa de Scribd logo
1 de 50
Descargar para leer sin conexión
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/1
Groovy 3
the new Meta Object Protocol
in examples
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Jochen Theodorou, GoPivtoal Germany GmbH
@JochenTheodorou
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/2
… in certainly not enough examples
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Jochen Theodorou, GoPivtoal Germany GmbH
@JochenTheodorou
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/3
What cannot go forward
goes backwards.
Johann Wolfgang von Goethe
(1749-1832), German Poet
Translation by Jochen Theodorou
“
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/4
Goals:
■ Metaclass as Persistent Collection and Realms
● Better multi threading performance
● Allowing different versions of metaclasses for same class
■ Only internal metaclasses
● no „extends MetaClassImpl“ any more, instead like ExpandoMetaClass for everything
● Delegation instead of Inheritance
■ MOP Methods
● Names and Signatures change to avoid conflicts with normal methods
● GroovyObject becomes a marker interface or is removed
● All methods then optional and in different variants
● No exception controlled MOP any more
■ Others
● All operators available for meta programmings
● Based on invokedynamic and ClassValue (Java 7 becomes minimum)
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/5
MOP Methods
= in class defined methods to control MOP
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/6
Overview:
■ Uncached:
● Difficulty: I did hear of Groovy
● methodMissing, methodIntercept, propertyMissing, propertyIntercept
■ Cached 1:
● Difficulty: Me, want more. Now!
● cacheMethodMissing, cacheMethodIntercept, cachePropertyMissing,
cachePropertyIntercept
■ Cached 2:
● Difficulty: I know what I do! Give me the full program!
● cacheMethodTarget, cachePropertyTarget
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/7
MOP Methods – A Groovy Builder
Groovy 1 and Groovy 2
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/8
Groovy Builder in Groovy 1/2
class XmlBuilder {
def out
def methodMissing(String name, args) {
out << "<$name>"
if(args[0] instanceof Closure) {
args[0].delegate = this
args[0].call()
} else {
out << args[0].toString()
}
out << "</$name>"
}
}
def xml = new XmlBuilder(out:System.out)
xml.html {
head {
title "Hello World"
}
body {
p "Welcome!"
}
}
console output:
<html><head><title>Hello World</title></head><body><p>Welcome!
</p></body></html>
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/9
Groovy Builder in Groovy 1/2
class XmlBuilder {
def out
def methodMissing(String name, args) {
out << "<$name>"
if(args[0] instanceof Closure) {
args[0].delegate = this
args[0].call()
} else {
out << args[0].toString()
}
out << "</$name>"
}
}
def xml = new XmlBuilder(out:System.out)
xml.html {
head {
title "Hello World"
}
body {
p "Welcome!"
}
}
console output:
<html><head><title>Hello World</title></head><body><p>Welcome!
</p></body></html>
called if no method
can be found for call
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/10
Groovy Builder in Groovy 1/2
class XmlBuilder {
def out
def methodMissing(String name, args) {
out << "<$name>"
if(args[0] instanceof Closure) {
args[0].delegate = this
args[0].call()
} else {
out << args[0].toString()
}
out << "</$name>"
}
}
def xml = new XmlBuilder(out:System.out)
xml.html {
head {
title "Hello World"
}
body {
p "Welcome!"
}
}
console output:
<html><head><title>Hello World</title></head><body><p>Welcome!
</p></body></html>
name = name of call
args = arguments of call
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/11
Groovy Builder in Groovy 1/2
class XmlBuilder {
def out
def methodMissing(String name, args) {
out << "<$name>"
if(args[0] instanceof Closure) {
args[0].delegate = this
args[0].call()
} else {
out << args[0].toString()
}
out << "</$name>"
} //implcit return !//implcit return !
}
def xml = new XmlBuilder(out:System.out)
xml.html {
head {
title "Hello World"
}
body {
p "Welcome!"
}
}
console output:
<html><head><title>Hello World</title></head><body><p>Welcome!
</p></body></html>The result of the call is the
result of methodMissing
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/12
MOP Methods – A Groovy Builder
Groovy 3 Uncached
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/13
Groovy Builder in Groovy 3 - Uncached
class XmlBuilder {
def out
MopResult methodMissing(String name, args) {
out << "<$name>"
If (args[0] instanceof Closure) {
args[0].delegate = this
args[0].call()
} else {
out << args[0].toString()
}
out << "</$name>"
return MopResult.VOID
}
}
def xml = new XmlBuilder(out:System.out)
xml.html {
head {
title "Hello World"
}
body {
p "Welcome!"
}
}
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/14
Groovy Builder uncached - before and after
class XmlBuilder {
def out
def methodMissing
(String name, args) {
out << "<$name>"
if(args[0] instanceof Closure) {
args[0].delegate = this
args[0].call()
} else {
out << args[0].toString()
}
out << "</$name>"
}
}
class XmlBuilder {
def out
MopResult methodMissing
(String name, args) {
out << "<$name>"
If (args[0] instanceof Closure) {
args[0].delegate = this
args[0].call()
} else {
out << args[0].toString()
}
out << "</$name>"
return MopResult.VOID
}
}
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/15
Groovy Builder uncached - before and after
class XmlBuilder {
def out
def methodMissing
(String name, args) {
out << "<$name>"
if(args[0] instanceof Closure) {
args[0].delegate = this
args[0].call()
} else {
out << args[0].toString()
}
out << "</$name>"
}
}
class XmlBuilder {
def out
MopResult methodMissing
(String name, args) {
out << "<$name>"
If (args[0] instanceof Closure) {
args[0].delegate = this
args[0].call()
} else {
out << args[0].toString()
}
out << "</$name>"
return MopResult.VOID
}
}
MopResult contains the
result of the call
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/16
Groovy Builder uncached - before and after
class XmlBuilder {
def out
def methodMissing
(String name, args) {
out << "<$name>"
if(args[0] instanceof Closure) {
args[0].delegate = this
args[0].call()
} else {
out << args[0].toString()
}
out << "</$name>"
}
}
class XmlBuilder {
def out
MopResult methodMissing
(String name, args) {
out << "<$name>"
If (args[0] instanceof Closure) {
args[0].delegate = this
args[0].call()
} else {
out << args[0].toString()
}
out << "</$name>"
return MopResult.VOID
}
}
it can also transport errors
or that there is no result (VOID)
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/17
MOP Methods – A Groovy Builder
Groovy 3 Cached
return how to get a result, instead of the result itself
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/18
Ein Groovy Builder in Groovy 3 - Cached
class XmlBuilder {
def out
def methodMissing
(String name, args)
{
out << "<$name>"
if(args[0] instanceof Closure) {
args[0].delegate = this
args[0].call()
} else {
out << args[0].toString()
}
out << "</$name>"
}
}
class XmlBuilder {
def out
void cacheMethodMissing
(GroovyCall call, String name)
{
call.chain {out << "<${name}>"}
if(call[0].isAssignableTo(Closure))
{
call[0].chain
{it.delegate = this}
call[0].execute()
} else {
call[0].execute "toString"
}
call.chain {out << "</${name}>"}
}
}
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/19
Ein Groovy Builder in Groovy 3 - Cached
class XmlBuilder {
def out
def methodMissing
(String name, args)
{
out << "<$name>"
if(args[0] instanceof Closure) {
args[0].delegate = this
args[0].call()
} else {
out << args[0].toString()
}
out << "</$name>"
}
}
class XmlBuilder {
def out
void cacheMethodMissing
(GroovyCall call, String name)
{
call.chain {out << "<${name}>"}
if(call[0].isAssignableTo(Closure))
{
call[0].chain
{it.delegate = this}
call[0].execute()
} else {
call[0].execute "toString"
}
call.chain {out << "</${name}>"}
}
}
since there is no result
we return void
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/20
Ein Groovy Builder in Groovy 3 - Cached
class XmlBuilder {
def out
def methodMissing
(String name, args)
{
out << "<$name>"
if(args[0] instanceof Closure) {
args[0].delegate = this
args[0].call()
} else {
out << args[0].toString()
}
out << "</$name>"
}
}
class XmlBuilder {
def out
void cacheMethodMissing
(GroovyCall call, String name)
{
call.chain {out << "<${name}>"}
if(call[0].isAssignableTo(Closure))
{
call[0].chain
{it.delegate = this}
call[0].execute()
} else {
call[0].execute "toString"
}
call.chain {out << "</${name}>"}
}
}
GroovyCall is created for
each uncached call
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/21
Ein Groovy Builder in Groovy 3 - Cached
class XmlBuilder {
def out
def methodMissing
(String name, args)
{
out << "<$name>"
if(args[0] instanceof Closure) {
args[0].delegate = this
args[0].call()
} else {
out << args[0].toString()
}
out << "</$name>"
}
}
class XmlBuilder {
def out
void cacheMethodMissing
(GroovyCall call, String name)
{
call.chain {out << "<${name}>"}
if(call[0].isAssignableTo(Closure))
{
call[0].chain
{it.delegate = this}
call[0].execute()
} else {
call[0].execute "toString"
}
call.chain {out << "</${name}>"}
}
}
No argument objects here,
only their rutime classes
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/22
Some more details:
■ We provide a high-level API to let you express how to get to a result, not what the
result is – This allows caching in the first place
■ The to be cached method called can go through cacheMethodMissing more than
once. Reasons for that can be type changes for the arguments or the receiver
■ If you want to react different to different values of the same type, caching might be
not for you. (example: provide the method to be called as additional argument
instead)
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/23
MOP Methods – A Groovy Builder
Groovy 3 MethodHandles
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/24
Ein Groovy Builder in Groovy 3 – MethodHandles
class XmlBuilder {
def out
private final MethodHandle outField = LOOKUP.findGetter....
void cacheMethodTarget
(GroovyCall call, String name)
{
call.chain(
GroovyInvoker.bind(outField,"leftShift","<${name}>"))
if (call.arg(0).isAsignableTo(Closure)) {
call.arg(0).chain(
GroovyInvoker.setProperty("delegate",this))
call.arg(0).execute()
} else {
call.arg(0).execute "toString"
}
call.chain(
GroovyInvoker.bind(outField,"leftShift","</${name}>"))
}
}
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/25
Some Explanations:
■ Target is to produce a MethodHandle
■ GroovyCall high-level API is helping you here and can be mixed with MethodHandles
■ Of course the MethodHandles-API from Java7 is efficient and powerful, but also
difficult to understand and handle – for example because types have to match
exactly
■ Ultimately (and only for the most crazy people) we want to provide a way to give
your own bootstrap method and then design yourself what you do with the call. This
way you could for example completely emulate Javalogik and also speed (of course
there is still an overhead through invokedynamic)
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/26
MOP Methods – Dynamic Finder
Groovy 1 und Groovy 2
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/27
Dynamic Finder in Groovy 1/2
class GORM {
// an array of dynamic methods that use regex
def dynamicMethods = [...]
def methodMissing (String name, args) {
def method = dynamicMethods.find { it.match(name) }
if (method) {
GORM.metaClass."$name" = { Object[] varArgs ->
method.invoke(delegate, name, varArgs)
}
return method.invoke(delegate, name, args)
}
else throw new
MissingMethodException(name, delegate, args)
}
}
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/28
Dynamic Finder in Groovy 1/2
class GORM {
// an array of dynamic methods that use regex
def dynamicMethods = [...]
def methodMissing (String name, args) {
def method = dynamicMethods.find { it.match(name) }
if (method) {
GORM.metaClass."$name" = { Object[] varArgs ->
method.invoke(delegate, name, varArgs)
}
return method.invoke(delegate, name, args)
}
else throw new
MissingMethodException(name, delegate, args)
}
}
adds a meta method to metaClass
for each missing method
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/29
Dynamic Finder in Groovy 1/2
class GORM {
// an array of dynamic methods that use regex
def dynamicMethods = [...]
def methodMissing (String name, args) {
def method = dynamicMethods.find { it.match(name) }
if (method) {
GORM.metaClass."$name" = { Object[] varArgs ->
method.invoke(delegate, name, varArgs)
}
return method.invoke(delegate, name, args)
}
else throw new
MissingMethodException(name, delegate, args)
}
}
makes the metaClass
stay in memory
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/30
The metaclass is in Groovy 1 and 2 actually linked to an instance, but has to be
saved in a global structure. That might use SoftReferences to avoid memory
problems, still garbage collection doesn't like such actions.
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/31
MOP Methods – Dynamic Finder
Groovy 3 Uncached
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/32
Dynamic Finder in Groovy 3
class GORM {
// an array of dynamic methods that use regex
def dynamicMethods = [...]
MopResult methodMissing (String name, args) {
def method = dynamicMethods.find { it.match(name) }
if (method) {
GORM.metaClass."$name" = { Object[] varArgs ->
method.invoke(delegate, name, varArgs)
}
return MopResult.of (GroovyInvoker.invoke
(method, delegate, name, args))
}
else return MopResult.ERROR
}
}
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/33
Dynamic Finder in Groovy 3
class GORM {
// an array of dynamic methods that use regex
def dynamicMethods = [...]
MopResult methodMissing (String name, args) {
def method = dynamicMethods.find { it.match(name) }
if (method) {
GORM.metaClass."$name" = { Object[] varArgs ->
method.invoke(delegate, name, varArgs)
}
return MopResult.of (GroovyInvoker.invoke
(method, delegate, name, args))
}
else return MopResult.ERROR
}
}
makes the metaClass
stay in memory
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/34
Dynamic Finder in Groovy 3
class GORM {
// an array of dynamic methods that use regex
def dynamicMethods = [...]
MopResult methodMissing (String name, args) {
def method = dynamicMethods.find { it.match(name) }
if (method) {
GORM.metaClass."$name" = { Object[] varArgs ->
method.invoke(delegate, name, varArgs)
}
return MopResult.of (GroovyInvoker.invoke
(method, delegate, name, args))
}
else return MopResult.ERROR
}
}
but not longer than the
class GORM
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/35
MOP Methods – Dynamic Finder
Groovy 3 Cached
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/36
Dynamic Finder in Groovy 3
class GORM {
// an array of dynamic methods that use regex
def dynamicMethods = [...]
void cacheMethodMissing (GroovyCall call, String name)
{
def method = dynamicMethods.find { it.match(name) }
if (method) {
call.chain (method, delegate, name)
}
else call.error()
}
}
metaClass stays unchanged
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/37
Metaclass Versions and Views
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/38
Recover old version of a metaclass
class A{}
A.metaClass.foo = {->1}
assert new A().foo() == 1
def oldMetaClass = A.metaClass.freeze()
A.metaClass.foo = {->2}
assert new A().foo() == 2
oldMetaClass.restore()
assert new A().foo() == 1
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/39
Recover old version of a metaclass
class A{}
A.metaClass.foo = {->1}
assert new A().foo() == 1
def oldMetaClass = A.metaClass.freeze()
A.metaClass.foo = {->2}
assert new A().foo() == 2
oldMetaClass.restore()
assert new A().foo() == 1
handler for the meta class
Instead of the meta class itself
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/40
Recover old version of a metaclass
class A{}
A.metaClass.foo = {->1}
assert new A().foo() == 1
def oldMetaClass = A.metaClass.freeze()
A.metaClass.foo = {->2}
assert new A().foo() == 2
oldMetaClass.restore()
assert new A().foo() == 1
make handler keeping
current meta class version
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/41
Recover old version of a metaclass
class A{}
A.metaClass.foo = {->1}
assert new A().foo() == 1
def oldMetaClass = A.metaClass.freeze()
A.metaClass.foo = {->2}
assert new A().foo() == 2
oldMetaClass.restore()
assert new A().foo() == 1
set meta method
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/42
Recover old version of a metaclass
class A{}
A.metaClass.foo = {->1}
assert new A().foo() == 1
def oldMetaClass = A.metaClass.freeze()
A.metaClass.foo = {->2}
assert new A().foo() == 2
oldMetaClass.restore()
assert new A().foo() == 1
restore old metaclass version
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/43
Some explanations:
■ Before Groovy 3 we always mutate the metaclass
● Recovering an old state is difficult
● Isolating changes almost impossible
■ In Groovy 3 the metaclass is a persistent collection which you can reference by a
handler
● Handler can be set to always give the actual meta class
● Or to “freeze” to keep the actual version and then maybe restore later
In the long term this might actually allow to serialize meta class states
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/44
Usage of Realms
class A{}
A.metaClass.foo = {->1}
assert new A().foo() == 1
realm {
A.metaClass.foo = {->2}
assert new A().foo() == 2
}
assert new A().foo() == 1
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/45
Usage of Realms
class A{}
A.metaClass.foo = {->1}
assert new A().foo() == 1
realm {
A.metaClass.foo = {->2}
assert new A().foo() == 2
}
assert new A().foo() == 1
create sub realm
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/46
Usage of Realms
class A{}
A.metaClass.foo = {->1}
assert new A().foo() == 1
realm {
A.metaClass.foo = {->2}
assert new A().foo() == 2
}
assert new A().foo() == 1
set new meta method
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/47
Usage of Realms
class A{}
A.metaClass.foo = {->1}
assert new A().foo() == 1
realm {
A.metaClass.foo = {->2}
assert new A().foo() == 2
}
assert new A().foo() == 1only visible in subrealm
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/48
Usage of Realms
class A{}
A.metaClass.foo = {->1}
assert new A().foo() == 1
realm {
A.metaClass.foo = {->2}
assert new A().foo() == 2
} // end of realm
assert new A().foo() == 1
return to parent realm
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/49
Some Explanations:
■ A Realm is a set of metaclases separated from the normal program (or parent realm)
at the point of call
■ Changes inside the Realm stay in the Realm and its subrealms
■ Exiting a Realm means to discard all changes done in the Realm
Thought Usage:
● Libraries can isolate code and protect it from outside changes
● Lexicographic Categories
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/50
And as always,
there is by far not enough time
:(

Más contenido relacionado

Similar a Groovy 3 Meta Object Protocol in Examples

Grooscript in Action SpringOne2gx 2015
Grooscript in Action SpringOne2gx 2015Grooscript in Action SpringOne2gx 2015
Grooscript in Action SpringOne2gx 2015Jorge Franco Leza
 
Lessons learned from upgrading Thymeleaf
Lessons learned from upgrading ThymeleafLessons learned from upgrading Thymeleaf
Lessons learned from upgrading ThymeleafVMware 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
 
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
 
Groovy for System Administrators
Groovy for System AdministratorsGroovy for System Administrators
Groovy for System AdministratorsDaniel Woods
 
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
 
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
 
Introducing RaveJS: Spring Boot concepts for JavaScript applications
Introducing RaveJS: Spring Boot concepts for JavaScript applicationsIntroducing RaveJS: Spring Boot concepts for JavaScript applications
Introducing RaveJS: Spring Boot concepts for JavaScript applicationsJohn Hann
 
Teaching TDD to Different Learning Styles
Teaching TDD to Different Learning StylesTeaching TDD to Different Learning Styles
Teaching TDD to Different Learning StylesVMware Tanzu
 
Development Setup of B-Translator
Development Setup of B-TranslatorDevelopment Setup of B-Translator
Development Setup of B-TranslatorDashamir Hoxha
 
7 Tips on Getting Your Theme Approved the First Time
7 Tips on Getting Your Theme Approved the First Time7 Tips on Getting Your Theme Approved the First Time
7 Tips on Getting Your Theme Approved the First TimeDmitry Mayorov
 
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...Guillaume Laforge
 
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
 
2014-11-11 Multiple Approaches to Managing Puppet Modules @ Puppet Camp Seattle
2014-11-11 Multiple Approaches to Managing Puppet Modules @ Puppet Camp Seattle2014-11-11 Multiple Approaches to Managing Puppet Modules @ Puppet Camp Seattle
2014-11-11 Multiple Approaches to Managing Puppet Modules @ Puppet Camp Seattlegarrett honeycutt
 
Reactive frontends with RxJS and Angular
Reactive frontends with RxJS and AngularReactive frontends with RxJS and Angular
Reactive frontends with RxJS and AngularVMware Tanzu
 
Groovy for Java Developers
Groovy for Java DevelopersGroovy for Java Developers
Groovy for Java DevelopersAndres Almiray
 
Mykhailo Bodnarchuk "The history of the Codeception project"
Mykhailo Bodnarchuk "The history of the Codeception project"Mykhailo Bodnarchuk "The history of the Codeception project"
Mykhailo Bodnarchuk "The history of the Codeception project"Fwdays
 

Similar a Groovy 3 Meta Object Protocol in Examples (20)

Grooscript in Action SpringOne2gx 2015
Grooscript in Action SpringOne2gx 2015Grooscript in Action SpringOne2gx 2015
Grooscript in Action SpringOne2gx 2015
 
Lessons learned from upgrading Thymeleaf
Lessons learned from upgrading ThymeleafLessons learned from upgrading Thymeleaf
Lessons learned from upgrading Thymeleaf
 
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
 
SpringOne 2GX 2015 - Fullstack Groovy developer
SpringOne 2GX 2015 - Fullstack Groovy developerSpringOne 2GX 2015 - Fullstack Groovy developer
SpringOne 2GX 2015 - Fullstack Groovy developer
 
Groovy for System Administrators
Groovy for System AdministratorsGroovy for System Administrators
Groovy for System Administrators
 
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
 
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
 
Introducing RaveJS: Spring Boot concepts for JavaScript applications
Introducing RaveJS: Spring Boot concepts for JavaScript applicationsIntroducing RaveJS: Spring Boot concepts for JavaScript applications
Introducing RaveJS: Spring Boot concepts for JavaScript applications
 
Teaching TDD to Different Learning Styles
Teaching TDD to Different Learning StylesTeaching TDD to Different Learning Styles
Teaching TDD to Different Learning Styles
 
Development Setup of B-Translator
Development Setup of B-TranslatorDevelopment Setup of B-Translator
Development Setup of B-Translator
 
Grooscript greach
Grooscript greachGrooscript greach
Grooscript greach
 
7 Tips on Getting Your Theme Approved the First Time
7 Tips on Getting Your Theme Approved the First Time7 Tips on Getting Your Theme Approved the First Time
7 Tips on Getting Your Theme Approved the First Time
 
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
 
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)
 
2014-11-11 Multiple Approaches to Managing Puppet Modules @ Puppet Camp Seattle
2014-11-11 Multiple Approaches to Managing Puppet Modules @ Puppet Camp Seattle2014-11-11 Multiple Approaches to Managing Puppet Modules @ Puppet Camp Seattle
2014-11-11 Multiple Approaches to Managing Puppet Modules @ Puppet Camp Seattle
 
Reactive frontends with RxJS and Angular
Reactive frontends with RxJS and AngularReactive frontends with RxJS and Angular
Reactive frontends with RxJS and Angular
 
Croogo
CroogoCroogo
Croogo
 
Groovy for Java Developers
Groovy for Java DevelopersGroovy for Java Developers
Groovy for Java Developers
 
Mykhailo Bodnarchuk "The history of the Codeception project"
Mykhailo Bodnarchuk "The history of the Codeception project"Mykhailo Bodnarchuk "The history of the Codeception project"
Mykhailo Bodnarchuk "The history of the Codeception project"
 

Más de GR8Conf

DevOps Enabling Your Team
DevOps Enabling Your TeamDevOps Enabling Your Team
DevOps Enabling Your TeamGR8Conf
 
Creating and testing REST contracts with Accurest Gradle
Creating and testing REST contracts with Accurest Gradle Creating and testing REST contracts with Accurest Gradle
Creating and testing REST contracts with Accurest Gradle GR8Conf
 
Mum, I want to be a Groovy full-stack developer
Mum, I want to be a Groovy full-stack developerMum, I want to be a Groovy full-stack developer
Mum, I want to be a Groovy full-stack developerGR8Conf
 
Metaprogramming with Groovy
Metaprogramming with GroovyMetaprogramming with Groovy
Metaprogramming with GroovyGR8Conf
 
Scraping with Geb
Scraping with GebScraping with Geb
Scraping with GebGR8Conf
 
How to create a conference android app with Groovy and Android
How to create a conference android app with Groovy and AndroidHow to create a conference android app with Groovy and Android
How to create a conference android app with Groovy and AndroidGR8Conf
 
Ratpack On the Docks
Ratpack On the DocksRatpack On the Docks
Ratpack On the DocksGR8Conf
 
Groovy Powered Clean Code
Groovy Powered Clean CodeGroovy Powered Clean Code
Groovy Powered Clean CodeGR8Conf
 
Cut your Grails application to pieces - build feature plugins
Cut your Grails application to pieces - build feature pluginsCut your Grails application to pieces - build feature plugins
Cut your Grails application to pieces - build feature pluginsGR8Conf
 
Performance tuning Grails applications
 Performance tuning Grails applications Performance tuning Grails applications
Performance tuning Grails applicationsGR8Conf
 
Ratpack and Grails 3
 Ratpack and Grails 3 Ratpack and Grails 3
Ratpack and Grails 3GR8Conf
 
Grails & DevOps: continuous integration and delivery in the cloud
Grails & DevOps: continuous integration and delivery in the cloudGrails & DevOps: continuous integration and delivery in the cloud
Grails & DevOps: continuous integration and delivery in the cloudGR8Conf
 
Functional testing your Grails app with GEB
Functional testing your Grails app with GEBFunctional testing your Grails app with GEB
Functional testing your Grails app with GEBGR8Conf
 
Deploying, Scaling, and Running Grails on AWS and VPC
Deploying, Scaling, and Running Grails on AWS and VPCDeploying, Scaling, and Running Grails on AWS and VPC
Deploying, Scaling, and Running Grails on AWS and VPCGR8Conf
 
The Grails introduction workshop
The Grails introduction workshopThe Grails introduction workshop
The Grails introduction workshopGR8Conf
 
Idiomatic spock
Idiomatic spockIdiomatic spock
Idiomatic spockGR8Conf
 
The Groovy Ecosystem Revisited
The Groovy Ecosystem RevisitedThe Groovy Ecosystem Revisited
The Groovy Ecosystem RevisitedGR8Conf
 
Integration using Apache Camel and Groovy
Integration using Apache Camel and GroovyIntegration using Apache Camel and Groovy
Integration using Apache Camel and GroovyGR8Conf
 
CRaSH the shell for the Java Virtual Machine
CRaSH the shell for the Java Virtual MachineCRaSH the shell for the Java Virtual Machine
CRaSH the shell for the Java Virtual MachineGR8Conf
 
Grooscript gr8conf
Grooscript gr8confGrooscript gr8conf
Grooscript gr8confGR8Conf
 

Más de GR8Conf (20)

DevOps Enabling Your Team
DevOps Enabling Your TeamDevOps Enabling Your Team
DevOps Enabling Your Team
 
Creating and testing REST contracts with Accurest Gradle
Creating and testing REST contracts with Accurest Gradle Creating and testing REST contracts with Accurest Gradle
Creating and testing REST contracts with Accurest Gradle
 
Mum, I want to be a Groovy full-stack developer
Mum, I want to be a Groovy full-stack developerMum, I want to be a Groovy full-stack developer
Mum, I want to be a Groovy full-stack developer
 
Metaprogramming with Groovy
Metaprogramming with GroovyMetaprogramming with Groovy
Metaprogramming with Groovy
 
Scraping with Geb
Scraping with GebScraping with Geb
Scraping with Geb
 
How to create a conference android app with Groovy and Android
How to create a conference android app with Groovy and AndroidHow to create a conference android app with Groovy and Android
How to create a conference android app with Groovy and Android
 
Ratpack On the Docks
Ratpack On the DocksRatpack On the Docks
Ratpack On the Docks
 
Groovy Powered Clean Code
Groovy Powered Clean CodeGroovy Powered Clean Code
Groovy Powered Clean Code
 
Cut your Grails application to pieces - build feature plugins
Cut your Grails application to pieces - build feature pluginsCut your Grails application to pieces - build feature plugins
Cut your Grails application to pieces - build feature plugins
 
Performance tuning Grails applications
 Performance tuning Grails applications Performance tuning Grails applications
Performance tuning Grails applications
 
Ratpack and Grails 3
 Ratpack and Grails 3 Ratpack and Grails 3
Ratpack and Grails 3
 
Grails & DevOps: continuous integration and delivery in the cloud
Grails & DevOps: continuous integration and delivery in the cloudGrails & DevOps: continuous integration and delivery in the cloud
Grails & DevOps: continuous integration and delivery in the cloud
 
Functional testing your Grails app with GEB
Functional testing your Grails app with GEBFunctional testing your Grails app with GEB
Functional testing your Grails app with GEB
 
Deploying, Scaling, and Running Grails on AWS and VPC
Deploying, Scaling, and Running Grails on AWS and VPCDeploying, Scaling, and Running Grails on AWS and VPC
Deploying, Scaling, and Running Grails on AWS and VPC
 
The Grails introduction workshop
The Grails introduction workshopThe Grails introduction workshop
The Grails introduction workshop
 
Idiomatic spock
Idiomatic spockIdiomatic spock
Idiomatic spock
 
The Groovy Ecosystem Revisited
The Groovy Ecosystem RevisitedThe Groovy Ecosystem Revisited
The Groovy Ecosystem Revisited
 
Integration using Apache Camel and Groovy
Integration using Apache Camel and GroovyIntegration using Apache Camel and Groovy
Integration using Apache Camel and Groovy
 
CRaSH the shell for the Java Virtual Machine
CRaSH the shell for the Java Virtual MachineCRaSH the shell for the Java Virtual Machine
CRaSH the shell for the Java Virtual Machine
 
Grooscript gr8conf
Grooscript gr8confGrooscript gr8conf
Grooscript gr8conf
 

Último

The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 

Último (20)

The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 

Groovy 3 Meta Object Protocol in Examples

  • 1. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/1 Groovy 3 the new Meta Object Protocol in examples Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Jochen Theodorou, GoPivtoal Germany GmbH @JochenTheodorou
  • 2. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/2 … in certainly not enough examples Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Jochen Theodorou, GoPivtoal Germany GmbH @JochenTheodorou
  • 3. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/3 What cannot go forward goes backwards. Johann Wolfgang von Goethe (1749-1832), German Poet Translation by Jochen Theodorou “
  • 4. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/4 Goals: ■ Metaclass as Persistent Collection and Realms ● Better multi threading performance ● Allowing different versions of metaclasses for same class ■ Only internal metaclasses ● no „extends MetaClassImpl“ any more, instead like ExpandoMetaClass for everything ● Delegation instead of Inheritance ■ MOP Methods ● Names and Signatures change to avoid conflicts with normal methods ● GroovyObject becomes a marker interface or is removed ● All methods then optional and in different variants ● No exception controlled MOP any more ■ Others ● All operators available for meta programmings ● Based on invokedynamic and ClassValue (Java 7 becomes minimum)
  • 5. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/5 MOP Methods = in class defined methods to control MOP
  • 6. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/6 Overview: ■ Uncached: ● Difficulty: I did hear of Groovy ● methodMissing, methodIntercept, propertyMissing, propertyIntercept ■ Cached 1: ● Difficulty: Me, want more. Now! ● cacheMethodMissing, cacheMethodIntercept, cachePropertyMissing, cachePropertyIntercept ■ Cached 2: ● Difficulty: I know what I do! Give me the full program! ● cacheMethodTarget, cachePropertyTarget
  • 7. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/7 MOP Methods – A Groovy Builder Groovy 1 and Groovy 2
  • 8. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/8 Groovy Builder in Groovy 1/2 class XmlBuilder { def out def methodMissing(String name, args) { out << "<$name>" if(args[0] instanceof Closure) { args[0].delegate = this args[0].call() } else { out << args[0].toString() } out << "</$name>" } } def xml = new XmlBuilder(out:System.out) xml.html { head { title "Hello World" } body { p "Welcome!" } } console output: <html><head><title>Hello World</title></head><body><p>Welcome! </p></body></html>
  • 9. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/9 Groovy Builder in Groovy 1/2 class XmlBuilder { def out def methodMissing(String name, args) { out << "<$name>" if(args[0] instanceof Closure) { args[0].delegate = this args[0].call() } else { out << args[0].toString() } out << "</$name>" } } def xml = new XmlBuilder(out:System.out) xml.html { head { title "Hello World" } body { p "Welcome!" } } console output: <html><head><title>Hello World</title></head><body><p>Welcome! </p></body></html> called if no method can be found for call
  • 10. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/10 Groovy Builder in Groovy 1/2 class XmlBuilder { def out def methodMissing(String name, args) { out << "<$name>" if(args[0] instanceof Closure) { args[0].delegate = this args[0].call() } else { out << args[0].toString() } out << "</$name>" } } def xml = new XmlBuilder(out:System.out) xml.html { head { title "Hello World" } body { p "Welcome!" } } console output: <html><head><title>Hello World</title></head><body><p>Welcome! </p></body></html> name = name of call args = arguments of call
  • 11. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/11 Groovy Builder in Groovy 1/2 class XmlBuilder { def out def methodMissing(String name, args) { out << "<$name>" if(args[0] instanceof Closure) { args[0].delegate = this args[0].call() } else { out << args[0].toString() } out << "</$name>" } //implcit return !//implcit return ! } def xml = new XmlBuilder(out:System.out) xml.html { head { title "Hello World" } body { p "Welcome!" } } console output: <html><head><title>Hello World</title></head><body><p>Welcome! </p></body></html>The result of the call is the result of methodMissing
  • 12. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/12 MOP Methods – A Groovy Builder Groovy 3 Uncached
  • 13. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/13 Groovy Builder in Groovy 3 - Uncached class XmlBuilder { def out MopResult methodMissing(String name, args) { out << "<$name>" If (args[0] instanceof Closure) { args[0].delegate = this args[0].call() } else { out << args[0].toString() } out << "</$name>" return MopResult.VOID } } def xml = new XmlBuilder(out:System.out) xml.html { head { title "Hello World" } body { p "Welcome!" } }
  • 14. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/14 Groovy Builder uncached - before and after class XmlBuilder { def out def methodMissing (String name, args) { out << "<$name>" if(args[0] instanceof Closure) { args[0].delegate = this args[0].call() } else { out << args[0].toString() } out << "</$name>" } } class XmlBuilder { def out MopResult methodMissing (String name, args) { out << "<$name>" If (args[0] instanceof Closure) { args[0].delegate = this args[0].call() } else { out << args[0].toString() } out << "</$name>" return MopResult.VOID } }
  • 15. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/15 Groovy Builder uncached - before and after class XmlBuilder { def out def methodMissing (String name, args) { out << "<$name>" if(args[0] instanceof Closure) { args[0].delegate = this args[0].call() } else { out << args[0].toString() } out << "</$name>" } } class XmlBuilder { def out MopResult methodMissing (String name, args) { out << "<$name>" If (args[0] instanceof Closure) { args[0].delegate = this args[0].call() } else { out << args[0].toString() } out << "</$name>" return MopResult.VOID } } MopResult contains the result of the call
  • 16. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/16 Groovy Builder uncached - before and after class XmlBuilder { def out def methodMissing (String name, args) { out << "<$name>" if(args[0] instanceof Closure) { args[0].delegate = this args[0].call() } else { out << args[0].toString() } out << "</$name>" } } class XmlBuilder { def out MopResult methodMissing (String name, args) { out << "<$name>" If (args[0] instanceof Closure) { args[0].delegate = this args[0].call() } else { out << args[0].toString() } out << "</$name>" return MopResult.VOID } } it can also transport errors or that there is no result (VOID)
  • 17. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/17 MOP Methods – A Groovy Builder Groovy 3 Cached return how to get a result, instead of the result itself
  • 18. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/18 Ein Groovy Builder in Groovy 3 - Cached class XmlBuilder { def out def methodMissing (String name, args) { out << "<$name>" if(args[0] instanceof Closure) { args[0].delegate = this args[0].call() } else { out << args[0].toString() } out << "</$name>" } } class XmlBuilder { def out void cacheMethodMissing (GroovyCall call, String name) { call.chain {out << "<${name}>"} if(call[0].isAssignableTo(Closure)) { call[0].chain {it.delegate = this} call[0].execute() } else { call[0].execute "toString" } call.chain {out << "</${name}>"} } }
  • 19. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/19 Ein Groovy Builder in Groovy 3 - Cached class XmlBuilder { def out def methodMissing (String name, args) { out << "<$name>" if(args[0] instanceof Closure) { args[0].delegate = this args[0].call() } else { out << args[0].toString() } out << "</$name>" } } class XmlBuilder { def out void cacheMethodMissing (GroovyCall call, String name) { call.chain {out << "<${name}>"} if(call[0].isAssignableTo(Closure)) { call[0].chain {it.delegate = this} call[0].execute() } else { call[0].execute "toString" } call.chain {out << "</${name}>"} } } since there is no result we return void
  • 20. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/20 Ein Groovy Builder in Groovy 3 - Cached class XmlBuilder { def out def methodMissing (String name, args) { out << "<$name>" if(args[0] instanceof Closure) { args[0].delegate = this args[0].call() } else { out << args[0].toString() } out << "</$name>" } } class XmlBuilder { def out void cacheMethodMissing (GroovyCall call, String name) { call.chain {out << "<${name}>"} if(call[0].isAssignableTo(Closure)) { call[0].chain {it.delegate = this} call[0].execute() } else { call[0].execute "toString" } call.chain {out << "</${name}>"} } } GroovyCall is created for each uncached call
  • 21. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/21 Ein Groovy Builder in Groovy 3 - Cached class XmlBuilder { def out def methodMissing (String name, args) { out << "<$name>" if(args[0] instanceof Closure) { args[0].delegate = this args[0].call() } else { out << args[0].toString() } out << "</$name>" } } class XmlBuilder { def out void cacheMethodMissing (GroovyCall call, String name) { call.chain {out << "<${name}>"} if(call[0].isAssignableTo(Closure)) { call[0].chain {it.delegate = this} call[0].execute() } else { call[0].execute "toString" } call.chain {out << "</${name}>"} } } No argument objects here, only their rutime classes
  • 22. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/22 Some more details: ■ We provide a high-level API to let you express how to get to a result, not what the result is – This allows caching in the first place ■ The to be cached method called can go through cacheMethodMissing more than once. Reasons for that can be type changes for the arguments or the receiver ■ If you want to react different to different values of the same type, caching might be not for you. (example: provide the method to be called as additional argument instead)
  • 23. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/23 MOP Methods – A Groovy Builder Groovy 3 MethodHandles
  • 24. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/24 Ein Groovy Builder in Groovy 3 – MethodHandles class XmlBuilder { def out private final MethodHandle outField = LOOKUP.findGetter.... void cacheMethodTarget (GroovyCall call, String name) { call.chain( GroovyInvoker.bind(outField,"leftShift","<${name}>")) if (call.arg(0).isAsignableTo(Closure)) { call.arg(0).chain( GroovyInvoker.setProperty("delegate",this)) call.arg(0).execute() } else { call.arg(0).execute "toString" } call.chain( GroovyInvoker.bind(outField,"leftShift","</${name}>")) } }
  • 25. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/25 Some Explanations: ■ Target is to produce a MethodHandle ■ GroovyCall high-level API is helping you here and can be mixed with MethodHandles ■ Of course the MethodHandles-API from Java7 is efficient and powerful, but also difficult to understand and handle – for example because types have to match exactly ■ Ultimately (and only for the most crazy people) we want to provide a way to give your own bootstrap method and then design yourself what you do with the call. This way you could for example completely emulate Javalogik and also speed (of course there is still an overhead through invokedynamic)
  • 26. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/26 MOP Methods – Dynamic Finder Groovy 1 und Groovy 2
  • 27. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/27 Dynamic Finder in Groovy 1/2 class GORM { // an array of dynamic methods that use regex def dynamicMethods = [...] def methodMissing (String name, args) { def method = dynamicMethods.find { it.match(name) } if (method) { GORM.metaClass."$name" = { Object[] varArgs -> method.invoke(delegate, name, varArgs) } return method.invoke(delegate, name, args) } else throw new MissingMethodException(name, delegate, args) } }
  • 28. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/28 Dynamic Finder in Groovy 1/2 class GORM { // an array of dynamic methods that use regex def dynamicMethods = [...] def methodMissing (String name, args) { def method = dynamicMethods.find { it.match(name) } if (method) { GORM.metaClass."$name" = { Object[] varArgs -> method.invoke(delegate, name, varArgs) } return method.invoke(delegate, name, args) } else throw new MissingMethodException(name, delegate, args) } } adds a meta method to metaClass for each missing method
  • 29. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/29 Dynamic Finder in Groovy 1/2 class GORM { // an array of dynamic methods that use regex def dynamicMethods = [...] def methodMissing (String name, args) { def method = dynamicMethods.find { it.match(name) } if (method) { GORM.metaClass."$name" = { Object[] varArgs -> method.invoke(delegate, name, varArgs) } return method.invoke(delegate, name, args) } else throw new MissingMethodException(name, delegate, args) } } makes the metaClass stay in memory
  • 30. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/30 The metaclass is in Groovy 1 and 2 actually linked to an instance, but has to be saved in a global structure. That might use SoftReferences to avoid memory problems, still garbage collection doesn't like such actions.
  • 31. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/31 MOP Methods – Dynamic Finder Groovy 3 Uncached
  • 32. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/32 Dynamic Finder in Groovy 3 class GORM { // an array of dynamic methods that use regex def dynamicMethods = [...] MopResult methodMissing (String name, args) { def method = dynamicMethods.find { it.match(name) } if (method) { GORM.metaClass."$name" = { Object[] varArgs -> method.invoke(delegate, name, varArgs) } return MopResult.of (GroovyInvoker.invoke (method, delegate, name, args)) } else return MopResult.ERROR } }
  • 33. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/33 Dynamic Finder in Groovy 3 class GORM { // an array of dynamic methods that use regex def dynamicMethods = [...] MopResult methodMissing (String name, args) { def method = dynamicMethods.find { it.match(name) } if (method) { GORM.metaClass."$name" = { Object[] varArgs -> method.invoke(delegate, name, varArgs) } return MopResult.of (GroovyInvoker.invoke (method, delegate, name, args)) } else return MopResult.ERROR } } makes the metaClass stay in memory
  • 34. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/34 Dynamic Finder in Groovy 3 class GORM { // an array of dynamic methods that use regex def dynamicMethods = [...] MopResult methodMissing (String name, args) { def method = dynamicMethods.find { it.match(name) } if (method) { GORM.metaClass."$name" = { Object[] varArgs -> method.invoke(delegate, name, varArgs) } return MopResult.of (GroovyInvoker.invoke (method, delegate, name, args)) } else return MopResult.ERROR } } but not longer than the class GORM
  • 35. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/35 MOP Methods – Dynamic Finder Groovy 3 Cached
  • 36. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/36 Dynamic Finder in Groovy 3 class GORM { // an array of dynamic methods that use regex def dynamicMethods = [...] void cacheMethodMissing (GroovyCall call, String name) { def method = dynamicMethods.find { it.match(name) } if (method) { call.chain (method, delegate, name) } else call.error() } } metaClass stays unchanged
  • 37. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/37 Metaclass Versions and Views
  • 38. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/38 Recover old version of a metaclass class A{} A.metaClass.foo = {->1} assert new A().foo() == 1 def oldMetaClass = A.metaClass.freeze() A.metaClass.foo = {->2} assert new A().foo() == 2 oldMetaClass.restore() assert new A().foo() == 1
  • 39. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/39 Recover old version of a metaclass class A{} A.metaClass.foo = {->1} assert new A().foo() == 1 def oldMetaClass = A.metaClass.freeze() A.metaClass.foo = {->2} assert new A().foo() == 2 oldMetaClass.restore() assert new A().foo() == 1 handler for the meta class Instead of the meta class itself
  • 40. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/40 Recover old version of a metaclass class A{} A.metaClass.foo = {->1} assert new A().foo() == 1 def oldMetaClass = A.metaClass.freeze() A.metaClass.foo = {->2} assert new A().foo() == 2 oldMetaClass.restore() assert new A().foo() == 1 make handler keeping current meta class version
  • 41. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/41 Recover old version of a metaclass class A{} A.metaClass.foo = {->1} assert new A().foo() == 1 def oldMetaClass = A.metaClass.freeze() A.metaClass.foo = {->2} assert new A().foo() == 2 oldMetaClass.restore() assert new A().foo() == 1 set meta method
  • 42. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/42 Recover old version of a metaclass class A{} A.metaClass.foo = {->1} assert new A().foo() == 1 def oldMetaClass = A.metaClass.freeze() A.metaClass.foo = {->2} assert new A().foo() == 2 oldMetaClass.restore() assert new A().foo() == 1 restore old metaclass version
  • 43. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/43 Some explanations: ■ Before Groovy 3 we always mutate the metaclass ● Recovering an old state is difficult ● Isolating changes almost impossible ■ In Groovy 3 the metaclass is a persistent collection which you can reference by a handler ● Handler can be set to always give the actual meta class ● Or to “freeze” to keep the actual version and then maybe restore later In the long term this might actually allow to serialize meta class states
  • 44. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/44 Usage of Realms class A{} A.metaClass.foo = {->1} assert new A().foo() == 1 realm { A.metaClass.foo = {->2} assert new A().foo() == 2 } assert new A().foo() == 1
  • 45. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/45 Usage of Realms class A{} A.metaClass.foo = {->1} assert new A().foo() == 1 realm { A.metaClass.foo = {->2} assert new A().foo() == 2 } assert new A().foo() == 1 create sub realm
  • 46. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/46 Usage of Realms class A{} A.metaClass.foo = {->1} assert new A().foo() == 1 realm { A.metaClass.foo = {->2} assert new A().foo() == 2 } assert new A().foo() == 1 set new meta method
  • 47. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/47 Usage of Realms class A{} A.metaClass.foo = {->1} assert new A().foo() == 1 realm { A.metaClass.foo = {->2} assert new A().foo() == 2 } assert new A().foo() == 1only visible in subrealm
  • 48. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/48 Usage of Realms class A{} A.metaClass.foo = {->1} assert new A().foo() == 1 realm { A.metaClass.foo = {->2} assert new A().foo() == 2 } // end of realm assert new A().foo() == 1 return to parent realm
  • 49. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/49 Some Explanations: ■ A Realm is a set of metaclases separated from the normal program (or parent realm) at the point of call ■ Changes inside the Realm stay in the Realm and its subrealms ■ Exiting a Realm means to discard all changes done in the Realm Thought Usage: ● Libraries can isolate code and protect it from outside changes ● Lexicographic Categories
  • 50. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/50 And as always, there is by far not enough time :(