1

I want to derive some project properties using a script at early phase of Maven build.

  • Is there a way to execute scripts in given phase of Maven compilation other than groovy-maven-plugin? It seems rather heavyweight for what I want to do.

  • Java since 8 seems to have JavaScript engine built in, is there a way to leverage that instead?

UPDATE

More details:

  • We want to set other properties derived from ${project.version} which are then used and their placeholders replaced in generated (re)sources. E.g., from ${project.version} value 10.5.2.97 we want derive shortVersion as 10.5, etc.

UPDATE 2

I have found nashorn-maven-plugin which would satisfy my needs. Unfortunately, it breaks when Maven is run with Java 10.

wilx
  • 17,697
  • 6
  • 59
  • 114
  • It would be unusual to do something like this. What exactly do you want to achieve? – J Fabian Meier Jun 27 '18 at 13:16
  • Do you need anything more complex than filtering via [maven resource plugin](https://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html)? It doesn't provide scripting, but it lets you build properties with values taht depend on profiles – Mario Trucco Jun 27 '18 at 13:18
  • @MarioTrucco: I need some string manipulation, pick one from a map, and file existence checking so far. – wilx Jun 27 '18 at 14:13
  • 1
    @wilx can you describe more in detail what you like to achieve? – khmarbaise Jun 27 '18 at 14:21

2 Answers2

1

The build helper Maven plugin has the ability to set properties according to regex. This may cover the cases you need:

https://www.mojohaus.org/build-helper-maven-plugin/regex-property-mojo.html

Regarding Nashorn: I would be careful using something that is not popular. If you really need to adapt the build beyond existing plugins, you might be better off writing your own Maven plugin.

J Fabian Meier
  • 33,516
  • 10
  • 64
  • 142
1

I see you found the nashorn-maven-plugin to run Javascript. But the ScriptEngine JS implementation has since been removed from the JRE, so that plugin won't work from Java 15 onwards unless you find a way to add the JS engine back to your classpath.

There is currently a more generic official maven plugin available to run small scripts in a very similar way. The Apache Maven Scripting Plugin can execute scripts in any JSR223 compatible scripting language.

The plugin uses the same ScriptEngine mechanism, which relies on service discovery (loading a service provider interface). This means that it can use any compatible scripting language by placing a specific library on your classpath.

For more references on the library options you have, see the following questions:

These also include code on how to list the currently available scripting languages (which is just JS for Java versions 8 to 15 if you don't add additional libraries).

I have successfully used this plugin with the language of my choice on Maven 3 and Java 17. See the full example below.

I would advice to use the <scriptFile> option if at all possible, so you don't have to maintain code in the pom file. But if you need to use any ${...} variables you might not be able to use the file option. In that case you can use the <script> option. If needed you can include the CDATA marker to keep the XML valid.

The plugin does expose the entire MavenProject model and a logger, that should cover most needs. It gives access to all the project information, properties and the build environment. The following variables are bound by default for that purpose:

In my case i used Beanshell, and the plugin setup looks like this:

 <!-- Scripting Plugin: run ScriptEngine compatible scripts -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-scripting-plugin</artifactId>
    <version>3.0.0</version>
    <executions>
        <execution>
            <id>run-script</id>
            <phase>compile</phase>
            <goals>
                <goal>eval</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <engineName>beanshell</engineName>
        <!-- <scriptFile>use this when possible; no code in the POM is preferred</scriptFile> -->
        <script>
            log.info("Hello from " + project.getArtifact());
        </script>
    </configuration>
    <dependencies>
        <!-- Script Engine: Beanshell -->
        <dependency>
            <groupId>org.apache-extras.beanshell</groupId>
            <artifactId>bsh</artifactId>
            <version>2.0b6</version>
        </dependency>
    </dependencies>
</plugin>

You can use any id and phase you like in the execution element.

By changing the dependency and engineName you can use any other compatible scripting language.

This gives the following output in the maven build log:

[INFO] --- maven-scripting-plugin:3.0.0:eval (run-script) @ tests ---
[INFO] Hello from local:tests:jar:1.0
slindenau
  • 1,091
  • 2
  • 11
  • 18