Maven中无法运行Ant代码的解决方法

3

这可能是我在Java中见过的最奇怪的事情:以下代码(不使用外部库)在Ant上(在Netbeans上,在Windows-7机器上)无缝运行:

public static void main( String[] args ) throws IOException, InterruptedException
{
  String prog = "\"C:\\Program Files\\R\\R-2.14.2\\bin\\Rscript.exe\"";
  String[] progParams = new String[]{"C:\\Users\\pantelis\\Desktop\\SB\\MC_Sarfraz_ver5.R"};
  Process p = Runtime.getRuntime().exec(prog+" "+progParams[0]);
  p.waitFor();
  System.out.println(p.exitValue()==0);
  System.out.println("Done!!!"); 
}

它会返回输出信息:

true
Done!!!

这意味着程序已经顺利完成。然而,当我使用Maven运行相同的代码时,没有出现异常,但是代码最终输出:

false
Done!

而且这个过程从未被执行。这是我的POM文件:
<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany</groupId>
  <artifactId>MVNTest</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>
  <name>MVNTest</name>
  <url>http://maven.apache.org</url>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>
更新 1: 我使用了以下代码来打印由进程生成的任何错误消息:
String line;
BufferedReader input = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while ((line = input.readLine()) != null) {
  System.out.println(line);
}

这里是输出内容:
Error in library(RDCOMClient) : there is no package called 'RDCOMClient'
Execution halted

只有在使用Maven运行时才会出现此错误消息。
更新2:当我使用Maven运行时,我使用JDK7。以下是相应的命令:
cd C:\Users\pantelis\Documents\NetBeansProjects\MVNTest; 
"JAVA_HOME=C:\\Program Files\\Java\\jdk1.7.0_04" 
"\"C:\\Program Files\\NetBeans 7.1.2\\java\\maven\\bin\\mvn.bat\""  
"-Dexec.args=-classpath %classpath com.mycompany.mvntest.App"
"-Dexec.executable=C:\\Program Files\\Java\\jdk1.7.0_04\\bin\\java.exe" 
-Dexec.classpathScope=runtime process-classes 
org.codehaus.mojo:exec-maven-plugin:1.2:exec

更新3: 这些是我使用Ant运行时得到的环境变量:

USERPROFILE -> C:\Users\pantelis
ProgramData -> C:\ProgramData
PATHEXT -> .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
Classpath -> C:\LINGO9\Lingo9_0.jar
ProgramFiles(x86) -> C:\Program Files (x86)
TEMP -> C:\Users\pantelis\AppData\Local\Temp
SystemDrive -> C:
ProgramFiles -> C:\Program Files
Path -> C:\Program Files (x86)\MiKTeX 2.9\miktex\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\WIDCOMM\Bluetooth Software\;C:\Program Files\WIDCOMM\Bluetooth Software\syswow64;\;C:\Program Files (x86)\Sony\VAIO Startup Setting Tool;C:\Program Files (x86)\ATI Technologies\ATI.ACE\Core-Static;C:\LINGO9\;C:\Program Files (x86)\OpenVPN\bin
HOMEDRIVE -> C:
PROCESSOR_REVISION -> 2505
USERDOMAIN -> pantelis-VAIO
ALLUSERSPROFILE -> C:\ProgramData
ProgramW6432 -> C:\Program Files
PROCESSOR_IDENTIFIER -> Intel64 Family 6 Model 37 Stepping 5, GenuineIntel
SESSIONNAME -> Console
TMP -> C:\Users\pantelis\AppData\Local\Temp
CommonProgramFiles -> C:\Program Files\Common Files
=:: -> ::\
LOGONSERVER -> \\PANTELIS-VAIO
PROCESSOR_ARCHITECTURE -> AMD64
FP_NO_HOST_CHECK -> NO
OS -> Windows_NT
HOMEPATH -> \Users\pantelis
PROCESSOR_LEVEL -> 6
CommonProgramW6432 -> C:\Program Files\Common Files
configsetroot -> C:\Windows\ConfigSetRoot
LOCALAPPDATA -> C:\Users\pantelis\AppData\Local
COMPUTERNAME -> PANTELIS-VAIO
windir -> C:\Windows
SystemRoot -> C:\Windows
NUMBER_OF_PROCESSORS -> 4
USERNAME -> pantelis
PUBLIC -> C:\Users\Public
PSModulePath -> C:\Windows\system32\WindowsPowerShell\v1.0\Modules\
CommonProgramFiles(x86) -> C:\Program Files (x86)\Common Files
ComSpec -> C:\Windows\system32\cmd.exe
APPDATA -> C:\Users\pantelis\AppData\Roaming

