The Maven Cookbook

3.2. Running an Inline Scala Script in a Maven Build

3.2. Running an Inline Scala Script in a Maven Build

3.2.1. Task

You need to execute an inline Scala script as a part of your Maven build.

3.2.2. Action

Configure the script goal of the maven-scala-plugin, and pass a Scala script to the script configuration parameter.

Example 3.1. Executing an Inline Scala Script with the Maven Scala Plugin

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0                        
                             http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.sonatype.mcookbook</groupId>
  <artifactId>scala-script</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>scala-script</name>
  <dependencies>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-model</artifactId>
      <version>2.2.0</version>
    </dependency>
    <dependency>
      <groupId>org.scala-lang</groupId>
      <artifactId>scala-library</artifactId>
      <version>2.7.3</version>
    </dependency>
    <dependency>
      <groupId>org.scala-tools</groupId>
      <artifactId>maven-scala-plugin</artifactId>
      <version>2.10.1</version>
    </dependency>
    <dependency>
      <groupId>org.scalaforge</groupId>
      <artifactId>scalax</artifactId>
      <version>0.1</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.scala-tools</groupId>
        <artifactId>maven-scala-plugin</artifactId>
        <version>2.10.1</version>
        <executions>
          <execution>
            <phase>prepare-package</phase>
            <goals>
              <goal>script</goal>
            </goals>
            <configuration>
              <keepGeneratedScript>true</keepGeneratedScript>
              <script>
                <![CDATA[
        import java.io.{File,  PrintWriter, FileWriter};
        import scalax.io.FileExtras;
        import scala.collection.mutable.HashSet;

        val outputDir = project.getBuild().getOutputDirectory();
        val depsFile = new FileExtras( new File( outputDir, "deps.txt" ) )
        val pw = depsFile.printWriter
        val depSet = new HashSet[String]
        for( d <- project.getDependencies() ) {
          depSet += d.getGroupId + ":" + d.getArtifactId + ":" + d.getVersion
        }
        pw.writeLines( depSet.toSeq )

                ]]>
              </script>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  <repositories>
    <repository>
      <id>scala-tools</id>
      <url>http://scala-tools.org/repo-releases/</url>
    </repository>
  </repositories>
</project>

If you run mvn package, the script goal will be executed during the prepare-package phase.

~/examples/scala/scala-script $ mvn package -Dmaven.test.skip=true
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building scala-script
[INFO]    task-segment: [package]
[INFO] ------------------------------------------------------------------------
...
[INFO] [scala:script {execution: scala-magic}]
[INFO] Checking for multiple versions of scala
...
[INFO] BUILD SUCCESSFUL

After this script executes, there will be a file named deps.txt in ${basedir}/target/classes containing a list of the project's direct dependencies.

org.scalaforge:scalax:0.1
org.apache.maven:maven-model:2.2.0
org.scala-tools:maven-scala-plugin:2.10.1
org.scala-lang:scala-library:2.7.3

3.2.3. Detail

Example 3.1, “Executing an Inline Scala Script with the Maven Scala Plugin” includes the scala-tools repository and the dependency on version 0.1 of scalax to gain access to the FileExtras class which is used to augment the methods available on a File object. The FileHelper wraps the File object, and adds the method writeLines() which is used to write a Sequence of String objects. This Sequence of String objects is stored in a HashSet which is populated in a for loop that loops over all of the project's dependencies.

The other piece of configuration in this example is the keepGeneratedScript option. This option tells the Maven Scala plugin to retain the temporary Scala source which is generated by the plugin. The Scala plugin takes the inline Scala source code and creates a temporary script in ${basedir}/target/.scalaScriptGen/embeddedScript_1.scala. If keepGeneratedScript is set to false, the Maven Scala plugin will delete this file when it is finished executing the script. If keepGeneratedScript is set to true, the Scala plugin will retain this source file. Let's take a look at the embeddedScript_1.scala file:

import scala.collection.jcl.Conversions._
class embeddedScript_1(project:org.scala_tools.maven.model.MavenProjectAdapter,log:org
.apache.maven.plugin.logging.Log) {
  import java.io.{File,  PrintWriter, FileWriter};
          import scalax.io.FileExtras;
          import scala.collection.mutable.HashSet;
  
          val outputDir = project.getBuild().getOutputDirectory();
          val depsFile = new FileExtras( new File( outputDir, "deps.txt" ) )
          val pw = depsFile.printWriter
        val depSet = new HashSet[String]
          for( d <- project.getDependencies() ) {
            depSet += d.getGroupId + ":" + d.getArtifactId + ":" + d.getVersion
          }
          pw.writeLines( depSet.toSeq )
}

Notice that the class includes to argument project:org.scala_tools.maven.model.MavenProjectAdapter and log:org.apache.maven.plugin.logging.Log. The project argument gives you access to the Maven project object model and the log argument gives you access to the logging facilities of Maven. The project and log objects are only available when the Maven Scala plugin is available on the classpath, this is why you see the Maven Scala plugin declared both as a dependency of the project under dependencies in Example 3.1, “Executing an Inline Scala Script with the Maven Scala Plugin” and as a plugin.