| Groovy 2.3 is the new major release of Groovy, featuring |
| official *support for running Groovy on JDK 8*, *traits*, new and improved |
| AST transformations like `@TailRecursive`, `@Builder` and `@Sortable`, a |
| new _NIO2 module_ with `Path` support, *lightening fast JSON* parsing and |
| building,*closure parameter type inference*, a new *markup template engine*, |
| Groovysh and GroovyConsole ease of use improvements, a |
| new `GroovyAssert` test utility, more `@BaseScript` class capabilities, |
| and more. |
| |
| [[Groovy2.3releasenotes-OfficialsupportforrunningGroovyonJDK8]] |
| == Official support for running Groovy on JDK 8 |
| |
| This is the first version of Groovy to be officially compatible with JDK |
| 8. |
| |
| JDK 8 and its interface default methods introduced some |
| incompatibilities with a few methods of the Groovy Development Kit, so |
| we had to adapt to the situation, introducing minor breaking changes for |
| the affected methods and their outcome. |
| |
| Note that we’re not planning to backport the changes to older versions |
| of Groovy, so if you want to run Groovy on JDK 8, you’ll have to upgrade |
| to the shiniest version of Groovy! |
| |
| Groovy 2.3 doesn’t support the new syntax constructs offered by Java 8 |
| (such as lambdas, method references, default methods in interfaces, |
| etc), but you can very well already *use the new APIs offered by JDK |
| 8*, and even *use Groovy closures in lieu of Java 8 lambdas*. |
| |
| For reference, here are a couple of examples which use Java 8 streams, |
| for iterating over a stream of ints, or over the lines of a file: |
| |
| [source,groovy] |
| ---- |
| IntStream.range(1, 100).forEach { println it } |
| |
| Files.lines(Paths.get('README.adoc')) |
| .map { it.toUpperCase() } |
| .forEach { println it } |
| ---- |
| |
| |
| In particular, in the two statements above, notice that we replaced Java |
| 8 lambdas with Groovy closures, as Groovy provides a closure coercion |
| mechanism which transforms a Groovy closure into a functional interface |
| — unlike Java, Groovy also provides that coercion mechanism for abstract |
| classes containing a single abstract method. |
| |
| In future versions of Groovy, certain Java 8 syntax constructs, or |
| particular Groovy methods decorating JDK 8 APIs might be added. |
| |
| [[Groovy2.3releasenotes-Traits]] |
| == Traits |
| |
| A major highlight for Groovy 2.3 is the introduction of the *concept of traits*. |
| |
| link:{DOCS_BASEURL}/html/documentation/core-traits.html[Traits] |
| are reusable components of behavior that your classes can implement, and |
| are an additional Object-Oriented concept alongside classes and |
| interfaces. |
| |
| Below, we create a trait with a concrete method `fly()` which returns a |
| `String`. |
| |
| [source,groovy] |
| ---- |
| trait FlyingAbility { |
| String fly() { "I'm flying!" } |
| } |
| ---- |
| |
| Then we create a class, `Bird`, that implements that trait, and |
| instantiate it: |
| |
| [source,groovy] |
| ---- |
| class Bird implements FlyingAbility {} |
| def b = new Bird() |
| ---- |
| |
| We can check that the Bird instance does have the new `fly()` method |
| mixed-in: |
| |
| [source,groovy] |
| ---- |
| assert b.fly() == "I'm flying!" |
| ---- |
| |
| Groovy traits are stateful (unlike Java 8 interface default methods). |
| A trait can have Groovy properties like plain classes: |
| |
| [source,groovy] |
| ---- |
| trait Named { |
| String name |
| } |
| ---- |
| |
| This time, the `Bird` class implements that `Named` trait: |
| |
| [source,groovy] |
| ---- |
| class Bird implements Named {} |
| ---- |
| |
| We can instantiate the Bird with the named-argument constructor shortcut |
| provided by Groovy: |
| |
| [source,groovy] |
| ---- |
| def b = new Bird(name: 'Colibri') |
| ---- |
| |
| We assert that the instantiated Bird does have the name property added |
| to it: |
| |
| [source,groovy] |
| ---- |
| assert b.name == 'Colibri' |
| ---- |
| |
| They allow the composition of behavior without going into the "diamond |
| inheritance" problem allowing you to decide which behavior prevails |
| upon conflict, either by convention (last trait declared wins) or by |
| explicitly overriding the conflicting method: |
| |
| [source,groovy] |
| ---- |
| trait KiteSurfer { String surf() { 'kite' } } |
| |
| trait WebSurfer { String surf() { 'web' } } |
| |
| class Person { String name } |
| |
| class Hipster extends Person |
| implements KiteSurfer, WebSurfer {} |
| |
| def h = new Hipster() |
| assert h.surf() == 'web' |
| ---- |
| |
| Above, the `surf()` method from `WebSurfer` wins, as it’s the last declared |
| trait, but you can reverse the trait implementation order if you want |
| kite to be returned. If you want to be more explicit, your `Hipster` class |
| can override the `surf()` method itself, and call `WebSurfer.super.foo()` or |
| `KiteSurfer.super.foo()` or do something entirely different. |
| |
| Traits support inheritance, thus a trait can extend another trait or |
| implement an interface, as shown below: |
| |
| [source,groovy] |
| ---- |
| trait Named { String name } |
| |
| trait FlyingAbility extends Named { |
| String fly() { "I'm a flying ${name}!" } |
| } |
| |
| class Bird implements FlyingAbility {} |
| def b = new Bird(name: 'Colibri') |
| |
| assert b.name == 'Colibri' |
| assert b.fly() == "I'm a flying Colibri!" |
| ---- |
| |
| Traits are compatible with static type checking and compilation, as well |
| as our usual dynamic behavior. Trait mixed-in methods are actually |
| "real" methods (ie. visible from Java as well) and not just dynamic. |
| Note however, that not all existing AST transformations are compatible |
| with traits. |
| |
| Traits can also be implemented at runtime with `as` or with |
| `withTraits` if you just want to add behavior of a trait to an object |
| you’re instantiating, without having to create an intermediary |
| artificial class just for that purpose (also called per-instance |
| traits): |
| |
| [source,groovy] |
| ---- |
| trait Named { String name } |
| |
| trait Quacks { |
| String quack() { 'Quack!' } |
| } |
| |
| class Animal {} |
| |
| def na = new Animal().withTraits Named, Quacks |
| na.name = 'Daffy' |
| assert na.name == 'Daffy' |
| assert na.quack() == 'Quack!' |
| ---- |
| |
| You can find more information on traits in the |
| exhaustive link:{DOCS_BASEURL}/html/documentation/core-traits.html[traits documentation]. |
| |
| [[Groovy2.3releasenotes-NewandupdatedASTtransformations]] |
| == New and updated AST transformations |
| |
| [[Groovy2.3releasenotes-Newtransformations]] |
| === New transformations |
| |
| [[Groovy2.3releasenotes-TailRecursive]] |
| ==== @TailRecursive |
| |
| `@TailRecursive` on methods adds tail recursion to methods which are |
| recursive and call themselves at the last operation of the method body, |
| which helps avoid blowing up the stack with the recursive calls |
| (link:https://issues.apache.org/jira/browse/GROOVY-6570[GROOVY-6570]). |
| |
| Here’s a slightly rewritten factorial implementation, that is friendly |
| to tail-call transformation: |
| |
| [source,groovy] |
| ---- |
| import groovy.transform.TailRecursive |
| |
| @TailRecursive |
| def fact(BigInteger n, accu = 1G) { |
| if (n < 2) accu |
| else fact(n - 1, n * accu) |
| } |
| |
| assert fact(1000) > 10e2566 |
| ---- |
| |
| [[Groovy2.3releasenotes-Builder]] |
| ==== @Builder |
| |
| Recent Java APIs have adopted the builder pattern (not to be confused |
| with Groovy’s builders) to instantiate complex objects, without |
| requiring to multiply the number of constructors with variants taking |
| various combination of parameters. Groovy 2.3 introduces a `@Builder` |
| transformation to automate the creation of such builder APIs |
| (link:https://issues.apache.org/jira/browse/GROOVY-6484[GROOVY-6484]). |
| |
| The `@Builder` transformation offers different implementation strategies |
| that you can choose from: |
| |
| * a simple strategy for creating chained setters |
| * an external strategy where you annotate an explicit builder class |
| while leaving some buildee class being built untouched |
| * a default strategy which creates a nested helper class for instance |
| creation |
| * and an initializer strategy which creates a nested helper class for |
| instance creation which when used with `@CompileStatic` allows type-safe |
| object creation |
| |
| Here’s an example with the default strategy: |
| |
| [source,groovy] |
| ----- |
| import groovy.transform.builder.Builder |
| |
| @Builder |
| class Person { |
| String firstName |
| String lastName |
| int age |
| } |
| |
| def person = Person.builder() |
| .firstName("Robert") |
| .lastName("Lewandowski") |
| .age(21) |
| .build() |
| |
| assert person.firstName == "Robert" |
| assert person.lastName == "Lewandowski" |
| assert person.age == 21 |
| ----- |
| |
| You can have a look at |
| the link:{DOCS_BASEURL}/html/documentation/core-metaprogramming.html#xform-Builder[@Builder documentation] |
| for the other builder variants. |
| |
| [[Groovy2.3releasenotes-Sortable]] |
| ==== @Sortable |
| |
| `@Sortable` on classes implements comparison methods for you (through |
| implementing the `Comparable` interface), according to the declaration |
| order of your properties |
| (link:https://issues.apache.org/jira/browse/GROOVY-6649[GROOVY-6649]). |
| |
| For the following `Person` class, its instances will be sorted by last |
| name, then by first name, and by age, in that order: |
| |
| [source,groovy] |
| ---- |
| import groovy.transform.* |
| |
| @Sortable |
| @Canonical |
| class Person { |
| String last |
| String first |
| int age |
| } |
| |
| def folks = [ |
| new Person('Simpson', 'Bart', 12), |
| new Person('Simpson', 'Homer', 40), |
| new Person('Kent', 'Clark', 36) |
| ] |
| |
| assert folks.sort()*.first == ['Clark', 'Bart', 'Homer'] |
| ---- |
| |
| Additionally, you can define included / excluded fields, access |
| individual field comparators with methods like `comparatorByFirst()`. |
| |
| More details on |
| the {DOCS_BASEURL}/html/documentation/core-metaprogramming.html#xform-Sortable[@Sortable documentation] page. |
| |
| [[Groovy2.3releasenotes-SourceURI]] |
| ==== @SourceURI |
| |
| With `@SourceURI`, you can annotate a `java.net.URI` or even a |
| `java.lang.String` script variable or class field so that the variable or |
| field are injected the URI of the Groovy file. |
| |
| If you evaluate or compile a Groovy script or class, the variable or |
| field will contain a data URI, for example, for the following example: |
| |
| [source,groovy] |
| ---- |
| import groovy.transform.SourceURI |
| |
| @SourceURI String src |
| |
| println src |
| ---- |
| |
| The `src` variable will contain the following data URI: |
| |
| ---- |
| data:,import%20groovy.transform.SourceURI%0A%0A@SourceURI%20String%20src%0A%0Aprintln%20src |
| ---- |
| |
| If you save the script in a file called `sourceuri.groovy` in `/tmp`, and |
| run that script with the `groovy` command, you’ll see an absolute `File` |
| path printed: |
| |
| ---- |
| file:/tmp/sourceuri.groovy |
| ---- |
| |
| As we mentioned above, you can also write `@SourceURI URI src`, if you want |
| to have a `URI` instead of a `String`. |
| |
| [[Groovy2.3releasenotes-Updatedtransformations]] |
| === Updated transformations |
| |
| [[Groovy2.3releasenotes-Delegateimprovements]] |
| ==== @Delegate improvements |
| |
| `@Delegate` supports `includeTypes` and `excludeTypes` attributes to give you |
| fine-grained control over which methods to include or exclude from |
| delegation. Rather than just matching on name, this option matches on |
| the name and parameter types expressed in an interface type |
| (link:https://issues.apache.org/jira/browse/GROOVY-6329[GROOVY-6329]). |
| |
| [[Groovy2.3releasenotes-BaseScriptclassimprovements]] |
| ==== @BaseScript class improvements |
| |
| {DOCS_BASEURL}/html/gapi/groovy/transform/BaseScript.html[@BaseScript] |
| is a fairly recent addition in Groovy, and it allowed to annotate a |
| variable in your script to instruct the compiler to use a particular |
| base script class for this script. Now we have another notation which is |
| nicer as you can annotate an import or a package |
| (link:https://issues.apache.org/jira/browse/GROOVY-6592[GROOVY-6592]) to indicate |
| that base script class: |
| |
| [source,groovy] |
| ---- |
| @BaseScript(MyScript) |
| import groovy.transform.BaseScript |
| ---- |
| |
| Additionally, base script classes can now use any abstract method for |
| the script body. This means that you can implement the `run()` method to |
| implement specific behavior like setup and tear down in tests |
| (link:https://issues.apache.org/jira/browse/GROOVY-6585[GROOVY-6585] |
| and link:https://issues.apache.org/jira/browse/GROOVY-6615[GROOVY-6615]). |
| |
| Given the following custom base script class, where we implement the |
| default `run()` method, we also create a new abstract method called |
| `internalRun()`: |
| |
| [source,groovy] |
| ---- |
| abstract class CustomBase extends Script { |
| def run() { |
| before() |
| internalRun() |
| after() |
| } |
| |
| abstract internalRun() |
| |
| def before() { println 'before' } |
| def after() { println 'after' } |
| } |
| ---- |
| |
| We can then have the script below transparently implement the |
| `internalRun()` method instead of the usual `run()` one: |
| |
| [source,groovy] |
| ---- |
| import groovy.transform.BaseScript |
| @BaseScript CustomBase script |
| |
| println 'Hello' |
| ---- |
| |
| [[Groovy2.3releasenotes-NewNIOmoduleforJava7]] |
| == New NIO module for Java 7+ |
| |
| On JDK 7 and beyond, you can benefit from the same methods as the ones |
| of File but for the new NIO2 class `Path`. |
| |
| See link:https://issues.apache.org/jira/browse/GROOVY-6377[GROOVY-6377] and |
| the link:https://github.com/groovy/groovy-core/pull/260/files[pull request] |
| for some further hints of the new methods. |
| |
| You’ll find familiar methods of the Groovy GDK on `File` also available on |
| `Path` like these ones: |
| |
| [source,groovy] |
| ---- |
| path.withReader { Reader r -> ... } |
| path.eachLine { String line -> ... } |
| path.eachFileRecurse { Path p -> ... } |
| path << 'some content' |
| path << bytes |
| path.readLines() |
| ---- |
| |
| [[Groovy2.3releasenotes-Performanceimprovements]] |
| == Performance improvements |
| |
| [[Groovy2.3releasenotes-Miscellanousimprovements]] |
| === Miscellanous improvements |
| |
| Various minor *performance improvements across the board*, for static |
| compilation, the `invokedynamic` backend, as well as "normal" |
| dynamic Groovy, have been worked on. |
| |
| [[Groovy2.3releasenotes-DrasticJSONparsingandserializationperformanceimprovements]] |
| === Drastic JSON parsing and serialization performance improvements |
| |
| Groovy JSON support has been refactored and tailored towards |
| performance, making Groovy 2.3’s JSON support usually |
| *faster than all the JSON libraries* available in the Java ecosystem. |
| |
| Rick Hightower and Andrey Bleschestov covered the performance gains, |
| both in parsing and seralization, in |
| a link:http://rick-hightower.blogspot.fr/2014/04/groovy-and-boon-provide-fastest-json.html[benchmarks on Rick’s blog] |
| and on link:https://github.com/bura/json-benchmarks[Andrey’s JSON benchmark project on Github]. |
| The results are impressive, as the *parsing is generally roughly 2x to 4x faster* with Groovy’s new |
| parsers compared to existing libraries, and *~21x faster than pre-Groovy 2.3 parsing*. |
| On the serialization front, Groovy’s |
| new *serialization is also ~17x faster than before*, and at the same |
| level as competing libraries. |
| |
| [[Groovy2.3releasenotes-JSONslurperandbuilderenhancements]] |
| == JSON slurper and builder enhancements |
| |
| Beside the performance improvements of the JSON module, other updates |
| have taken place. |
| |
| With link:{DOCS_BASEURL}/html/gapi/groovy/json/JsonSlurper.html[JsonSlurper], |
| you’ll be able to set |
| different link:{DOCS_BASEURL}/html/gapi/groovy/json/JsonParserType.html[parser types] |
| depending on the kind of input you wish to parse, particularly if |
| you know the size of the payload you expect to parse, or whether you |
| want a more tolerant parser which accepts elements like comments which |
| are not normally supported by the JSON specification. |
| |
| Here’s an example showing how to parse a non-conformant JSON payload: |
| |
| [source,groovy] |
| ---- |
| import groovy.json.* |
| import static groovy.json.JsonParserType.* |
| |
| def parser = new JsonSlurper().setType(LAX) |
| |
| def conf = parser.parseText ''' |
| // configuration file |
| { |
| // no quote for key, single quoted value |
| environment: 'production' |
| # pound-style comment |
| 'server': 5 |
| } |
| ''' |
| |
| assert conf.environment == 'production' |
| assert conf.server == 5 |
| ---- |
| |
| [[Groovy2.3releasenotes-Closureparametertypeinference]] |
| == Closure parameter type inference |
| |
| We closed a gap which forced you to type your closure parameters to get |
| correct type inference with static type checking or static compilation |
| enabled. In situations like the following, you would have to explicitly |
| give the type of the parameter, but it’s no longer required: |
| |
| [source,groovy] |
| ---- |
| ['a','b'].each { it.toUpperCase() } |
| ---- |
| |
| In the signature of your methods taking closures as arguments, you’ll |
| also be able to annotate the closure parameter |
| with link:{DOCS_BASEURL}/html/gapi/groovy/transform/stc/ClosureParams.html[@ClosureParams] |
| to give additional hints to the type checker to infer the type of the |
| parameters passed to your closure. |
| |
| You can also find more about this in Cédric’s blog post |
| on link:http://melix.github.io/blog/2014/01/closure_param_inference.html[closure parameter type inference]. |
| |
| [[Groovy2.3releasenotes-Newmarkuptemplateengine]] |
| == New markup template engine |
| |
| Groovy now has an additional template engine, in the form of the Markup |
| template engine, which gives you a very fast template engine (thanks to |
| static compilation), based on the familiar Markup builder approach and |
| notation, but also offering formatting options (indentation, escaping), |
| internationalization, includes, as well as proposing type checked |
| templates and models. |
| |
| More details about the |
| new link:{DOCS_BASEURL}/html/documentation/markup-template-engine.html[Markup template engine] |
| in the documentation, as well as in Cédric’s link:http://melix.github.io/blog/[blog], if you want to learn more |
| about the "behind the scenes" stories! |
| |
| To illustrate the basic usage, consider you have the following template: |
| |
| [source,groovy] |
| ---- |
| def tpl = ''' |
| cars { |
| cars.each { |
| car(make: it.make, name: it.name) |
| } |
| } |
| ''' |
| ---- |
| |
| And have the following model: |
| |
| [source,groovy] |
| ---- |
| model = [cars: [ |
| new Car(make: 'Peugeot', name: '508'), |
| new Car(make: 'Toyota', name: 'Prius') |
| ]] |
| ---- |
| |
| You would generate the following XML (or HTML) output: |
| |
| [source,xml] |
| ---- |
| <cars> |
| <car make='Peugeot' name='508'/> |
| <car make='Toyota' name='Prius'/> |
| </cars> |
| ---- |
| |
| By doing the following: |
| |
| [source,groovy] |
| ---- |
| import groovy.text.markup.* |
| |
| def config = new TemplateConfiguration() |
| def engine = new MarkupTemplateEngine(config) |
| def tmpl = engine.createTemplate(tpl) |
| System.out << tmpl.make(model) |
| ---- |
| |
| You have useful methods available to your templates, like for including |
| other templates: |
| |
| [source,groovy] |
| ---- |
| // include another template |
| include template: 'foo.tpl' |
| |
| // include raw content |
| include unescaped: 'raw.txt' |
| |
| // escape & include |
| include escaped: 'to_escape.txt' |
| ---- |
| |
| And if you want to have your model be type checked, you can either |
| define the model types inside the template like so: |
| |
| [source,groovy] |
| ---- |
| modelTypes = { |
| List<Car> cars |
| } |
| ---- |
| |
| Or by using the dedicated template creation method: |
| |
| [source,groovy] |
| ---- |
| def modelTypes = [cars: "List<Car>"] |
| |
| def tmpl = engine.createTypeCheckedModelTemplate(tpl, modelTypes) |
| ---- |
| |
| Note that this template engine is super fast as it’s statically |
| compiled. |
| |
| [[Groovy2.3releasenotes-JUnit4GroovyAssertclass]] |
| == JUnit 4 GroovyAssert class |
| |
| The |
| venerable link:{DOCS_BASEURL}/html/gapi/groovy/util/GroovyTestCase.html[GroovyTestCase] |
| (JUnit 3 based approach) has often been used as a base class for your |
| test classes — unless you’ve been using |
| the link:http://www.spockframework.org/[Spock testing framework], of course. |
| One of the drawback of this class is that your test classes can’t extend |
| your own classes, but must derive from `GroovyTestCase` to benefit from |
| the additional assertion methods. |
| |
| In earlier versions of Groovy we introduced the JUnit |
| 4-friendly link:{DOCS_BASEURL}/html/gapi/groovy/util/GroovyAssert.html[GroovyAssert], |
| which is a convenient class offering the usual assertion methods of |
| `GroovyTestCase`, but in the form of static methods that you can static |
| import in your test class. In Groovy 2.3 we’ve enriched `GroovyAssert` |
| with additional features. There should be no reason to move on from |
| JUnit 3 if you haven’t already done so. We didn’t include all of the |
| myriad of `assertEquals` methods from `GroovyTestCase` as they are typically |
| less useful than Groovy’s built-in power assert, but it provides some |
| handy `shouldFail()` and `assertScript()` methods |
| (link:https://issues.apache.org/jira/browse/GROOVY-6588[GROOVY-6588]). |
| |
| For instance, if you want to leverage the `shouldFail(String)` and |
| `assertScript(String)` methods, you can do so as follows: |
| |
| [source,groovy] |
| ---- |
| import static groovy.test.GroovyAssert.shouldFail |
| |
| |
| import org.junit.Test |
| |
| class AssertTest { |
| @Test void checkBadAddition() { |
| shouldFail ''' |
| groovy.test.GroovyAssert.assertScript 'assert 1 + 1 == 3' |
| ''' |
| } |
| } |
| ---- |
| |
| [[Groovy2.3releasenotes-ConfigSlurper]] |
| == ConfigSlurper |
| |
| ConfigSlurper has previously supported a single "environments" |
| non-configurational conditional block, but you couldn’t define your own. |
| With Groovy 2.3 you can also create your own such blocks. For instance |
| if you wanted to support "flavors" like OS variants |
| (link:https://issues.apache.org/jira/browse/GROOVY-6383[GROOVY-6383]). |
| |
| Concretely, instead of the familiar environments / production blocks in |
| Grails, let’s register a flavors / prod pair: |
| |
| [source,groovy] |
| ---- |
| def conf = ''' |
| a.b.c = 1 |
| flavors { |
| prod { |
| a.b.c = 2 |
| } |
| } |
| ''' |
| |
| def slurper = new ConfigSlurper('prod') |
| slurper.registerConditionalBlock('flavors', 'prod') |
| |
| def config = slurper.parse(conf) |
| |
| assert config.a.b.c == 2 |
| ---- |
| |
| In addition, the `isSet()` / `hasSet()` combo methods |
| (link:https://issues.apache.org/jira/browse/GROOVY-4639[GROOVY-4639]) have been |
| added so you can double check if a given node of your configuration has |
| been defined. Before, whether the node wasn’t defined or containing |
| `null`, you couldn’t differentiate either case easily. |
| |
| [[Groovy2.3releasenotes-Toolsenhancements]] |
| == Tools enhancements |
| |
| [[Groovy2.3releasenotes-Groovysh]] |
| === Groovysh |
| |
| Along with a slightly reduced startup time, Groovysh has seen new |
| improvements in its code-completion capabilities: |
| |
| * completion for keywords |
| (link:https://issues.apache.org/jira/browse/GROOVY-6399[GROOVY-6399]) |
| * completion for properties |
| (link:https://issues.apache.org/jira/browse/GROOVY-6395[GROOVY-6395]) |
| |
| Commands are now prefixed with ``:'' |
| (link:https://issues.apache.org/jira/browse/GROOVY-6397). |
| |
| [[Groovy2.3releasenotes-GroovyConsole]] |
| === GroovyConsole |
| |
| It is now possible to configure the font used by the console |
| (link:https://issues.apache.org/jira/browse/GROOVY-6303[GROOVY-6303], although |
| without a UI dialog yet), and also to be able to run a selected snippet |
| of code reusing the imports defined in your script making it easier to |
| just run quick snippets of your script. The ability to comment or |
| uncomment selected code by pressing `Ctrl +` was added |
| with link:https://issues.apache.org/jira/browse/GROOVY-6459[GROOVY-6459]. |
| |
| |
| [[Groovy2.3releasenotes-Documentation]] |
| == Documentation |
| |
| [[Groovy2.3releasenotes-Newdocumentation]] |
| === New documentation |
| |
| We are still working on the |
| brand link:{DOCS_BASEURL}/html/documentation/[new documentation] for Groovy |
| (in Asciidoc(tor) format), so you can already |
| have a glimpse at what’s already covered or not. |
| |
| We’re looking forward to your help for fleshing out the various TBD ("To |
| Be Done") sections of the documentation, as it’s a gigantic task to |
| re-document each and every aspect of the language and its libraries! So |
| please shout if you want to *contribute to the new documentation*! All |
| help is warmly welcome! |
| |
| [[Groovy2.3releasenotes-RefreshedGroovyDocdocumentationstyle]] |
| === Refreshed GroovyDoc documentation style |
| |
| GroovyDoc has been updated with a new fresh and modern skin that will be |
| part of the future visual identity of the Groovy website. Those style |
| updates are also available by default for your own usage of GroovyDoc, |
| making your own documentation nicer on the eye. |
| |
| You can have a look at |
| the link:http://docs.groovy-lang.org/2.3.0/html/gapi/[GroovyDoc |
| documentation for Groovy 2.3.0]. |
| |
| [[Groovy2.3releasenotes-RefreshedGroovyGDKdocumentationstyle]] |
| === Refreshed Groovy GDK documentation style |
| |
| We also took the opportunity to apply the same stylesheet to our |
| `DocGenerator` tool which is responsible for the generation of the GDK |
| documentation, showing the methods the Groovy library adds on top of the |
| JDK classes. |
| |
| Please also have a look at the |
| new link:{DOCS_BASEURL}/html/groovy-jdk/[restyled GDK documentation]. |
| |
| [[Groovy2.3releasenotes-Dependencyupgrades]] |
| == Dependency upgrades |
| |
| The following dependencies have been upgraded: |
| |
| * *GPars 1.2* for all your concurrency, asynchronous or parallelism needs: |
| ** improvements in the dataflow area, such as lazy tasks and easy |
| fork-and-join on Promises |
| ** actors and dataflow operators now use the Groovy `@DelegatesTo` |
| annotation to allow for statically compiled bodies |
| ** GPars timers and thread-locals have been made more friendly towards |
| managed environments and the GParsConfig class now allows GPars to be |
| completely shutdown |
| * *Gradle 1.10* for building Groovy |
| * *ASM 5.0.1* library for generating our bytecode (also needed for our JDK 8 support) |
| * *JLine 2.11* and *JANSI 1.11* library for Groovysh |
| * *Ant 1.9.3* for the Ant builder |
| * *TestNG 6.8.8* for the TestNG module |
| |
| [[Groovy2.3releasenotes-Breakingchanges]] |
| == Breaking changes |
| |
| Groovy 2.3.0 introduces a limited list of breaking changes. |
| |
| First of all,*Groovy 2.3.0 now requires JDK 6* as its minimal JDK |
| requirement. Some parts of Groovy 2.3.0 might still run under JDK 5 but |
| no testing has been done on that platform and some parts are known not |
| to work. We encourage everyone to move to at least JDK 6. |
| |
| In Groovy 2.3.0, we *reworked our implementation of generics handling*. |
| Although we don’t know of any particular breakage so far, the static |
| type checker might report new errors as it can be stricter than before. |
| If ever you encounter such new errors in this area, please report them |
| as soon as you encounter them. |
| |
| With the introduction of "traits" in Groovy 2.3, the `trait` keyword |
| is an addition to the list of keyword of the languages, with the |
| consequence that *variables or fields that would use `trait` as name |
| with yield a compilation error*. So you would have to change the name of |
| your variable and recompile your code. |
| |
| A few updates have been made to the *XML support around whitespace |
| handling, and text node handling*: |
| |
| * https://issues.apache.org/jira/browse/GROOVY-6685[GROOVY-6685] |
| * https://issues.apache.org/jira/browse/GROOVY-6683[GROOVY-6683] |
| * https://issues.apache.org/jira/browse/GROOVY-6682[GROOVY-6682] |
| * https://issues.apache.org/jira/browse/GROOVY-6678[GROOVY-6678] |
| * https://issues.apache.org/jira/browse/GROOVY-6621[GROOVY-6621] |
| |
| With the new default methods on interfaces in JDK 8, there was |
| particularly one, |
| a link:https://issues.apache.org/jira/browse/GROOVY-6465[List#sort(Comparable) method], which *conflicted with one of the GDK*, |
| so we had to remove ours to stay compliant with JDK 8. |
| |
| We fixed a link:https://issues.apache.org/jira/browse/GROOVY-6456[race condition in AbstractHttpServler#applyResourceNameMatcher] |
| which incurred a small change in behavior. This feature is seldomly used and doesn’t seem to |
| have impacted users of the Groovy servlet machinery so far. |
| |
| You can look at the list of |
| the link:https://issues.apache.org/jira/browse/GROOVY-6685?jql=project%20%3D%20GROOVY%20AND%20fixVersion%20in%20%28%222.3.0-rc-3%22%2C%20%222.3.0-beta-1%22%2C%20%222.3.0-beta-2%22%2C%20%222.3.0-rc-1%22%2C%20%222.3.0-rc-2%22%29%20AND%20labels%20%3D%20breaking%20AND%20status%20in%20%28Resolved%2C%20Closed%29[breaking changes from our JIRA] |
| issue tracker. |
| |