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
Person
Java class. Try to run the tests:./gradlew test
-
❏ Let’s turn the
Person
Java class into a Groovy class. Just move it fromsrc/main/java
tosrc/main/groovy
and change the filename extension from.java
to.groovy
mv 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
PersonService
into 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
PersonService
Groovy class truly Groovy.
Now we are going to convert our tests over to the Groovy side.
-
❏ Let’s just move the
PersonTest
Java 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
PersonServiceTest
Java 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(
GroovyAssert
util).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
Person
in 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
hashCode
andequals
implementation are noisy and easily forgotten to be adjusted. Let’s play with some compile time meta-programming using annotations from thegroovy.transform
package. -
❏ 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
Person
Groovy class with atoJson
method 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
addAll
method 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
@DelegatesTo
annotation might help.