Articulo de referencia

Apache Groovy

Jochen Theodorou (Tech Lead) Guillaume Laforge Cedric Champeau Daniel Sun Eric Milles"},"released":{"wt":"{{Start date and age|2003}}"},"latest release version":{"wt":""},"lates...

Apache Groovy es un lenguaje de programación orientado a objetos compatible con la sintaxis de Java para la plataforma Java . Es un lenguaje tanto estático como dinámico con características similares a las de Python , Ruby y Smalltalk . Puede utilizarse como lenguaje de programación y de scripting para la plataforma Java, se compila a bytecode de la máquina virtual Java (JVM) e interactúa sin problemas con otros códigos y bibliotecas Java . Groovy utiliza una sintaxis de llaves similar a la de Java. Groovy admite cierres , cadenas multilínea y expresiones incrustadas en cadenas . Gran parte de la potencia de Groovy reside en sus transformaciones de árbol de sintaxis abstracta (AST), que se activan mediante anotaciones.

Groovy 1.0 se lanzó el 2 de enero de 2007 y Groovy 2.0 en julio de 2012. Desde la versión 2, Groovy se puede compilar estáticamente , ofreciendo inferencia de tipos y rendimiento cercanos a los de Java. [ 3 ] [ 4 ] Groovy 2.4 fue el último lanzamiento importante bajo el patrocinio de Pivotal Software , que finalizó en marzo de 2015. [ 5 ] Desde entonces, Groovy ha cambiado su estructura de gobernanza a un Comité de Gestión de Proyectos en la Apache Software Foundation . [ 6 ]

Historia

James Strachan habló por primera vez sobre el desarrollo de Groovy en su blog en agosto de 2003. [ 7 ] En marzo de 2004, Groovy se presentó al Java Community Process (JCP) como JSR 241 [ 8 ] y fue aceptado por votación. Se publicaron varias versiones entre 2004 y 2006. Después de que comenzó el esfuerzo de estandarización del JCP, la numeración de versiones cambió y se publicó una versión llamada "1.0" el 2 de enero de 2007. Después de varias versiones beta y candidatas a lanzamiento numeradas como 1.1, el 7 de diciembre de 2007, se publicó Groovy 1.1 Final y se renumeró inmediatamente como Groovy 1.5 para reflejar los muchos cambios realizados.

En 2007, Groovy ganó el primer premio en el premio a la innovación JAX 2007. [ 9 ] En 2008, Grails , un framework web Groovy , ganó el segundo premio en el premio a la innovación JAX 2008. [ 10 ]

En noviembre de 2008, SpringSource adquirió la empresa Groovy and Grails (G2One). [ 11 ] En agosto de 2009, VMware adquirió SpringSource. [ 12 ]

En abril de 2012, después de ocho años de inactividad, el líder de especificaciones cambió el estado de JSR 241 a inactivo. [ 8 ]

Strachan había abandonado el proyecto en silencio un año antes del lanzamiento de Groovy 1.0 en 2007. En octubre de 2016, Strachan declaró: "Todavía me encanta Groovy (¡las canalizaciones de Jenkins son geniales!), Java, Go, TypeScript y Kotlin". [ 13 ]

El 2 de julio de 2012 se lanzó Groovy 2.0, que, entre otras novedades, añadió compilación estática y comprobación de tipos estática .

Cuando la empresa conjunta Pivotal Software fue escindida por EMC Corporation (EMC) y VMware en abril de 2013, Groovy y Grails formaron parte de su cartera de productos. Pivotal dejó de patrocinar Groovy y Grails a partir de abril de 2015. [ 5 ] Ese mismo mes, Groovy cambió su estructura de gobernanza de un repositorio Codehaus a un Comité de Gestión de Proyectos (PMC) en la Apache Software Foundation a través de su incubadora. [ 6 ] Groovy se graduó de la incubadora de Apache y se convirtió en un proyecto de nivel superior en noviembre de 2015. [ 14 ]

