Maven -scala実行-
mavenを初めて使う機会があったので,引っかかったところを中心にまとめてみる.
maven自体がどんなものかはhttps://kengotoda.gitbooks.io/what-is-maven/primer/ を
読むことでおおまかなイメージをつけた.
本記事は以下の目的を達成するための手順を解説していく.
- scalaコードを含むプロジェクト作成
- mavenでscalaコードを実行するための設定
- 依存関係を含むjarファイルの生成とその実行
環境は
ApacheMave:3.5.0 java:1.8.0 scala:2.11.6
プロジェクト作成
$ mvn archetype:generate
Choose a number or apply filter : scala
# 7: remote -> net.alchim31.maven:scala-archetype-simpleを確認して
Choose a number or apply filter : 7
Choose a number : 3
Define value for property 'groupId': project.test
Define value for property 'artifactId': mavenTest
Define value for property 'version' 1.0-SNAPSHOT: [Enter]
Define value for property 'package' project.test: [Enter]
Y: [Enter]
これでmavenTestフォルダが生成される.
$ tree mavenTest
mavenTest/
├── pom.xml
└── src
├── main
│ └── scala
│ └── project
│ └── test
│ └── App.scala
└── test
└── scala
└── samples
├── junit.scala
├── scalatest.scala
└── specs.scala
実行するための設定
このままコンパイルを実行すると,
$ cd mavenTest
$ mvn compile
...
[ERROR] scalac error: bad option: '-make:transitive'
[INFO] scalac -help gives more information
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.446 s
[INFO] Finished at: 2017-08-11T21:39:24+09:00
[INFO] Final Memory: 11M/300M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal net.alchim31.maven:scala-maven-plugin:3.2.0:compi
...
というエラーが出てくる.そこでpom.xmlを次のように編集する.
<!-- この行を削除する -->
<arg>-make:transitive</arg>
するとコンパイルは成功するので実行を行う.すると次のエラーが出る.
$ mvn scala:run
...
[ERROR] /home/yoshiki/xgboost/jvm-packages/project/mavenTest/src/test/scala/samples/specs.scala:18: error: not found: type JUnitRunner
[ERROR] @RunWith(classOf[JUnitRunner])
[ERROR] ^
[ERROR] one error found
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.391 s
[INFO] Finished at: 2017-08-11T21:43:41+09:00
[INFO] Final Memory: 11M/300M
[INFO] ------------------------------------------------------------------------
...
どうやらテストコードのビルドにコケたようである.
そこで次のようにpom.xmlを変更する.
#ちなみに,mvn compileやmvn scala:runのcompile, scala:runは実行のゴールを指定するため,
mvn scala:runはmvn compileの操作を包含している.なので実際はmvn scala:runの実行だけで良い.
<dependencies>
...
<!-- JUnitRunner -->
<dependency>
<groupId>org.specs2</groupId>
<artifactId>specs2-junit_${scala.compat.version}</artifactId>
<!--versionは前後のspecs2-coreなどに合わせる-->
<version>2.4.16</version>
<scope>test</scope>
</dependency>
<!----------------->
...
</dependencies>
実行
$ mvn scala:run
[WARNING] warning: there was one deprecation warning; re-run with -deprecation for details
[WARNING] one warning found
[INFO] prepare-compile in 0 s
[INFO] compile in 4 s
[INFO]
[INFO] <<< scala-maven-plugin:3.2.0:run (default-cli) < test-compile @ mavenTest <<<
[INFO]
[INFO]
[INFO] --- scala-maven-plugin:3.2.0:run (default-cli) @ mavenTest ---
[WARNING] Not mainClass or valid launcher found/define
main class が無いということなのでscala-maven-pluginに指定する.(参考:http://qiita.com/motokazu/items/57540c80509d83c6a168 )
<!-- scala-maven-pluginのpluginのところに追加-->
<plugin>
<!-- see http://davidb.github.com/scala-maven-plugin -->
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
<configuration>
<args>
<arg>-dependencyfile</arg>
<arg>${project.build.directory}/.scala_dependencies</arg>
</args>
</configuration>
</execution>
</executions>
<!-- ここから -->
<configuration>
<launchers>
<launcher>
<id>test</id>
<mainClass>project.test.App</mainClass>
<args>
<arg>${basedir}</arg>
</args>
</launcher>
</launchers>
</configuration>
<!-- ここまで追加 -->
</plugin>
mvn scala:runすると,無事に'Hello world!'が出力される.
次に自由に使いたいライブラリをpom.xmlのdependenciesに追加していく.xgboostであれば,
<dependency>
<groupId>ml.dmlc</groupId>
<artifactId>xgboost4j</artifactId>
<version>0.7</version>
</dependency>
と言った具合に追加する.(実際にxgboostを使うには,あらかじめ公式の手順でmvn installしなければならない)
実行だけを行いたい
mvn scala:runはアプリケーションをコンパイル&実行してくれるが,勝手にコンパイルまでしてしまう.もし実行だけを行いたいならば,まず依存ライブラリを含むjarファイルを生成する必要がある.そのために
maven-assembly-pluginをpom.xmlに追加する.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
実行
$ ls target
archive-tmp maven-status test-classes
classes mavenTest-1.0-SNAPSHOT.jar test-classes.-2096028797.timestamp
classes.936127338.timestamp mavenTest-1.0-SNAPSHOT-jar-with-dependencies.jar
maven-archiver specs2-reports
$ scala -cp target/mavenTest-1.0-SNAPSHOT-jar-with-dependencies.jar project.test.App
Hello World!
concat arguments =
repository のurlを追加
<project>
<repositories>
<id>my-repo1</id>
<name>central-repo</name>
<url>https://repo.maven.apache.org/maven2/</url>
</repository>
<repository>
<id>my-repo2</id>
<name>maven2-repo</name>
<url>https://dl.bintray.com/spark-packages/maven/</url>
</repository>
</repositories>
</project>
おわり.