Groovying with Java
If you haven't combined Groovy scripts with your Java
projects yet...
You're missing out...
It's super easy with Maven,
and it'll make your code more modular and elegant.
But most importantly,
you'll have some fun scripting and if nothing else,
you'll most certainly benefit from some of the grooviest features,
including the magic that is Groovy's GString!
😃
You can check out the code for this tutorial in Github.
The given environment
Let's say you have a service for connecting customers to representatives via some sort of messaging service.
When the customer first reaches out to the service,
he should be responded with a standard message that includes his name,
his queue number, and an informational greeting of some sort.
We have a couple of ways to accomplish that in Java.
Old-school: method invoking
First, we can use a basic method that takes the name and queue number as arguments:
private static String createMessage(final String name, final int queueNum) {
return String.format(
"Hello %s, you're number %d, please wait patiently, here is some info:\n" +
"Anim incididunt deserunt ex ad do aliquip.\n" +
"Ullamco est Lorem nisi magna duis esse laboris commodo eu.\n" +
"Anim laborum commodo sint est dolor veniam id non sint aliquip amet pariatur.\n" +
"Ex non incididunt duis aliqua qui quis eiusmod ex eiusmod irure nisi sint anim.\n" +
"Ipsum voluptate laboris eiusmod sint ea do.", name, queueNum);
}
public String getMessage(final String name, final int queueNum) {
return createMessage(name, queueNum);
}
New-school: bi-function applying
Well... It is 2020...
Let's write this as a BiFunction:
private static final BiFunction<String, Integer, String> createMessage =
(name, queueNum) -> String.format(
"Hello %s, you're number %d, please wait patiently, here is some info:\n" +
"Anim incididunt deserunt ex ad do aliquip.\n" +
"Ullamco est Lorem nisi magna duis esse laboris commodo eu.\n" +
"Anim laborum commodo sint est dolor veniam id non sint aliquip amet pariatur.\n" +
"Ex non incididunt duis aliqua qui quis eiusmod ex eiusmod irure nisi sint anim.\n" +
"Ipsum voluptate laboris eiusmod sint ea do.", name, queueNum);
public String getMessage(final String name, final int queueNum) {
return createMessage.apply(name, queueNum);
}
Even better: function currying
If we'll ever need to add a couple of more arguments to the mix,
let's say an eta...
We'll have to think out of the box here,
maybe use a POJO
as the argument or use javatupels.
Maybe create a TriFunction
interface...
There are numerous possibilities.
For instance, we can switch to function currying.
It will make it easier to add arguments later on,
and... well...
It's fun invoking currying functions, am I right? 😁
private static final Function<String, Function<Integer, String>> createMessage =
name -> queueNum -> String.format(
"Hello %s, you're number %d, please wait patiently, here is some info:\n" +
"Anim incididunt deserunt ex ad do aliquip.\n" +
"Ullamco est Lorem nisi magna duis esse laboris commodo eu.\n" +
"Anim laborum commodo sint est dolor veniam id non sint aliquip amet pariatur.\n" +
"Ex non incididunt duis aliqua qui quis eiusmod ex eiusmod irure nisi sint anim.\n" +
"Ipsum voluptate laboris eiusmod sint ea do.", name, queueNum);
public String getMessage(final String name, final int queueNum) {
return createMessage.apply(name).apply(queueNum);
}
Last but not least: groovy scripting
If you're like me,
and you just hate seeing big long constant strings in your code.
Then let's try this as a Groovy Script
with a script called create_message.groovy
:
def name = bindName
def queueNum = bindQueueNum
"""Hello ${name}, you're number ${queueNum}, please wait patiently, here is some info:
Anim incididunt deserunt ex ad do aliquip.
Ullamco est Lorem nisi magna duis esse laboris commodo eu.
Anim laborum commodo sint est dolor veniam id non sint aliquip amet pariatur.
Ex non incididunt duis aliqua qui quis eiusmod ex eiusmod irure nisi sint anim.
Ipsum voluptate laboris eiusmod sint ea do."""
Please note:
- The
def
statements allow us to bind arguments from the shell. - The
"""
marks the text as aGString
, which allows us, in this case to:- Easily incorporate the arguments with no
String.format
required. - Produce multi-line strings without worrying about line breaks and long lines.
- Easily incorporate the arguments with no
- What you might have noticed missing here, is the
return
statement. With Groovy the last statement is the return statement.
Now let's invoke the script with some intentionally boiler plated Java code:
public String getMessage(final String name, final int queueNum) {
try {
var shell = new GroovyShell();
var scriptFile = new File(shell.getClassLoader().getResource("scripts/create_message.groovy").getFile());
var script = shell.parse(scriptFile);
var binding = new Binding();
binding.setProperty("bindName", name);
binding.setProperty("bindQueueNum", queueNum);
script.setBinding(binding);
return script.run().toString();
} catch (IOException exc) {
return exc.getMessage();
}
}
💥
Can you see how easy it is to add arguments?
Just add them to the script, and add the binding to the invoking class.
No more "scratching your head" when it comes to concatenating long strings...
😌
The real conundrum here is,
How do we get the script in our class loader ❓
It's easy with Maven, let's say this is our project layout:
- project
- src
- main
- *.java
- scripts
- create_message.groovy
- test
- *Test.java
First, we need to include the groovy dependency.
(Note the version, which was the latest when this tutorial was written).
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>3.0.5</version>
</dependency>
</dependencies>
Now we have the appropriate Groovy API classes like GroovyShell and Binding in our class loader.
We now need to add the following to our build
section in our pom.xml
:
<build>
<resources>
<resource>
<directory>src/scripts</directory>
<targetPath>scripts</targetPath>
</resource>
</resources>
</build>
This will add everything from our src/scripts
folder to our class loader under the folder scripts
.
So we'll be able to find our script like so: scripts/create_message.groovy
.
That's it!
You can check out the code for this tutorial in Github.
👋 See you in the next tutorial 👋
Discussion (0)