El 7 de febrero de 2020 se lanzó Groovy 3.0. [ 15 ] La versión 4.0 se lanzó el 25 de enero de 2022. [ 16 ]

Características

La mayoría de los archivos Java válidos también son archivos Groovy válidos. Aunque ambos lenguajes son similares, el código Groovy puede ser más compacto, ya que no necesita todos los elementos que requiere Java. [ 17 ] Esto permite a los programadores Java aprender Groovy gradualmente, comenzando con la sintaxis familiar de Java antes de adquirir más modismos de programación Groovy . [ 18 ]

Las características de Groovy que no están disponibles en Java incluyen tipado estático y dinámicodef (con la palabra clave ), sobrecarga de operadores , sintaxis nativa para listas y matrices asociativas (mapas), soporte nativo para expresiones regulares , iteración polimórfica, interpolación de cadenas , métodos auxiliares añadidos y el operador de navegación segura?. para comprobar automáticamente los punteros nulos (por ejemplo, variable?.method(), o variable?.field). [ 19 ]

Desde la versión 2, Groovy también admite modularidad (distribuyendo solo los jarque usa el proyecto, reduciendo así el tamaño de la biblioteca de Groovy), verificación de tipos, compilación estática, mejoras de sintaxis de Project Coin, bloques multicatch y mejoras de rendimiento continuas mediante la invokedynamicinstrucción introducida en Java 7. [ 20 ]

Groovy admite de forma nativa lenguajes de marcado como XML y HTML mediante una sintaxis de Modelo de Objetos de Documento (DOM) integrada. Esta característica permite definir y manipular diversos tipos de datos heterogéneos con una sintaxis y una metodología de programación uniformes y concisas.

A diferencia de Java, un archivo de código fuente Groovy puede ejecutarse como un script (sin compilar) si contiene código fuera de cualquier definición de clase, si es una clase con un método main o si es un Runnable o GroovyTestCase . Un script Groovy se analiza, compila y genera completamente antes de su ejecución (de forma similar a Python y Ruby). Esto ocurre internamente y la versión compilada no se guarda como un artefacto del proceso. [ 21 ]

GroovyBeans, propiedades

GroovyBeans es la versión de Groovy de JavaBeans . Groovy genera implícitamente métodos getter y setter. En el siguiente código, setColor(String color)y getColor()se generan implícitamente. Las dos últimas líneas, que parecen acceder directamente al color, en realidad llaman a los métodos generados implícitamente. [ 22 ]

clase AGroovyBean { String color }def myGroovyBean = nuevo AGroovyBean ()myGroovyBean.setColor ( ' baby blue' ) assert myGroovyBean.getColor ( ) == ' baby blue'myGroovyBean.color = ' pewter ' assert myGroovyBean.color == ' pewter '

Groovy ofrece una sintaxis simple y consistente para manejar listas y mapas , que recuerda a la sintaxis de matrices de Java . [ 23 ]

def movieList = [ 'Dersu Uzala' , 'Ran' , 'Los siete samuráis' ] // Parece un array, pero es una lista assert movieList [ 2 ] == 'Los siete samuráis' movieList [ 3 ] = 'Casablanca' // Agrega un elemento a la lista assert movieList . size () == 4def monthMap = [ 'Enero' : 31 , 'Febrero' : 28 , 'Marzo' : 31 ] // Declara un mapa assert monthMap [ 'Marzo' ] == 31 // Accede a una entrada monthMap [ 'Abril' ] = 30 // Agrega una entrada al mapa assert monthMap . size () == 4

Extensión del prototipo

Groovy ofrece soporte para la extensión de prototipos a través de , Módulos de extensión (solo en Groovy 2), CategoríasExpandoMetaClass tipo Objective-C y . [ 24 ]DelegatingMetaClass

