Workshop for Groovy programming language with a special focus on Java™ developers.
This workshop uses Gradle as its build tool. Generally it is also possible to run Groovy via Maven (see Groovy docs on Maven integration) but Gradle's support for different source sets — e.g. one for Groovy and Java — is very useful for this workshop.
In this part we’ll try to convert a Plain Old Java Object (POJO) into a Plain Old Groovy Object (POGO) to find the most basic differences between Java and Groovy.
All answers you might be looking for can be found in the Differences with Java (and the Groovy Style Guide).
-
❏ Take a look at the project, especially at
PersonJava class. Try to run the tests:./gradlew test -
❏ Let’s turn the
PersonJava class into a Groovy class. Just move it fromsrc/main/javatosrc/main/groovyand change the filename extension from.javato.groovymv src/main/java/de/assertagile/workshop/groovy/Person.java \ src/main/groovy/de/assertagile/workshop/groovy/Person.groovy
Run the tests again, understand & fix the error. You might want to read the Behaviour of
==again. -
❏ Keeping the Differences with Java in mind, make the link:src/main/groovy/de/assertagile/workshop/groovy/Person.groovy as Groovy as you can. Run the tests after each change.
Hint: my solution has only 50 lines of code (keeping white space as is)
NoteThere is a IntelliJ action (Ctrl+Shift+A) called "cleanup code".
-
❏ Now let’s move something with more logic over. Turn
PersonServiceinto a Groovy class.mv src/main/java/de/assertagile/workshop/groovy/PersonService.java \ src/main/groovy/de/assertagile/workshop/groovy/PersonService.groovy
Try to compile. Fix the compile errors and run the tests.
You might want to look at the section about Lambdas.
-
❏ Again try to make
PersonServiceGroovy class truly Groovy.
Now we are going to convert our tests over to the Groovy side.
-
❏ Let’s just move the
PersonTestJava test first as we did with the classes before:mv src/test/java/de/assertagile/workshop/groovy/PersonTest.java \ src/test/groovy/de/assertagile/workshop/groovy/PersonTest.groovy
Run it and make it Groovy.
-
❏ Now also move
PersonServiceTestJava test:mv src/test/java/de/assertagile/workshop/groovy/PersonServiceTest.java \ src/test/groovy/de/assertagile/workshop/groovy/PersonServiceTest.groovy
There will be a compile error. Maybe you can find a creative way to fix that without using a
\in the Groovy Style Guide. -
❏ The output of the assertion errors in our tests is quite useless. Let’s replace the assertions with Power Assertions and the http://groovy-lang.org/testing.html#_junit_4(
GroovyAssertutil).Actually the Power Assertions won’t help with the current failures. Try to break a test intentionally to see the "Power". E.g. remove one
Personin the second test’s assertion. -
❏ Try to fix the remaining tests. You might find the paragraph about Multi-methods pretty useful here.
-
❏ Make the test truly Groovy.
-
❏ Change the various service initializations to use the named parameters constructor.
In this part we add some more Groovy power to the existing classes and tests.
-
❏ That
hashCodeandequalsimplementation are noisy and easily forgotten to be adjusted. Let’s play with some compile time meta-programming using annotations from thegroovy.transformpackage. -
❏ The email address should be read-only, too. See if you find an even better annotation now.
-
❏ Read Parsing and producing JSON and extend the
PersonGroovy class with atoJsonmethod which returns the properties in pretty printed JSON. Don’t forget to extendPersonTest(first). -
❏ …
This part is about how to create domain specific languages with Groovy.
This is less formal than you might think.
Files will still be .groovy files, you will still compile them the same way and your IDE will still understand, what you are doing.
-
❏ Replace the
addAllmethod with the<<<operator, so the following test succeeds:service <<< [TODD, ANDREA] assert service.persons == [TODD, ANDREA]
-
❏ Change the predicate variant of
findPersons, so the following test works:assert service.findPersons { name == "Todd Ler" } == TODD
Hint: The
@DelegatesToannotation might help.