Enables Maven to read POMs (pom.scala
) written in Scala Language.
In your project extension configuration .mvn/extensions.xml
add the following:
<extensions xmlns="http://maven.apache.org/EXTENSIONS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.0.0 http://maven.apache.org/xsd/core-extensions-1.0.0.xsd">
<extension>
<groupId>io.takari.polyglot</groupId>
<artifactId>polyglot-scala</artifactId>
<version>0.4.9</version>
</extension>
</extensions>
You can (initially) convert existing projects with the polyglot-translate-plugin
.
mvn io.takari.polyglot:polyglot-translate-plugin:0.4.9:translate -Dinput=pom.xml -Doutput=pom.scala
As an example, the pom.xml
of this project pom (in version 0.4.9) written as pom.scala
would look like:
import org.sonatype.maven.polyglot.scala.model._
import scala.collection.immutable.Seq
Model(
"" % "polyglot-scala",
packaging = "takari-jar",
name = "Polyglot :: Scala",
contributors = Seq(
Contributor(
name = "Christopher Hunt",
organization = "Typesafe",
organizationUrl = "http://typesafe.com"
),
Contributor(
name = "Tobias Roeser",
url = "https://github.com/lefou"
)
),
parent = Parent(
gav = "io.takari.polyglot" % "polyglot" % "0.4.7-SNAPSHOT"
),
repositories = Seq(
Repository(
snapshots = RepositoryPolicy(
enabled = false
),
id = "sonatype-public-grid",
url = "http://repository.sonatype.org/content/groups/sonatype-public-grid/"
)
),
dependencies = Seq(
"io.takari.polyglot" % "polyglot-common" % "",
"com.twitter" % "util-eval_2.11" % "6.43.0",
"com.googlecode.kiama" % "kiama_2.11" % "1.8.0",
"org.scala-lang" % "scala-library" % "${scala.version}",
"org.scala-lang" % "scala-reflect" % "${scala.version}",
"org.scala-lang" % "scala-compiler" % "${scala.version}",
"org.specs2" % "specs2-junit_2.11" % "3.9.5" % "test"
),
properties = Map(
"scala.version" -> "2.11.12"
),
build = Build(
sourceDirectory = "src/main/scala",
testSourceDirectory = "src/test/scala",
pluginManagement = PluginManagement(
plugins = Seq(
Plugin(
"org.eclipse.m2e" % "lifecycle-mapping" % "1.0.0",
configuration = Config(
lifecycleMappingMetadata = Config(
pluginExecutions = Config(
pluginExecution = Config(
pluginExecutionFilter = Config(
groupId = "net.alchim31.maven",
artifactId = "scala-maven-plugin",
versionRange = "[3.3.0,)",
goals = Config(
goal = "add-source",
goal = "compile",
goal = "testCompile"
)
),
action = Config(
ignore = None
)
)
)
)
)
)
)
),
plugins = Seq(
Plugin(
"org.apache.maven.plugins" % "maven-compiler-plugin",
executions = Seq(
Execution(
id = "default-compile",
phase = "none"
)
)
),
Plugin(
"net.alchim31.maven" % "scala-maven-plugin" % "4.3.1",
executions = Seq(
Execution(
goals = Seq(
"compile",
"testCompile"
),
configuration = Config(
args = Config(
arg = "-deprecation",
arg = "-feature"
),
checkMultipleScalaVersions = "false",
recompileMode = "incremental",
useZincServer = "true"
)
)
)
),
Plugin(
"org.apache.maven.plugins" % "maven-surefire-plugin",
configuration = Config(
includes = Config(
include = "%regex[.*Spec.*]"
)
)
)
)
),
modelVersion = "4.0.0"
)
More examples…
-
Supports the complete Maven POM model
-
compact sbt-like notation for dependencies:
group % artiact % version % scope
-
Dynamic notation of plugin configurations with
Config
-
Provides full Scala Language features to write poms
-
Conversion to and from
pom.xml
via thepolyglot-translate-plugin
-
Powerful include feature, to share configuration code between poms
-
Works out of the box with Maven 3.3.1+
Polyglot-Scala allows you to write sbt-like scala-binary-version specific dependencies with %%
.
import org.sonatype.maven.polyglot.scala.model._
import scala.collection.immutable.Seq
implicit val scalaVersion = ScalaVersion("2.12.6")
Model(
dependencies = Seq(
"com.typesafe.akka" %% "akka-actor" % "2.5.9"
)
// ...
)
which is preferred over
"com.typesafe.akka" % s"akka-actor_${scalaVersion.binaryVersion}" % "2.5.9"
or even
"com.typesafe.akka" % "akka-actor_2.12" % "2.5.9"
For example, consider the following snippet, which uses a Maven property to define the Scala version
Model(
properties = Map(
"scala.version" -> "2.12.6"
),
dependencies = Seq(
"org.scala-lang" % "scala-library" % "${scala.version}",
"org.scala-lang" % "scala-reflect" % "${scala.version}"
)
// ...
)
Instead, you can use a Scala immutable variable to hold the Scala version.
val scalaVersion = "2.12.6"
Model(
dependencies = Seq(
"org.scala-lang" % "scala-library" % scalaVersion,
"org.scala-lang" % "scala-reflect" % scalaVersion
)
// ...
)
Benefits:
-
Variables are checked at compile-time (parse-time of pom), thus incomplete removals or renaming will fail early before Maven start building the project.
-
Maven will only see the actual value, thus no variables will be in the resulting pom which gets installed into the artifact repository.
One unique feature of the Polyglot Scala Extension is the include macro.
pom.scala
: Include code from the shared file mvn-shared.scala
//#include mvn-shared.scala
By placing the project version number in a shared scala file and including it into each project, you have to only edit one central place when the version number needs to be modified.
Also, the include process is completely transparent to Maven. When your artifact gets installed and deployed, the version is no longer a variable, which makes later resolve processes more robust.
Tip
|
Avoid Maven parent poms completely, by using include files for dependency and plugin definitions. |
Instead of defining and referencing parent poms, you should consider to define an object which produces the desired project model with all its settings and potential defaults. This not only makes the reasoning about your project easier, it also avoid various issues Maven has with parent poms. It also speeds up the build and produces less artifacts to download.
In case your pom.xml
does not have an proper XML header (aka XML Declaration), conversion with the polyglot-translate-plugin
will fail.
You can work around this issue by adding the missing XML header to the pom file.
E.g. just add to following line as to the top of the pom.xml
.
<?xml version="1.0" encoding="UTF-8"?>