ExpandoMetaClassOfrece un lenguaje específico de dominio (DSL) para expresar fácilmente los cambios en la clase, similar al concepto de clase abierta de Ruby :

Número.metaClass { sqrt = { Math.sqrt ( delegate ) } }afirmar 9 . sqrt () == 3 afirmar 4 . raíz cuadrada () == 2

Los cambios que Groovy realiza en el código mediante prototipado no son visibles en Java, ya que cada invocación de atributo o método en Groovy pasa por el registro de metaclases. El código modificado solo se puede acceder desde Java a través de dicho registro.

Groovy también permite sobrescribir métodos como getProperty(), propertyMissing()entre otros, lo que permite al desarrollador interceptar llamadas a un objeto y especificar una acción para ellas, de una manera simplificada y orientada a aspectos . El siguiente código permite que la clase java.lang.Stringresponda a la hexpropiedad:

enum Color { NEGRO ( '#000000' ), BLANCO ( '#FFFFFF' ), ROJO ( '#FF0000 ' ), AZUL ( '#0000FF' ) String hex Color ( String hex ) { this . hex = hex } }String . metaClass . getProperty = { String property -> def stringColor = delegate if ( property == 'hex' ) { Color . values ​​(). find { it . name (). equalsIgnoreCase stringColor }?. hex } }assert "WHITE" . hex == "#FFFFFF" assert "BLUE" . hex == "#0000FF" assert "BLACK" . hex == "#000000" assert "GREEN" . hex == null

El marco Grails utiliza ampliamente la metaprogramación para habilitar buscadores dinámicos GORM , como User.findByName('Josh')y otros. [ 25 ]

Punto y paréntesis

La sintaxis de Groovy permite omitir paréntesis y puntos en algunas situaciones. El siguiente código Groovy

tomar ( café ). con ( azúcar , leche ). y ( licor )

se puede escribir como

Tomar café con azúcar , leche y licor.

posibilitando el desarrollo de lenguajes específicos de dominio (DSL, por sus siglas en inglés) que se asemejan al inglés común.

Programación funcional

Aunque Groovy es principalmente un lenguaje orientado a objetos, también ofrece características de programación funcional .

Cierres

Según la documentación de Groovy: "Los cierres en Groovy funcionan de manera similar a un 'puntero de método', lo que permite escribir y ejecutar código en un momento posterior". [ 26 ] Los cierres de Groovy admiten variables libres, es decir, variables que no se han pasado explícitamente como parámetro, pero que existen en su contexto de declaración, aplicación parcial (que denomina ' currying ' [ 27 ] ), delegación, implícito, parámetros tipados y sin tipar.

Al trabajar con colecciones de un tipo determinado, se puede inferir el cierre que se pasa a una operación sobre la colección:

lista = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]/* * Los números distintos de cero se convierten a verdadero, por lo que cuando it % 2 == 0 (par), es falso. * El tipo del parámetro implícito "it" puede ser inferido como un Integer por el IDE. * También podría escribirse como: * list.findAll { Integer i -> i % 2 } * list.findAll { i -> i % 2 } */ def odds = list . findAll { it % 2 }afirmar probabilidades == [ 1 , 3 , 5 , 7 , 9 ]

Un grupo de expresiones se puede escribir en un bloque de cierre sin hacer referencia a una implementación, y el objeto que responde se puede asignar posteriormente mediante delegación:

// Este bloque de código contiene expresiones sin referencia a una implementación def operations = { declare 5 sum 4 divide 3 print }
/* * Esta clase gestionará las operaciones que se pueden utilizar en el cierre anterior. Se podría declarar otra clase * con los mismos métodos, pero utilizando, por ejemplo, operaciones de servicio web * en los cálculos. */ class Expression { BigDecimal value/*  * Aunque se pasa un Integer como parámetro, se convierte a BigDecimal, como se  definió. * Si la clase tuviera un método 'declare(Integer value)', se usaría en su lugar.  */ def declare ( BigDecimal value ) { this . value = value } def sum ( BigDecimal valueToAdd ) { this . value += valueToAdd } def divide ( BigDecimal divisor ) { this . value /= divisor } def propertyMissing ( String property ) { if ( property == "print" ) println value } }
// Aquí se define quién va a responder a las expresiones en el bloque de código anterior. operations.delegate = new Expression ( ) operations ()