当我使用Maven运行时,这里是环境变量:

USERPROFILE -> C:\Users\pantelis
JAVA_HOME -> C:\Program Files\Java\jdk1.7.0_04
PROGRAMDATA -> C:\ProgramData
MAVEN_CMD_LINE_ARGS -> "-Dexec.args=-classpath %classpath com.mycompany.mvntest.App" "-Dexec.executable=C:\Program Files\Java\jdk1.7.0_04\bin\java.exe" -Dexec.classpathScope=runtime process-classes org.codehaus.mojo:exec-maven-plugin:1.2:exec
CONFIGSETROOT -> C:\Windows\ConfigSetRoot
COMMONPROGRAMFILES -> C:\Program Files\Common Files
PROCESSOR_REVISION -> 2505
USERDOMAIN -> pantelis-VAIO
ALLUSERSPROFILE -> C:\ProgramData
PROGRAMW6432 -> C:\Program Files
SESSIONNAME -> Console
TMP -> C:\Users\pantelis\AppData\Local\Temp
PSMODULEPATH -> C:\Windows\system32\WindowsPowerShell\v1.0\Modules\
NB_EXEC_MAVEN_PROCESS_UUID -> b5daa24f-51dc-48ac-ad6d-820dc245b80a
M2_HOME -> C:\Program Files\NetBeans 7.1.2\java\maven\bin\..
LOGONSERVER -> \\PANTELIS-VAIO
=:: -> ::\
PATH -> C:\Program Files (x86)\MiKTeX 2.9\miktex\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\WIDCOMM\Bluetooth Software\;C:\Program Files\WIDCOMM\Bluetooth Software\syswow64;\;C:\Program Files (x86)\Sony\VAIO Startup Setting Tool;C:\Program Files (x86)\ATI Technologies\ATI.ACE\Core-Static;C:\LINGO9\;C:\Program Files (x86)\OpenVPN\bin
PROMPT -> $P$G
COMMONPROGRAMW6432 -> C:\Program Files\Common Files
PROCESSOR_LEVEL -> 6
LOCALAPPDATA -> C:\Users\pantelis\AppData\Local
COMPUTERNAME -> PANTELIS-VAIO
CLASSWORLDS_LAUNCHER -> org.codehaus.plexus.classworlds.launcher.Launcher
USERNAME -> pantelis
APPDATA -> C:\Users\pantelis\AppData\Roaming
WINDIR -> C:\Windows
PATHEXT -> .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
PROGRAMFILES(X86) -> C:\Program Files (x86)
TEMP -> C:\Users\pantelis\AppData\Local\Temp
HOMEDRIVE -> C:
SYSTEMDRIVE -> C:
=C: -> C:\Users\pantelis\Documents\NetBeansProjects\MVNTest
ERROR_CODE -> 0
COMMONPROGRAMFILES(X86) -> C:\Program Files (x86)\Common Files
CLASSWORLDS_JAR -> "C:\Program Files\NetBeans 7.1.2\java\maven\bin\..\boot\plexus-classworlds-2.4.jar"
PROCESSOR_IDENTIFIER -> Intel64 Family 6 Model 37 Stepping 5, GenuineIntel
MAVEN_JAVA_EXE -> "C:\Program Files\Java\jdk1.7.0_04\bin\java.exe"
CLASSPATH -> C:\LINGO9\Lingo9_0.jar
PROCESSOR_ARCHITECTURE -> AMD64
FP_NO_HOST_CHECK -> NO
OS -> Windows_NT
HOMEPATH -> \Users\pantelis
COMSPEC -> C:\Windows\system32\cmd.exe
PROGRAMFILES -> C:\Program Files
HOME -> C:\Users\pantelis
NUMBER_OF_PROCESSORS -> 4
PUBLIC -> C:\Users\Public
SYSTEMROOT -> C:\Windows

