I have a problem running a command in java using the Process builder. In the test machine it works correctly but once on the server the proccess being opened by the command freezes and never exits. this code is used on an apache tomcat windows web server:
//WORD is the absolute path for msWord and inF is the absolute path
//for the file to save as pdf
public boolean changeFormatMSOffice(String inF, String WORD) {
System.out.println("changeFormatMSOffice(" + inF + "," + WORD + ")");
String macro = "";
ArrayList<String> wordArr = new ArrayList<String>(java.util.Arrays.asList(TO_PDF_WORD.replace(" ", "").split(",")));
ArrayList<String> excelArr = new ArrayList<String>(java.util.Arrays.asList(TO_PDF_EXCEL.replace(" ", "").split(",")));
ArrayList<String> ppArr = new ArrayList<String>(java.util.Arrays.asList(TO_PDF_PP.replace(" ", "").split(",")));
String extension = inF.substring(inF.lastIndexOf(".")).replace(".", "").trim();
BufferedWriter out;
List<String> cmdList = new ArrayList<String>();
cmdList.add(WORD);
String saveFile = "";
if (wordArr.contains(extension)) {
macro = "/msaveAsPDF";
cmdList.add(macro);
cmdList.add(inF);
} else if (excelArr.contains(extension) || ppArr.contains(extension)) {
if (excelArr.contains(extension)) {
macro = "/mSaveXLSAsPDF";
} else {
macro = "/msavePPTAsPDF";
}
cmdList.add(macro);
int fileNum = 0;
saveFile = "\"" + PATH + (PATH.substring(PATH.length() - 1).equals(File.separator) ? "" : File.separator) + fileNum + ".txt\"";
while (new File(saveFile).exists()) {
fileNum++;
saveFile = "\"" + PATH + (PATH.substring(PATH.length() - 1).equals(File.separator) ? "" : File.separator) + fileNum + ".txt\"";
}
try {
out = new BufferedWriter(new FileWriter(saveFile));
out.write(inF);
out.close();
cmdList.add(saveFile);
} catch (Exception e) {
System.err.println(e.toString());
}
}
try {
ProcessBuilder proc = new ProcessBuilder(cmdList);
System.out.println("PreWaitForList");
Process pro = proc.start(); //<----- important part starts here
StreamGobbler g1 = new StreamGobbler("stdin", pro.getInputStream());
StreamGobbler g2 = new StreamGobbler("stderr", pro.getErrorStream());
g1.start();
g2.start();
pro.waitFor();//<---- hangs here, but need to wait for it to exit(system requirement)
System.out.println("AfterWaitFor");
try {
if (!saveFile.equals("")) {
new File(saveFile).delete();
}
} catch (Exception e) {
}
return true;
} catch (Exception e) {
System.err.println(e.toString());
return false;
}
}
i found information saying that you need to collect the std and error streams else it will freze so i used the following stream gobbler implementation:
public class StreamGobbler implements Runnable {
String name;
InputStream is;
Thread thread;
public StreamGobbler(String name, InputStream is) {
this.name = name;
this.is = is;
}
public void start() {
thread = new Thread(this);
thread.start();
}
public void run() {
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
while (true) {
String s = br.readLine();
if (s == null) {
break;
}
System.out.println("[" + name + "] " + s);
}
is.close();
} catch (Exception ex) {
System.out.println("Problem reading stream " + name + "... :" + ex);
ex.printStackTrace();
}
}
}
note that while running the command in the command line it works, in both the test machine and in the server
Are the environment parameters (like $path) and the working directory the same when you start the process from java vs the command line?