Curry

Generalmente llamada aplicación parcial , [ 27 ] esta característica de Groovy permite que los parámetros de los cierres se establezcan a un parámetro predeterminado en cualquiera de sus argumentos, creando un nuevo cierre con el valor vinculado. Proporcionar un argumento al curry()método fijará el argumento uno. Proporcionar N argumentos fijará los argumentos 1 a N.

def joinTwoWordsWithSymbol = { símbolo , primero , segundo -> primero + símbolo + segundo } assert joinTwoWordsWithSymbol ( '#' , 'Hola' , 'Mundo' ) == 'Hola#Mundo'def concatWords = joinTwoWordsWithSymbol . curry ( ' ' ) assert concatWords ( 'Hello' , 'World' ) == 'Hello World'def prependHello = concatWords.curry ( 'Hello' ) // def prependHello = joinTwoWordsWithSymbol.curry(' ', 'Hello') assert prependHello ( ' World' ) == 'Hello World'

Curry también se puede usar en la dirección inversa (fijando los últimos N argumentos) usando rcurry().

def potencia = { BigDecimal valor , BigDecimal potencia -> valor ** potencia }def cuadrado = potencia . rcurry ( 2 ) def cubo = potencia . rcurry ( 3 )afirmar potencia ( 2 , 2 ) == 4 afirmar cuadrado ( 4 ) == 16 afirmar cubo ( 3 ) == 27

Groovy también admite evaluación perezosa , [ 28 ] [ 29 ] reducción/plegado , [ 30 ] estructuras infinitas e inmutabilidad , [ 31 ] entre otras. [ 32 ]

Procesamiento de JSON y XML

En el procesamiento de JSON (JavaScript Object Notation ) y XML, Groovy emplea el patrón Builder , lo que hace que la producción de la estructura de datos sea menos verbosa. Por ejemplo, el siguiente XML:

<languages> <language year= "1995" > <name> Java </name> <paradigm> object oriented </paradigm> <typing> static </typing> </language> <language year= "1995" > <name> Ruby </name> <paradigm> functional, object oriented </paradigm> <typing> duck typing, dynamic </typing> </language> <language year= "2003" > <name> Groovy </name> <paradigm> functional, object oriented </paradigm> <typing> duck typing, dynamic, static </typing> </language> </languages>

Se puede generar mediante el siguiente código Groovy:

def escritor = new StringWriter () def constructor = new groovy.xml.MarkupBuilder ( escritor ) constructor.languages ​​{ language ( year : 1995 ) { name "Java" paradigm " object oriented" typing "static" } language(year: 1995 ) { name " Ruby " paradigm " functional , object oriented " typing " duck typing , dynamic" } language ( year: 2003 ) { name "Groovy" paradigm "functional, object oriented" typing "duck typing, dynamic, static" } }

y también se puede procesar de forma continua a través de StreamingMarkupBuilder. Para cambiar la implementación a JSON, se MarkupBuilderpuede intercambiar por JsonBuilder. [ 33 ]

Para analizarlo y buscar un lenguaje funcional, findAllel método de Groovy puede ser útil:

def languages ​​= new XmlSlurper (). parseText writer . toString ()// Aquí se emplea la sintaxis de expresiones regulares de Groovy para un comparador (=~) que se convertirá a un // valor booleano: verdadero, si el valor contiene nuestra cadena, o falso en caso contrario. def functional = languages ​​. language . findAll { it . paradigm =~ "functional" } assert functional . collect { it . name } == [ "Groovy" , "Ruby" ]

interpolación de cadenas

