要启动ant脚本,我使用java.lang.Runtime
类的exec
方法,如下所示:
Process Process = Runtime。getRuntime()。执行JAVA_HOME ANT_HOME -jar/lib/ant-launcher.jar-BuildFile file.xml);
这个方法,尽管看起来很简单,但是它带来了几个问题,在javadoc中描述如下:
因为一些本地平台只提供有限的缓冲区大小标准输入和输出流,不能及时写入输入流或读取子进程的输出流可能导致子进程阻塞,甚至死锁。
为了解决这个问题,我参考了以下文章:http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=1此方法适用于unemachine(64位Windows 7, Core 2 Quad Q9400 @ 2,66 GHz 2.67 GHz, 4GB)但是当我使用另一台机器(XP SP3, Core 2 Duo 2.99 GHz @ 3 GHz, 3.21 GB内存)时,该过程在生成数据模式时挂起,并且控制台在发布以下消息后保持绝望的沉默:
[hibernatetool]使用JPA配置执行Hibernate工具警告:引用没有被设置为编译。classpath.id运行时,目标是在发现构建文件解析,试图的决心。未来的Ant版本可能支持引用已定义的id
(Hibernatetool) 1。任务:hbm2ddl(生成数据库模式).
你遇到过这样的问题吗?你有解决办法吗?我愿意接受任何解决方案。注意:我的ant脚本看起来像这样:
<project>
..
<target name="create-jpa-schema">
<tstamp>
<format property="timestamp.for.sql" pattern="yyyy-MM-dd_HH-mm-ss" />
</ Tstamp>
<hibernatetool destdir="${build.sql.dir}">
<classpath>
<path refid="classpath.id" />
<pathelement path="${model.jar}" />
</ Classpath>
<jpaconfiguration persistenceunit="studio-pu" />
<! - Export schema to SQL database and run it Against ->
<Hbm2ddl drop = "false" update = "true" create = "true" export = "true" outputfilename = "$ {schema_ timestamp.for.sql}. Sql" delimiter = "" format = "true" haltOnError = "true "/>
</ Hibernatetool>
</ Target>
..
</ Project>
编辑:执行runtime.exec:
的代码public static int executeCommand(
String cmd,
File directory) throws IOException, InterruptedException
{
Process process = Runtime.getRuntime().exec(cmd, null, directory);
StreamReader outputStreamReader = new StreamReader(
process.getInputStream(),
"OUTPUT");
StreamReader errorStreamReader = new StreamReader(process.getErrorStream(), "ERROR");
final Thread outputThreadReader = new Thread(outputStreamReader);
final Thread errorThreadReader = new Thread(errorStreamReader);
outputThreadReader.start();
errorThreadReader.start();
int exitCode = process.waitFor();
System.out.println("exit code:" + exitCode);
return exitCode;
}
StreamReader.java
public class StreamReader implements Runnable
{
InputStream is;
OutputStream os;
String type;
StreamReader(InputStream is, String type)
{
this.is = is;
this.type = type;
}
StreamReader(InputStream is, OutputStream os, String type)
{
this.is = is;
this.os = os;
this.type = type;
}
@Override
public void run()
{
try
{
PrintWriter pw = null;
if (os != null)
pw = new PrintWriter(os);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null)
{
if (pw != null)
{
pw.println(line);
pw.flush();
}
else
System.out.println(type + ">" + line);
if(progressListener!=null)
progressListener.onUpdate(line);
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
我不确定这是否是一种可能性,但您是否考虑过以编程方式调用ant,而不是启动新进程?
根据本文,您应该能够在新线程中执行以下操作,而不是生成进程:
File buildFile = new File("build.xml");
Project p = new Project();
p.setUserProperty("ant.file", buildFile.getAbsolutePath());
p.init();
ProjectHelper helper = ProjectHelper.getProjectHelper();
p.addReference("ant.projectHelper", helper);
helper.parse(p, buildFile);
p.executeTarget(p.getDefaultTarget());
在StreamReader中readLine()
之前和之后添加System.out.println()
。查看当控制台挂起时,它是否仍在积极地读取,或者线程是否过早退出。
您要导出的模式特别大吗?它会产生大量产出吗?
在ant任务hbm2ddl
上有一个'console'属性,如果console="true"
将ddl复制到System.out.println()
,这可能会导致您的问题。它可能会搞乱XP系统的缓冲。
默认是console="true"。试试console="false"
<Hbm2ddl console="false" drop = "false" update = "true" create = "true" export = "true" outputfilename = "$ {schema_ timestamp.for.sql}. Sql" delimiter = "" format = "true" haltOnError = "true "/>
有关更多信息,请参见Hbm2ddl Ant任务代码