Combining Groovy and Java
Tags: java, groovy, tutorial, code
Published: 2020-08-06 14:25:52

---
title: Combining Groovy and Java
published: true
description: Using Groovy scripts in a Java project tutorial
tags: ["java", "groovy", "tutorial", "code"]
cover_image: https://source.unsplash.com/WrYAR-yDwe8
---

Combining [Groovy](https://groovy-lang.org/) scripts in our [Java](https://www.java.com/)-based code, is easy with [Maven](https://maven.apache.org/).

You can check out the code for this tutorial in [Github][0].

Scenario: we're asked to produce a text message to send to customers registering to some call queue to inform them that we got their registration request.</br>
The message should include the customer name, queue number, and an informational greeting of some sort.

We have a couple of ways to accomplish that in *Java*.

First, we can use a basic method that takes the *name* and *queue number* as arguments:

```java
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" +
      "Ipsum voluptate laboris eiusmod sint ea do.", name, queueNum);
}

public String getMessage(final String name, final int queueNum) {
  return createMessage(name, queueNum);
}
```

Let's try this as a *BiFunction*:

```java
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" +
      "Ipsum voluptate laboris eiusmod sint ea do.", name, queueNum);

public String getMessage(final String name, final int queueNum) {
  return createMessage.apply(name, queueNum);
}
```

As we add parameters to the message, i.e. eta, while using any of the above approaches, our code will get less readable and more error-prone.

So let's do *function currying*; it will make it easier to add parameters later on. </br>
And it's fun invoking currying functions.<br/>
:grin:

```java
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" +
      "Ipsum voluptate laboris eiusmod sint ea do.", name, queueNum);

public String getMessage(final String name, final int queueNum) {
  return createMessage.apply(name).apply(queueNum);
}
```

Now, Let's give [Groovy](https://groovy-lang.org/) a try.</br>
We'll create *Groovy Script* called *create_message.groovy*:

```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.
Ipsum voluptate laboris eiusmod sint ea do."""
```

- The `def` statements allow us to bind arguments from the shell.
- The `"""` marks the text as a `GString`, which allows us to leverage string interpolation and implied line breaks.
- In *Groovy* last statement **is** the return statement.

Now let's invoke the script from our *Java* code:

```java
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();
  }
}
```

Adding an eta to the above approach is as simple as editing the text and binding another property. :relieved:

To get our script into our classpath with *Maven*, let's say this is our project layout:

```text
- project
  - src
    - main
      - *.java
    - scripts
      - create_message.groovy
    - test
      - *Test.java
```

First, we need to include the [groovy dependency](https://mvnrepository.com/artifact/org.codehaus.groovy/groovy).</br>
This will give access to *Groovy*'s API, i.e. the *GroovyShell* and *Binding* classes.

```xml
<dependencies>
    <dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy</artifactId>
        <version>3.0.5</version>
    </dependency>
</dependencies>
```

We'll add the following to our `build` section in our `pom.xml`,</br>
This will add everything from our `src/scripts` to our project.

```xml
<build>
    <resources>
      <resource>
        <directory>src/scripts</directory>
        <targetPath>scripts</targetPath>
      </resource>
    </resources>
</build>
```

That's it, have fun and stay groovy!

[0]: https://github.com/TomerFi/groovy-script-java-project-tutorial