为什么这个Scala Maven POM文件不好?

时间:2016-08-10 12:42:33

标签: scala maven apache-spark jar

我有一个新的Spark应用程序,我正在使用Scala在Maven上编写,我发现我甚至因某些原因无法运行“Hello World”。虽然编译工作正常,尝试运行jar本身最终会出错。

编辑:从依赖项中删除<scope>provided</scope>,收到其他错误。

这是POM文件:

<modelVersion>4.0.0</modelVersion>
<groupId>com.app</groupId>
<artifactId>deviceScore</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>Device Score</name>

<properties>
    <spark.version>1.6.2</spark.version>
    <app.main.class>com.app.deviceScore.App</app.main.class>
</properties>

<profiles>
    <profile>
        <id>scala-2.10</id>
        <properties>
            <scala.version>2.10.6</scala.version>
            <scala.binary.version>2.10</scala.binary.version>
        </properties>
    </profile>
    <profile>
        <id>scala-2.11</id>
        <properties>
            <scala.version>2.11.8</scala.version>
            <scala.binary.version>2.11</scala.binary.version>
        </properties>
    </profile>
</profiles>

<repositories>
    <repository>
        <id>maven-repo</id>
        <name>Maven Repository</name>
        <url>http://repo1.maven.apache.org/maven2</url>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
    <repository>
        <id>s3.release</id>
        <url>s3://clojure-deps/releases</url>
    </repository>
    <repository>
        <id>apache-repo</id>
        <name>Apache release repo</name>
        <url>https://github.com/adatao/mvnrepos/tree/master/releases/</url>
    </repository>
</repositories>

<pluginRepositories>
    <pluginRepository>
        <id>scala-tools.org</id>
        <name>Scala-Tools Maven2 Repository</name>
        <url>http://scala-tools.org/repo-releases</url>
    </pluginRepository>
    <pluginRepository>
        <id>protoc-plugin</id>
        <url>http://sergei-ivanov.github.com/maven-protoc-plugin/repo/releases/</url>
    </pluginRepository>
</pluginRepositories>

<dependencies>
    <dependency>
        <groupId>org.scala-lang</groupId>
        <artifactId>scala-library</artifactId>
        <version>${scala.version}</version>

    </dependency>
    <dependency>
        <groupId>org.scala-lang</groupId>
        <artifactId>scala-compiler</artifactId>
        <version>${scala.version}</version>

    </dependency>
    <dependency>
        <groupId>org.scalatest</groupId>
        <artifactId>scalatest_${scala.binary.version}</artifactId>
        <version>2.2.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-core_${scala.binary.version}</artifactId>
        <version>${spark.version}</version>

    </dependency>
    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-hive_${scala.binary.version}</artifactId>
        <version>${spark.version}</version>

    </dependency>
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk</artifactId>
        <version>1.10.11</version>

    </dependency>
</dependencies>

<build>
    <sourceDirectory>src/main/scala</sourceDirectory>
    <testSourceDirectory>src/test/scala</testSourceDirectory>
    <plugins>
        <plugin>
            <groupId>net.alchim31.maven</groupId>
            <artifactId>scala-maven-plugin</artifactId>
            <version>3.2.0</version>
            <dependencies>
                <dependency>
                    <groupId>org.scala-lang</groupId>
                    <artifactId>scala-library</artifactId>
                    <version>${scala.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.scala-lang</groupId>
                    <artifactId>scala-compiler</artifactId>
                    <version>${scala.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.scala-lang</groupId>
                    <artifactId>scala-reflect</artifactId>
                    <version>${scala.version}</version>
                </dependency>
            </dependencies>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>testCompile</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <scalaVersion>${scala.version}</scalaVersion>
                <jvmArgs>
                    <jvmArg>-Xms256m</jvmArg>
                    <jvmArg>-Xmx2048m</jvmArg>
                </jvmArgs>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.12</version>
            <configuration>
                <skipTests>true</skipTests>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>${app.main.class}</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

应用程序非常简单:

package com.app.deviceScore

object App {
  def main(args: Array[String]) = {
    println ("Hi!")
  }
}

当我运行mvn clean package -P scala-2.11时,构建运行正常,但是当我尝试运行jar时,我使用java -jar target/deviceScore-1.0.0.jar得到:

Error: Could not find or load main class com.app.deviceScore.App

尝试scala target/deviceScore-1.0.0.jar时,我得到了:

java.lang.ClassNotFoundException: com.app.deviceScore.App
        at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:63)
        at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101)
        at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22)
        at scala.tools.nsc.JarRunner$.run(MainGenericRunner.scala:13)
        at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29)
        at scala.tools.nsc.JarRunner$.runJar(MainGenericRunner.scala:25)
        at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:69)
        at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:87)
        at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:98)
        at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103)
        at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)

我错过了什么?为了简单地运行jar,应该在POM文件中包含什么?

3 个答案:

答案 0 :(得分:2)

您已将scala-library(以及其他Scala依赖项)定义为provided - 这意味着它们不会打包在jar中,但很可能是提供在运行时外部,但它们不是 - 因此这些类在运行时丢失。

如果您从所有依赖项中删除<scope>provided</scope>(可能scala-compiler可以保留provided),这应该可以。

修改: 根据你的更新 - 不确定为什么你得到那个特定的错误(应该找到主类),但似乎还有更多要修复的地方:当你使用maven的maven-jar-plugin时,它会构建jar 而不用包括它的依赖项,这意味着你仍然不会有Scala的类。

相反,你可以使用maven的maven-assembly-plugin来创建一个“胖罐子”,包含其依赖。通过用以下代码替换jar插件来实现:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.6</version>
    <configuration>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <archive>
            <manifest>
                <mainClass>${app.main.class}</mainClass>
            </manifest>
        </archive>
    </configuration>
    <executions>
        <execution>
            <id>assemble-all</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

然后,运行:

> mvn clean package -P scala-2.11
> java -jar target/deviceScore-1.0.0-jar-with-dependencies.jar
Hi!

答案 1 :(得分:1)

要运行打包在可运行jar文件中的Scala程序,请使用scala命令而不是java -jar

scala target/deviceScore-1.0.0.jar

如果要使用java -jar运行它,则必须确保Scala库包含在类路径中。通过将Scala库的范围设置为provided,可以将其从运行时类路径中排除。

答案 2 :(得分:1)

让它发挥作用。在插件部分,我使用了这三个:

<plugins>
            <plugin>
                <groupId>org.scala-tools</groupId>
                <artifactId>maven-scala-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>${app.main.class}</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>${app.main.class}</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>

第一个与前一个pom文件中使用的scala-maven-plugin不同。第二个插件在使用scala target/deviceScore-1.0.0.jar时使jar可执行,而Tzach Zohar提到的第三个插件创建了一个可以java -jar target/deviceScore-1.0.0-jar-with-dependencies.jar执行的胖jar