At BreizhCamp 2017, Guillaume Laforge and Cédric Champeau presented about the latest developments about Apache Groovy: in the current 2.4 branch, in the new 2.5 alpha, and what's coming in 2.6 and beyond.
PMC Chair of Apache Groovy Developer Advocate Google Cloud Platform Cédric Champeau @cedricchampeau PMC Member of Apache Groovy Principal Engineer Gradle Inc.
true) class Person { String name int age } assert new Person('Guillaume', 39).toString() == 'Person(name:Guillaume, age:39)' includeNames from @ToString
annotation collection will always be inserted. PREFER_COLLECTOR Annotations from the collector will be added and any existing annotations with the same name will be removed. PREFER_EXPLICIT Annotations from the collector will be ignored if any existing annotations with the same name are found. PREFER_EXPLICIT_MERGED Annotations from the collector will be ignored if any existing annotations with the same name are found but any new parameters on the collector annotation will be added to existing annotations. PREFER_COLLECTOR_MERGED Annotations from the collector will be added and any existing annotations with the same name will be removed but any new parameters found within existing annotations will be merged into the added annotation.
first = first?.toLowerCase() }) class Person { String first } def p = new Person('Jack') assert p.first == 'jack' import groovy.transform.TupleConstructor import static groovy.test.GroovyAssert.shouldFail @TupleConstructor(pre = { assert first }) class Person { String first } def p = new Person('Jack') shouldFail { def unknown = new Person() }
= 'sirName') class Person { String firstName String surName } new Person(firstName: "John", surName: "Doe").clone() Error during @AutoClone processing: 'excludes' property 'sirName' does not exist.
class Person { String name } @Immutable @TupleConstructor(includeSuperProperties = true) @EqualsAndHashCode(callSuper = true) @ToString(includeNames = true, includeSuperProperties = true) class Athlete extends Person { String sport }
{ String name Optional<String> address } def p = new Person('Joe', Optional.of('Home')) assert p.toString() == 'Person(Joe, Optional[Home])' assert p.address.get() == 'Home' @Immutable class Person { String name Optional<Date> birth } Fails compilation, as Date is mutable
Writer { } @AutoImplement(exception = UnsupportedOperationException, message = 'Not supported by MyIterator') class MyIterator implements Iterator<String> { } @AutoImplement(code = { throw new UnsupportedOperationException( 'Should never be called but was called on ' + new Date()) }) class EmptyIterator implements Iterator<String> { boolean hasNext() { false } }
@EqualsAndHashCode @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement class Person { String name int age } def jaxbContext = JAXBContext.newInstance(Person) def p = new Person(name: 'Marion', age: 9) def xml = jaxbContext.marshal(p) assert jaxbContext.unmarshal(xml, Person) == p
@EqualsAndHashCode @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement class Person { String name int age } def jaxbContext = JAXBContext.newInstance(Person) def p = new Person(name: 'Marion', age: 9) def xml = jaxbContext.marshal(p) assert jaxbContext.unmarshal(xml, Person) == p No need for createMarshaller()
age = 39 return it }.toString() == 'Person(Guillaume, 39)' assert new Person().tap { name = 'Guillaume' age = 39 }.toString() == 'Person(Guillaume, 39)' @Canonical class Person { String name int age }
String title int age String password Date dob URL favoriteUrl } Person person = new Person(name: 'John', title: null, age: 21, password: 'secret', dob: Date.parse('yyyy-MM-dd', '1984-12-15'), favoriteUrl: new URL('http://groovy-lang.org/')) def generator = new JsonGenerator.Options() .excludeNulls() .dateFormat('yyyy@MM') .excludeFieldsByName('age', 'password') .excludeFieldsByType(URL) .build() assert generator.toJson(person) == '{"dob":"1984@12","name":"John"}'
new File('./NOTICE') def output = new File('/tmp/zipped.zip') // Java-style try ( FileInputStream fin = new FileInputStream(input); GZIPOutputStream out = new GZIPOutputStream(new FileOutputStream(output)) ) { byte[] buffer = new byte[4096] int nread = 0 while ((nread = fin.read(buffer)) != -1) { out.write(buffer, 0, nread) } }
new File('./NOTICE') def output = new File('/tmp/zipped.zip') // Groovy-style :-) try ( fin = new FileInputStream(input) out = new GZIPOutputStream(new FileOutputStream(output)) ) { out << fin }
String name int age } def p = new Person(name: 'Érine') p.with { name = name ?: 'unknown' age = age ?: 4 } assert p.toString() == 'Person(Érine, 4)' p.with { name ?= 'unknown' age ?= 4 }