En Groovy, las cadenas se pueden interpolar con variables y expresiones mediante el uso de GStrings: [ 34 ]

BigDecimal cuenta = 10.0 def texto = "La cuenta muestra actualmente un saldo de $cuenta" assert texto == "La cuenta muestra actualmente un saldo de 10.0"

Las cadenas GString que contengan variables y expresiones deben declararse utilizando comillas dobles.

Una expresión compleja debe ir entre llaves. Esto evita que partes de ella se interpreten como pertenecientes a la cadena circundante en lugar de a la expresión:

BigDecimal minus = 4.0 text = "La cuenta muestra actualmente un saldo de ${account - minus}" assert text == "La cuenta muestra actualmente un saldo de 6.0"// Sin los corchetes para aislar la expresión, el resultado sería: texto = "La cuenta muestra actualmente un saldo de $cuenta - menos" assert texto == "La cuenta muestra actualmente un saldo de 10.0 - menos"

La evaluación de expresiones puede posponerse empleando la sintaxis de flecha:

BigDecimal tax = 0.15 text = "La cuenta muestra actualmente un saldo de ${->account - account*tax}" tax = 0.10// El valor del impuesto se modificó DESPUÉS de la declaración de la GString. Las variables de expresión // se vinculan solo cuando la expresión debe evaluarse realmente: assert text == "La cuenta muestra actualmente un saldo de 9.000"

Transformación de árbol de sintaxis abstracta

Según la propia documentación de Groovy, «Cuando el compilador de Groovy compila scripts y clases de Groovy, en algún punto del proceso, el código fuente se representa en memoria en forma de un Árbol de Sintaxis Concreta (AST), que luego se transforma en un Árbol de Sintaxis Abstracta (AST). El objetivo de las transformaciones del AST es permitir a los desarrolladores intervenir en el proceso de compilación para poder modificar el AST antes de que se convierta en código de bytes que ejecutará la JVM. Las transformaciones del AST proporcionan a Groovy capacidades mejoradas de metaprogramación en tiempo de compilación, lo que permite una gran flexibilidad a nivel del lenguaje, sin penalización en el rendimiento en tiempo de ejecución». [ 35 ]

Ejemplos de AST en Groovy son:

  • Transformación de categoría y mixin
  • Macro AST inmutable
  • Transformación de Newify
  • Transformación Singleton

entre otros.

El marco de pruebas Spock utiliza transformaciones AST para permitir al programador escribir pruebas en una sintaxis no compatible con Groovy, pero el código relevante se manipula posteriormente en el AST para obtener código válido. [ 36 ] Un ejemplo de dicha prueba es:

def "máximo de #a y #b es #c" () { expect: Math . max ( a , b ) == cdonde: a | b || c 3 | 5 || 5 7 | 0 || 7 0 | 0 || 0 }

Rasgos

Según la documentación de Groovy, " los traits son una construcción estructural del lenguaje que permite: la composición de comportamientos, la implementación en tiempo de ejecución de interfaces, la anulación de comportamientos y la compatibilidad con la comprobación/compilación de tipos estáticos".

Los rasgos pueden considerarse interfaces que contienen tanto implementaciones predeterminadas como estado. Un rasgo se define utilizando la palabra clave trait:

trait FlyingAbility { /* declaración de un rasgo */ String fly () { "¡Estoy volando!" } /* declaración de un método dentro de un rasgo */ }

Luego, se puede usar como una interfaz normal usando la palabra clave implements:

class Bird implements FlyingAbility {} /* Agrega el rasgo FlyingAbility a las capacidades de la clase Bird */ def bird = new Bird () /* Instancia un nuevo Bird */ assert bird . fly () == "¡Estoy volando!" /* La clase Bird obtiene automáticamente el comportamiento del rasgo FlyingAbility */

Los rasgos permiten una amplia gama de habilidades, desde la composición simple hasta la realización de pruebas.

