SlideShare uma empresa Scribd logo
1 de 97
Baixar para ler offline
MACRO	MACRO,	BURRITOMACRO	MACRO,	BURRITOMACRO	MACRO,	BURRITOMACRO	MACRO,	BURRITOMACRO	MACRO,	BURRITOMACRO	MACRO,	BURRITO
MACRO	MACRO,	BURRITO
MACRO	MACRO,	BURRITO
MACRO	MACRO,	BURRITO
MACRO	MACRO,	BURRITO
MACRO	MACRO,	BURRITO
MACRO	MACRO,	BURRITO
MACRO	MACRO,	BURRITO
MACRO	MACRO,	BURRITO
MACRO	MACRO,	BURRITOMACRO	MACRO,	BURRITO
BURRITOBURRITOBURRITOBURRITOBURRITOBURRITO
@marioggar
1
SOBRE	MI
Mario	Garcia
Trabajo	en	Kaleidos
Programo	con	Groovy,	JDK_8
https://twitter.com/marioggar
http://kaleidos.net/
2
DE	QUE	VOY	A	HABLAR	?
Meta	programacion
Macros
Asteroid
3
THEORY	101
Teoria	basica	para	entender	el	api	AST.
4
QUE
5 . 1
ABSTRACT	SYNTAX	TREE
El	compilador	necesita	una	representacion	de	tu	codigo:
5 . 2
EXPRESSIONS
Una	expresion	es	una	combinacion	de	uno	o	mas	valores,
constantes	variables,	operadores,	y	funciones	que	el
lenguage	de	programacion	interpreta	y	ejecuta	para	producir
otro	valor.
5 . 3
BINARY	⇒	BOOLEAN
BinaryExpression
constant	expression	1
token	==
constant	expression	1
1	==	1
5 . 4
VARIABLE	⇒	CONSTANT	⇒	CALL
variable	expression	ref
constant	myMethod
param	expression	3
ref.myMethod(3)
5 . 5
SENTENCIAS
En	programacion,	una	sentencia	es	la	parte	mas	pequena	de
un	lenguage	de	programacion	imperativo	que	expresa	una
accion	que	se	debe	llevar	a	cabo.	Una	sentencia	puede	tener
expresiones.
5 . 6
IF	STATEMENT
expression	to	evaluate
statement	to	be	executed	if	the	boolean	expression
evaluates	to	true
if(booleanExpression)	{
	println	"hello"	//	statement
}
5 . 7
BLOCK	STATEMENT
A	block	statement	is	easily	recognized	by	curly	braces
It	is	built	from	other	statements	containing	expressions
public	void	main(String[]	args)	{	//	block	starts
		//	this	is	inside	a	block	statement
}	//	block	ends
5 . 8
BLOCK	STATEMENT	(CONT.)
This	block	statement	contains	a	return	statement	receiving	a
constant	expression	Hello	Greach.
public	String	greetings()	{
				return	"Hello	Greach"
}
5 . 9
NODES
—	Lord	of	the	Rings
A	ring	to	rule	them	all
5 . 10
NODES	(CONT.)
Como	esta	estructurado	nuestro	programa.	Agrupana
sentencia	y	expressions.
classes
methods
fields
properties
…​
5 . 11
A	CLASS	NODE
ClassNode	may	contain:	methods,	fields…​
MethodNode	may	contain	statements,	and	expressions
…​
class	A	{	//	ClassNode
			String	greetings	//	FieldNode
			String	hello()	{	//	MethodNode
			}
}
5 . 12
POR	LO	TANTO
class	A	{	//	ClassNode
			String	hello()	//	MethodNode
			{	//	blockStatement	{
							return	"Hello"	//	returnStatement(constantExpression)
				}	//	}
}
5 . 13
CUANDO
6 . 1
EN	QUE	MOMENTOS	PUEDO	ENGANCHARME	AL
COMPILADOR	PARA	CAMBIAR	EL	AST	?
Depends	on	type	of	transformation	(Local	vs	Global)
Depends	on	the	Compilation	Phase	you	need	to	target
6 . 2
COMPILATION	PHASES
Initialization,	Parsing,	Conversion,	Semantic,
Canonicalization,	Instruction,	Class,	Output,	Finalization
Groovy	Reference
6 . 3
RESUMIENDO
Semantic	Analysis
Canonicalization
Instruction
Before	that	you	have	no	types/scopes/imports…​
After	that	you	better	know	ByteCode-Kunfu
6 . 4
META	PROGRAMACION
7 . 1
7 . 2
QUE	ES	?
"Metaprogramming	bla	bla	blabla…​	It	means	that	a	program
could	be	designed	to	read,	generate,	analyse	or	transform
other	programs,	and	even	modify	itself	while	running.bla
blabla	bla…​blabla	bla	blablabla	minimize	the	number	of	lines
of	code	to	express	a	solution	…​	y	blablabla. 
— https://en.wikipedia.org/wiki/Metaprogramming
7 . 3
RESUMIENDO…​
Leer,	generar,	analizar,	transformar	tu	codigo
Trata	de	expresar	lo	mismo	con	menos	codigo
7 . 4
7 . 5
DOS	SABORES:
En	tiempo	de	EJECUCION
En	tiempo	de	COMPILACION
7 . 6
TIEMPO	DE	EJECUCION:	PROS
Sencillo
Facil	de	testear
7 . 7
TIEMPO	DE	EJECUCION:	CONS
Dificil	de	aplicar	aisladamente
Problema	de	polucion	del	codigo
Te	das	cuenta	de	los	problemas	en	tiempo	de	ejecucion
7 . 8
EJEMPLOS:	QUICK	DEMO
7 . 9
TIEMPO	DE	EJECUCION:	TABLA
Name Category Difficulty
invokeMethod Runtime Easy
method/propertyMissing Runtime Easy
MetaClass Runtime Easy/Tricky
7 . 10
TIEMPO	DE	COMPILACION:	PROS
Puedes	controlar	mejor	como	se	aplican	los	cambios
Puedes	crear	nuevas	formas	de	expresar	tu	codigo
Muchos	problemas	se	detectan	por	el	compilador
7 . 11
TIEMPO	DE	COMPILACION:	CONS
Hasta	ahora	curva	de	apredizaje	parecida	a…​
Haskell	?
Desconocimiento	del	compilador	de	Groovy
7 . 12
TIEMPO	DE	COMPILACION:	TABLA
Name Category Difficulty
Traits Compile	time Super-Easy
Extensions Compile	time Easy
Local Compile	time Hard
Global Compile	time Hardcore
7 . 13
POR	QUE	SON	NECESARIAS	LAS	MACROS	?
8
EN	PARTE	POR…​
9
LA	VIEJA	TRANSFORMACION	AST
10 . 1
10 . 2
COSAS	QUE	NO	CAMBIAN
Transformaciones	LOCALES
Transformaciones	GLOBALES
10 . 3
AST	LOCALES
11 . 1
UN	"SIMPLE"	EJEMPLO:
11 . 2
ANOTACION
package	compile.old.local.md5
import	org.codehaus.groovy.transform.GroovyASTTransformationClass
import	java.lang.annotation.ElementType
import	java.lang.annotation.Retention
import	java.lang.annotation.RetentionPolicy
import	java.lang.annotation.Target
@Retention(RetentionPolicy.SOURCE)
@Target([ElementType.TYPE])
@GroovyASTTransformationClass(
				["compile.old.local.md5.MD5Transform"])