记录退出值而不仅仅是测试是否为0。还要查看错误流和输入流中是否有任何输出。很可能会找到更多信息。 - Guillaume Polet
@GuillaumePolet 我的代码调用了一个R脚本。根据上面的错误信息,RDCOMClient包未找到(这是一个R库)。但奇怪的是它可以在Ant中运行。 - Pantelis Sopasakis
3个回答

1

更新后,根据从Maven运行时出现的错误,似乎某些(类)路径没有正确设置:RDCOMClient似乎与R相关,因此运行Rscript.exe的设置是问题所在。

在通过ant和maven运行时打印环境变量,并进行比较以确定缺失库错误的来源。

来自评论的更新:

问题可能与如何从maven执行项目有关:exec:exec启动一个新的JVM,而exec:java在运行maven的同一JVM中运行项目。

来自评论的更新:

显然,NetBeans中的“保存时编译”设置将maven目标从exec:exec更改为exec:java。或者,您可以手动配置pom.xml(请参见exec maven plugin页面,其中包含两个目标的示例和描述)。


有一些差异,但我无法确定是否有错误。我会在我的问题中更新更多信息。 - Pantelis Sopasakis
实际上我无法发现任何可能造成差异的问题(除了环境变量名称的大小写敏感性,但我认为这并不重要)。你是如何通过ant执行它的?你可以尝试使用mvn exec:java运行它——exec:exec会启动一个单独的JVM,而exec:java则使用正在运行maven的那个JVM。目前我想不到其他可能会有影响的因素了... - Attila
你实际上帮我找到了问题的解决方案。毕竟它是执行目标...从Netbeans中,我选择了“保存时编译:适用于应用程序和测试执行”的选项,所以,在更新后,你值得获得绿色的勾号...非常感谢! - Pantelis Sopasakis
@PantelisSopasakis - 如果您考虑了其他更新,请告诉我。我不确定NetBeans设置如何相关。 - Attila
@Attile:当我使用"For both application blah blah"运行时,目标从"exec:exec"变为"run"。我该如何在我的pom.xml中定义这个呢?调整NetBeans的"Compile On Save"属性的解决方案是特定于IDE的,但对于使用NetBeans的人来说仍然是一个好的建议。修改POM文件是更通用的结果。 - Pantelis Sopasakis

1
这个问题是所有的R包都会出现吗?还是只有RDCOMClient包?
如果这是Maven / Ant问题,我会非常惊讶。
读取错误流是不必要的。R会在文件中输出错误,或者您可以使用sink(“filename”)将R输出写入文件。
请视为评论。

例如,样条曲线不会出现这种情况。因此,我猜测RDCOMClient的安装存在问题。即使是一个只包含一行library(RDCOMClient)的简单R脚本也会出错。我该如何跟踪错误并进行故障排除? - Pantelis Sopasakis
我想我首先要做的事情是进入R提示符并输入library()以查看我正确安装的库。我不在Windows机器上,因此没有RDCOMClient。在Linux上,有两个存储R包的位置,如果这些包都没有存储在这两个位置中的任何一个位置,R将无法访问该库。 - Sridhar

0

我认为你需要将你的程序和参数放在一个数组中指定,并将该数组传递给exec。

public static void main( String[] args ) throws IOException, InterruptedException
{
  String prog = "\"C:\\Program Files\\R\\R-2.14.2\\bin\\Rscript.exe\"";
  String[] progParams = new String[] {
     prog,
     "C:\\Users\\pantelis\\Desktop\\SB\\MC_Sarfraz_ver5.R"
  };
  Process p = Runtime.getRuntime().exec(progParams);
  p.waitFor();
  System.out.println(p.exitValue()==0);
  System.out.println("Done!!!"); 
}

我也尝试过这个版本。但请记住,同样的代码在Ant下运行得非常顺畅,但在Maven下却不是这样。 - Pantelis Sopasakis
有时候他们可能使用不同的JVM。据我所知,在Windows系统中,Java二进制文件可能位于System32文件夹中。如果是这样,尝试删除它以确保使用哪个JVM。 - weekens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接