Historial de versiones genial

  • Groovy no tiene un ciclo de lanzamiento fijo; el soporte suele cambiar con el lanzamiento de una nueva versión principal.
  • La última versión se puede descargar desde: Descargar Groovy [ 37 ]
  • El historial de versiones se basa en [ 38 ].

Adopción

Algunos ejemplos notables de la adopción de Groovy incluyen:

Soporte IDE

Muchos entornos de desarrollo integrados (IDE) y editores de texto son compatibles con Groovy:

Dialectos

Existe una implementación alternativa de Groovy:

  • Grooscript convierte código Groovy a código JavaScript . [ 48 ] Aunque Grooscript tiene algunas limitaciones en comparación con Apache Groovy, puede usar clases de dominio tanto en el servidor como en el cliente. [ 49 ] Se proporciona soporte de complementos para Grails versión 3.0, así como conversiones de código en línea. [ 50 ]

Véase también

Referencias

Citas

  1. "Versión 5.0.7" . 25 de junio de 2026. Consultado el 25 de junio de 2026 .
  2. "Groovy Goodness: Extensiones de archivo de script Groovy predeterminadas" .
  3. "Rendimiento de Groovy 2.0 en comparación con Java" . 25 de agosto de 2012.
  4. "Java vs Groovy2.0 vs Scala Simple Performance Test" . 10 de julio de 2012. Archivado del original el 10 de diciembre de 2012. Consultado el 7 de octubre de 2012 .
  5. 1 2 "Groovy 2.4 y Grails 3.0 serán los últimos lanzamientos importantes bajo el patrocinio de Pivotal" . 19 de enero de 2015.
  6. 1 2 "Groovy se une a la incubadora Apache" . 11 de marzo de 2015.
  7. James Strachan (29 de agosto de 2003). "Groovy: el nacimiento de un nuevo lenguaje dinámico para la plataforma Java" . Archivado del original el 1 de septiembre de 2003.
  8. 1 2 "Proceso de la comunidad Java JSR 241" .
  9. "Groovy gana el primer premio en el concurso de innovación JAX 2007" . 26 de abril de 2007. Archivado del original el 13 de mayo de 2015. Consultado el 7 de octubre de 2012 .
  10. "Dicen que muchas cosas pueden pasar tomando una taza de café" . Archivado del original el 19 de abril de 2011. Consultado el 7 de octubre de 2012 .
  11. "SpringSource adquiere la empresa de Groovy y Grails (G2One)" . 11 de noviembre de 2008.
  12. "VMware adquiere SpringSource" . 10 de agosto de 2009.
  13. "Tuit de James Strachan" . 24 de noviembre de 2016. Consultado el 24 de noviembre de 2016 .
  14. "Anuncio en la lista de correo de desarrolladores" .
  15. "Release GROOVY_3_0_0 · apache/groovy" . GitHub . Consultado el 27-03-2024 .
  16. "Release GROOVY_4_0_0 · apache/groovy" . GitHub . Consultado el 27 de marzo de 2024 .
  17. König 2007, pág. 32
  18. "Directrices de estilo y características del lenguaje Groovy para desarrolladores Java" . Groovy.codehaus.org. Archivado del original el 17 de enero de 2015. Consultado el 22 de enero de 2015 .
  19. "Groovy – Diferencias con Java" . Groovy.codehaus.org. Archivado del original el 17 de marzo de 2009. Consultado el 12 de agosto de 2013 .
  20. "¿Qué novedades trae Groovy 2.0?" 28 de junio de 2012.
  21. König 2007, págs. 37-8
  22. König 2007, págs. 38-9
  23. König 2007, págs. 41-3
  24. "JN3525-MetaClasses" . Archivado del original el 1 de octubre de 2012. Consultado el 7 de octubre de 2012 .
  25. "Técnicas de metaprogramación en Groovy y Grails" . 11 de junio de 2009.
  26. "Groovy - Cierres" . Archivado del original el 22 de mayo de 2012.
  27. 1 2 "¿Groovy llama 'currying' a la aplicación parcial? ", 10 de agosto de 2013
  28. "Groovy - Transformación perezosa" . Archivado del original el 8 de octubre de 2012. Consultado el 7 de octubre de 2012 .
  29. "Notas al margen: Listas perezosas en Groovy" . 3 de febrero de 2011.
  30. "Groovy's Fold" . 20 de junio de 2011. Archivado del original el 13 de febrero de 2015. Consultado el 12 de febrero de 2015 .
  31. "Programación funcional con Groovy" . 5 de noviembre de 2011.
  32. "Programación de funciones en Groovy" . Archivado del original el 8 de octubre de 2012. Consultado el 7 de octubre de 2012 .
  33. "JsonBuilder" . Archivado del original el 2 de octubre de 2012. Consultado el 7 de octubre de 2012 .
  34. "Cuerdas geniales: diferentes maneras de crearlas" . 26 de diciembre de 2009.
  35. "Metaprogramación en tiempo de compilación: transformaciones AST" . Archivado del original el 14 de octubre de 2012. Consultado el 7 de octubre de 2012 .
  36. King, Paul (2020). "Una historia del lenguaje de programación Groovy" . Proc. ACM Program. Lang . 4 : 53. doi : 10.1145/3386326 .
  37. "Descargar Groovy" .
  38. "Apache Groovy" . Fin de vida útil (EOL) Endoflife.date .
  39. "DSL Groovy para la lógica de negocio de OFBiz" . Wiki abierta del proyecto Apache OFBiz .
  40. "Ejemplos de métodos simples usando Groovy" . Wiki abierta del proyecto Apache OFBiz .
  41. "Grails en LinkedIn" . Consultado el 2 de junio de 2015 .
  42. "Jenkins Pipeline" .
  43. Rocher, Graeme (2 de octubre de 2008). "Blog de Graeme Rocher: Sky.com se relanza escrito en Grails" . Blog de Graeme Rocher . Consultado el 2 de junio de 2015 .
  44. Análisis de seguridad de las aplicaciones emergentes para hogares inteligentes
  45. "Scripting y la biblioteca de scripts | Scripting y propiedades" . www.soapui.org . Consultado el 2 de junio de 2015 .
  46. "Wired.Com" (PDF) . www.springsource.org . Consultado el 2 de junio de 2015 .
  47. "XWiki SAS" (PDF) . www.springsource.org . Consultado el 2 de junio de 2015 .
  48. "Documentación de Grooscript" . 12 de septiembre de 2016. Archivado del original el 28 de junio de 2017. Consultado el 4 de julio de 2017 .
  49. "Presentación en SpringOne/2GX sobre Grooscript" . 13 de diciembre de 2015.
  50. "Conversiones en línea de Grooscript" . 15 de mayo de 2017. Archivado del original el 9 de julio de 2017. Consultado el 4 de julio de 2017 .

Fuentes

  • König, Dierk; Pablo Rey; Guillaume Laforge; Hamlet D'Arcy; Cédric Champeau; Erik Pragt; Jon Skeet (2015). Groovy en acción, segunda edición . Manning. ISBN 978-1-935182-44-3.
  • Barclay, Kenneth; John Savage (2007). Groovy Programming: An Introduction for Java Developers . Morgan Kaufmann Publishers. ISBN 978-0-12-372507-3Archivado del original el 12 de enero de 2010. Consultado el 19 de julio de 2007 .
  • Davis, Scott (2008). Groovy Recipes: Greasing the Wheels of Java . Pragmatic Bookshelf. ISBN 978-0-9787392-9-4.
  • Subramaniam, Venkat (2008). Programación Groovy: Productividad dinámica para el desarrollador Java . Pragmatic Bookshelf. ISBN 978-1-934356-09-8.
  • Sitio web oficialEdita esto en Wikidata