@interface	MD5	{	}
11 . 3
TRANSFORMATION
import	org.codehaus.groovy.ast.*
import	org.codehaus.groovy.control.*
import	org.codehaus.groovy.transform.*
@GroovyASTTransformation(phase	=	CompilePhase.SEMANTIC_ANALYSIS)
class	MD5Transform	extends	AbstractASTTransformation	{
				@Override
				void	visit(ASTNode[]	nodes,	SourceUnit	sourceUnit)	{
							//...
				}
}
11 . 4
APLICACION
package	compile.old.local.md5
@MD5
class	Document	{
				File	file
				String	name
				void	printMD5()	{
								println	"===>${nameAsMD5()}"
								println	"===>${fileAsMD5()}"
				}
}
11 . 5
VEAMOS	LA	TRANSFORMACION…​
11 . 6
11 . 7
TRANSFORMACION	(I)
imports
import	static	org.codehaus.groovy.ast.tools.GeneralUtils.*
import	static	org.codehaus.groovy.ast.ClassHelper.*
import	org.codehaus.groovy.ast.*
import	org.codehaus.groovy.ast.expr.*
import	org.codehaus.groovy.ast.stmt.*
import	org.codehaus.groovy.control.*
import	org.codehaus.groovy.transform.*
11 . 8
TRANSFORMACION	(II)
clase	transformacion
@GroovyASTTransformation(phase	=	CompilePhase.SEMANTIC_ANALYSIS)
class	MD5Transform	extends	AbstractASTTransformation	{
11 . 9
TRANSFORMACION	(III)
visit	method
				@Override
				void	visit(ASTNode[]	nodes,	SourceUnit	sourceUnit)	{
								ClassNode	currentClass	=	(ClassNode)	nodes[1]
								currentClass.fields.each	{	FieldNode	field	->
												currentClass.addMethod(createMD5Method(field))
								}
				}
11 . 10
TRANSFORMACION	(IV)
				MethodNode	createMD5Method(FieldNode	node)	{
								return	new	MethodNode("${node.name}asMD5",
												ACC_PUBLIC,
												ClassHelper.STRING_TYPE,
												[]	as	Parameter[],
												[]	as	ClassNode[],
												createBlock(node))
				}
11 . 11
TRANSFORMACION	(V)
				BlockStatement	createBlock(FieldNode	node)	{
								return	block(
												stmt(
																callX(
																				callX(
																								callX(
																												callX(
																																make(java.security.MessageDigest),
																																'getInstance',
																																args(constX('MD5'))
																												),
																												constX('digest'),
																												args(
																																callX(
																																				varX(node.name),
																																				constX('getBytes'),
																																				args(constX('UTF-8'))
																																)
																												)
																								),
																								constX('encodeHex'),
																								args()
																				),
																				constX('toString'), 11 . 12
11 . 13
QUE	ESTA	MAL	EN	EL	EJEMPLO	?
11 . 14
AGGREGAR	UN	SIMPLE	METODO…​
Requiere	conocer	bastante	el	API	de	AST
Requiere	saber	como	se	construye	el	AST
Requiere	un	monton	de	codigo	:(
11 . 15
SE	PODRIA	HABER	HECHO	"MEJOR"	?
11 . 16
ASTBUILDER.BUILDFROMCODE
AstBuilder.buildFromCode	es	el	abuelo	de	las	macros
El	codigo	que	genera	es	buggy
Vamos	que	no	lo	uses!
Si	tienes	que	usar	alguno,	usa…​
11 . 17
ASTBUILDER.BUILDFROMSTRING
AstBuilder.buildFromString
No	tendras	chequeo	estatico	de	codigo	pero…​
El	codigo	sera	compatible	a	futuro
11 . 18
ASTBUILDER.BUILDFROMSTRING
				BlockStatement	createBlock(FieldNode	node)	{
								return	AstBuilder.buildFromString("""
												return	java.security.MessageDigest
														.getInstance('MD5')
														.digest(${node.name}.getBytes())
														.encodeHex()
														.toString()
									""").first()	as	BlockStatement
				}
11 . 19
QUIERO	ESTO	MISMO…​PERO	BIEN!
11 . 20
MACROS
12 . 1
12 . 2
NOVETA!!	NOVETA!!	EN	2.5.0
Gracias	a	@bsideup	y	@melix
http://docs.groovy-lang.org/docs/groovy-2.5.0-
SNAPSHOT/
12 . 3
QUE	ES	UNA	MACRO	?
—	Wikipedia
En	programación,	instrucción	escrita	en	un
lenguaje	fuente	que	equivale	a	varias
instrucciones	de	lenguaje	máquina.
12 . 4
QUE	ES	UNA	MACRO	?	(CONT)
En	Groovy,	una	macro	es	una	funcion	que	representa	un	set
de	instrucciones.	En	tiempo	de	compilacion	se	sustituye
parte	del	codigo	de	tu	aplicacion	(marcadores)	por	el	set	de
instrucciones	que	encapsulaban	estas	macros.
12 . 5
EJEMPLO	ILUSTRATIVO
Tenemos	macroX	=	"hombre	muy	alto"
Y	sustituimos	el	marcador	x	en	"John	es	un	x"	por	el
contenido	de	la	macro
Y	tendriamos	"John	es	un	hombre	muy	alto"
12 . 6
QUE	NOS	DAN	LAS	MACROS
Nos	dan	seguridad	de	tipos
Nos	permiten	devolver	expressiones	o	statements
Nos	permiten	especificar	el	momento	del	compilador	en	el
que	se	procesara	el	codigo
Nos	permiten	substituir	variables
12 . 7
COMO	ENCAPULAMOS	EL	CODIGO	?
12 . 8
MACRO	METHOD	(I)
En	realidad	es	una	meta-transformacion
El	codigo	que	encapsula	lo	transforma	a	llamadas	del	API
AST
Puede	crear	tanto	Statements	como	Expresiones
12 . 9
MACRO	METHOD	(II)
MethodCallExpression	expression	=	macro	{	println	"hey"	}
MethodCallExpression	expression	=
				callThisX('println',	param(constX('hey')))
ConstantExpression	expression	=	macro	{	42	}
ConstantExpression	expression	=	new	ConstantExpression(42)
ReturnStatement	statement	=	macro(true)	{	return	1	+	1	}
ReturnStatement	statement	=
	new	ReturnStatement(
				new	BinaryExpression(
								new	ConstantExpression(42...
12 . 10
MACRO	METHOD	(III)
true	si	quieres	que	devuelva	un	Statement
false	si	quieres	que	devuelva	un	Expression
macro(boolean)	{	/*	...CODE...	*/}
12 . 11
EJEMPLO
@Add	aggrega	el	metodo	getMessage()
getMessage()	devolvera	siempre	42
@Add
class	A	{
}
assert	new	A().getMessage()	==	42
12 . 12
SIN	MACROS
ClassNode	classNode	=	(ClassNode)	nodes[1]
ReturnStatement	code	=
				new	ReturnStatement(
								new	ConstantExpression(42))
MethodNode	methodNode	=
				new	MethodNode(
								"getMessage",
								ACC_PUBLIC,
								ClassHelper.make(String),
								[]	as	Parameter[],
								[]	as	ClassNode[],
								code)
classNode.addMethod(methodNode)
12 . 13
CON	MACROS
ClassNode	classNode	=	(ClassNode)	nodes[1]
ReturnStatement	code	=	macro	{	return	"42"	}
MethodNode	methodNode	=
				new	MethodNode(
								"getMessage",
								ACC_PUBLIC,
								ClassHelper.make(String),
								[]	as	Parameter[],
								[]	as	ClassNode[],
								code)
classNode.addMethod(methodNode)
12 . 14
MACRO	METHOD	(CONT.)
Fase	de	compilacion	en	el	que	quieras	que	se	procese	el
codigo
Puedes	tambien	indicar	si	devuelve	un	Statement	o	un
Expression
macro(CompilePhase,	boolean)	{	/*	...CODE...	*/}
12 . 15
MD5	REVISITED
				BlockStatement	createBlock(FieldNode	node)	{
								return	block(
												stmt(
																callX(
																				callX(
																								callX(
																												callX(
																																make(java.security.MessageDigest),
																																'getInstance',
																																args(constX('MD5'))
																												),
																												constX('digest'),
																												args(
																																callX(
																																				varX(node.name),
																																				constX('getBytes'),
																																				args(constX('UTF-8'))
																																)
																												)
																								),
																								constX('encodeHex'),
																								args()
																				),
																				constX('toString'), 12 . 16
CON	MACROS
BlockStatement	createBlock(FieldNode	node)	{
				VariableExpression	fieldVar	=	GeneralUtils.varX(fieldNode.name)
				return	macro(CompilePhase.SEMANTIC_ANALYSIS,	true)	{
								return	java.security.MessageDigest
																.getInstance('MD5')
																.digest($v	{	fieldVar}	.getBytes())
																.encodeHex()
																.toString()
				}
}
12 . 17
AHORA…​
Es	codigo	normal,	no	un	string	o	llamadas	al	API	de	AST
Se	puede	compilar	estaticamente
Puedes	sustituir	variables
12 . 18
Y	CREAR	EL	METODO	ENTERO	?
MacroClass
Necesita	@CompileDynamic
http://docs.groovy-lang.org/docs/groovy-2.5.0-
SNAPSHOT/html/documentation/#_macroclass
12 . 19
AUN	ASI…​
Las	ASTs	siguen	teniendo	mucha	ceremonia
12 . 20
ASTEROID
13 . 1
13 . 2
QUE	ES	ASTEROID
Es	una	biblioteca	que	Busca	reducir	el	codigo	de	tus	ASTs
http://grooviter.github.io/asteroid/
13 . 3
ORGANIZACION
Abstracciones	sobre	transformaciones	Locales	y	Globales
Fluent	API	para	crear	expresiones,	metodos	y/o
13 . 4
EJEMPLO	MD5
13 . 5
ANOTACION
package	compile.old.local.md5
import	org.codehaus.groovy.transform.GroovyASTTransformationClass
import	java.lang.annotation.ElementType
import	java.lang.annotation.Retention
import	java.lang.annotation.RetentionPolicy
import	java.lang.annotation.Target
@Retention(RetentionPolicy.SOURCE)
@Target([ElementType.TYPE])
@GroovyASTTransformationClass(
				["compile.old.local.md5.MD5Transform"])
@interface	MD5	{	}
package	compile.gro.local.md5
import	asteroid.Local
@Local(MD5Transform)
@interface	MD5	{	}
13 . 6
DECLARACION	AST
antes
ahora
@GroovyASTTransformation(phase	=	CompilePhase.SEMANTIC_ANALYSIS)
class	MD5Transform	extends	AbstractASTTransformation	{
@Phase(Phase.LOCAL.SEMANTIC_ANALYSIS)
class	MD5Transform	extends	AbstractLocalTransformation<MD5,	ClassNode>	{
13 . 7
DECLARACION	AST	(CONT.)
No	te	equivocas	de	fase	de	compilacion
Declaras	que	tipo	de	anotacion	va	a	procesar	(MD5)
Declaras	sobre	que	tipo	se	va	a	aplicar	(ClassNode)
13 . 8
METODO	DOVISIT
antes
ahora
@Override
void	visit(ASTNode[]	nodes,	SourceUnit	sourceUnit)	{
				ClassNode	currentClass	=	(ClassNode)	nodes[1]
				currentClass.fields.each	{	FieldNode	field	->
								currentClass.addMethod(createMD5Method(field))
				}
}
@Override
void	doVisit(AnnotationNode	annotation,	ClassNode	node)	{
				node.fields.each	{	FieldNode	field	->
								node.addMethod(createMD5Method(field))
				}
}
13 . 9
METODO	DOVISIT	(CONT.)
Ya	no	hacen	falta	el	horrible	casting	de	tipos
13 . 10
CREANDO	METODO
Los	builders	te	guian	si	no	conoces	el	API
MethodNode	createMD5Method(FieldNode	node)	{
				return	A.NODES.method("${node.name}ToMD5")
						.modifiers(A.ACC.ACC_PUBLIC)
						.returnType(String)
						.code(createBlock(node))
						.build()
}
13 . 11
CREAR	METODO	MD5
BlockStatement	createBlock(FieldNode	node)	{
				VariableExpression	fieldVar	=	GeneralUtils.varX(node.name)
				return	macro(CompilePhase.SEMANTIC_ANALYSIS,	true)	{
								return	java.security.MessageDigest
										.getInstance('MD5')
										.digest($v	{	fieldVar	}.getBytes())
										.encodeHex()
										.toString()
				}
}
13 . 12
CREAR	METODO	MD5	(CONT.)
Todo	es	codigo	compilado
No	pierdes	dinamismo	gracias	a	los	placeholders
Aun	asi,	necesitas	saber	si	necesitas	una	Expr.	o	un	Stmt.
13 . 13
QUE	NO	HE	VISTO	Y	QUE	MEREZCA	LA	PENA	?
MacroClass
ASTMatcher
http://docs.groovy-lang.org/docs/groovy-2.5.0-
SNAPSHOT/html/documentation/#_macroclass
http://docs.groovy-lang.org/docs/groovy-2.5.0-
SNAPSHOT/html/documentation/#_astmatcher
14 . 1
DE	TODAS	MANERAS
Las	ASTs	con	o	sin	macros	no	son	el	mejor	sitio	por	donde
empezar
en	serio
Traits,	extension	modules,	ASTs	es	el	camino	mas
recomendado
Revisar	la	documentacion	de	Groovy
14 . 2
:)
14 . 3
Q	&	A
14 . 4
RAFFLE
14 . 5

Mais conteúdo relacionado

Destaque

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
 
Api architectures for the modern enterprise
Api architectures for the modern enterpriseApi architectures for the modern enterprise
Api architectures for the modern enterpriseCA API Management
 
What is tackled in the Java EE Security API (Java EE 8)
What is tackled in the Java EE Security API (Java EE 8)What is tackled in the Java EE Security API (Java EE 8)
What is tackled in the Java EE Security API (Java EE 8)Rudy De Busscher
 

Destaque (12)

Groovy android
Groovy androidGroovy android
Groovy android
 
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
 
Api architectures for the modern enterprise
Api architectures for the modern enterpriseApi architectures for the modern enterprise
Api architectures for the modern enterprise
 
What is tackled in the Java EE Security API (Java EE 8)
What is tackled in the Java EE Security API (Java EE 8)What is tackled in the Java EE Security API (Java EE 8)
What is tackled in the Java EE Security API (Java EE 8)
 
Gorm for cassandra
Gorm for cassandraGorm for cassandra
Gorm for cassandra
 

Mais de Mario García

Blockchain 101 (spanish)
Blockchain 101 (spanish)Blockchain 101 (spanish)
Blockchain 101 (spanish)Mario García
 
Jbake workshop (Greach 2019)
Jbake workshop (Greach 2019)Jbake workshop (Greach 2019)
Jbake workshop (Greach 2019)Mario García
 
Groovy 2.5 and 3.0 (Spanish)
Groovy 2.5 and 3.0 (Spanish)Groovy 2.5 and 3.0 (Spanish)
Groovy 2.5 and 3.0 (Spanish)Mario García
 
Calidad del codigo (MadridGUG)
Calidad del codigo (MadridGUG)Calidad del codigo (MadridGUG)
Calidad del codigo (MadridGUG)Mario García
 
Creating ASTTs The painful truth
Creating ASTTs The painful truthCreating ASTTs The painful truth
Creating ASTTs The painful truthMario García
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with GroovyMario García
 
Test Motherfucker...Test
Test Motherfucker...TestTest Motherfucker...Test
Test Motherfucker...TestMario García
 
Programación concurrente con GPars
Programación concurrente con GParsProgramación concurrente con GPars
Programación concurrente con GParsMario García
 
Greach 2011 : Creando Plugins Con Griffon
Greach 2011 : Creando Plugins Con GriffonGreach 2011 : Creando Plugins Con Griffon
Greach 2011 : Creando Plugins Con GriffonMario García
 

Mais de Mario García (15)

Blockchain 101 (spanish)
Blockchain 101 (spanish)Blockchain 101 (spanish)
Blockchain 101 (spanish)
 
Jbake workshop (Greach 2019)
Jbake workshop (Greach 2019)Jbake workshop (Greach 2019)
Jbake workshop (Greach 2019)
 
Groovy 2.5 and 3.0 (Spanish)
Groovy 2.5 and 3.0 (Spanish)Groovy 2.5 and 3.0 (Spanish)
Groovy 2.5 and 3.0 (Spanish)
 
GraphQL & Ratpack
GraphQL & RatpackGraphQL & Ratpack
GraphQL & Ratpack
 
GraphQL y Groovy
GraphQL y GroovyGraphQL y Groovy
GraphQL y Groovy
 
Calidad del codigo (MadridGUG)
Calidad del codigo (MadridGUG)Calidad del codigo (MadridGUG)
Calidad del codigo (MadridGUG)
 
GraphQL and Groovy
GraphQL and GroovyGraphQL and Groovy
GraphQL and Groovy
 
Creating ASTTs The painful truth
Creating ASTTs The painful truthCreating ASTTs The painful truth
Creating ASTTs The painful truth
 
Groovy on Android
Groovy on AndroidGroovy on Android
Groovy on Android
 
Gpars Workshop 2014
Gpars Workshop 2014Gpars Workshop 2014
Gpars Workshop 2014
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
Test Motherfucker...Test
Test Motherfucker...TestTest Motherfucker...Test
Test Motherfucker...Test
 
Programación concurrente con GPars
Programación concurrente con GParsProgramación concurrente con GPars
Programación concurrente con GPars
 
Gradle vs Maven
Gradle vs MavenGradle vs Maven
Gradle vs Maven
 
Greach 2011 : Creando Plugins Con Griffon
Greach 2011 : Creando Plugins Con GriffonGreach 2011 : Creando Plugins Con Griffon
Greach 2011 : Creando Plugins Con Griffon
 

Último

Delitos informáticos en Slideshare.pptx
Delitos informáticos en  Slideshare.pptxDelitos informáticos en  Slideshare.pptx
Delitos informáticos en Slideshare.pptxmaykolmagallanes012
 
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVO
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVOSISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVO
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVOELIAMARYTOVARFLOREZD
 
Se realiza instalacion y configuraacion servicios Windows
Se realiza instalacion y configuraacion servicios WindowsSe realiza instalacion y configuraacion servicios Windows
Se realiza instalacion y configuraacion servicios WindowsCZSOTEC
 
Instalacion de servicios windows, configuracion y aplicacion.
Instalacion de servicios windows, configuracion y aplicacion.Instalacion de servicios windows, configuracion y aplicacion.
Instalacion de servicios windows, configuracion y aplicacion.CZSOTEC
 
Webinar Resolucion2335 de 2023 Kubapp.pdf
Webinar Resolucion2335 de 2023 Kubapp.pdfWebinar Resolucion2335 de 2023 Kubapp.pdf
Webinar Resolucion2335 de 2023 Kubapp.pdfAnaRosaMontenegro
 
MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptx
MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptxMacOS SISTEMA OPERATIVO CARACTERISTICAS.pptx
MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptxcalzadillasluis134
 

Último (6)

Delitos informáticos en Slideshare.pptx
Delitos informáticos en  Slideshare.pptxDelitos informáticos en  Slideshare.pptx
Delitos informáticos en Slideshare.pptx
 
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVO
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVOSISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVO
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVO
 
Se realiza instalacion y configuraacion servicios Windows
Se realiza instalacion y configuraacion servicios WindowsSe realiza instalacion y configuraacion servicios Windows
Se realiza instalacion y configuraacion servicios Windows
 
Instalacion de servicios windows, configuracion y aplicacion.
Instalacion de servicios windows, configuracion y aplicacion.Instalacion de servicios windows, configuracion y aplicacion.
Instalacion de servicios windows, configuracion y aplicacion.
 
Webinar Resolucion2335 de 2023 Kubapp.pdf
Webinar Resolucion2335 de 2023 Kubapp.pdfWebinar Resolucion2335 de 2023 Kubapp.pdf
Webinar Resolucion2335 de 2023 Kubapp.pdf
 
MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptx
MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptxMacOS SISTEMA OPERATIVO CARACTERISTICAS.pptx
MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptx
 

Macro macro, burrito burrit