Reputation: 582
I need to execute an external program from Java (to convert a fodt file to pdf using libreoffice, it so happens) I know the precise command-line I need for the program:
/usr/bin/libreoffice --headless --convert-to pdf:'writer_pdf_Export' --outdir /home/develop/tomcat/mf/ROOT/private/docs/0/ /home/develop/tomcat/mf/ROOT/private/docs/0/35_invoice.fodt
and that works perfectly from the command line.
But it does not work in Java using a ProcessBuilder
:
java.io.IOException: Cannot run program "/usr/bin/libreoffice --headless --convert-to pdf:'writer_pdf_Export' --outdir /home/develop/tomcat/mf/ROOT/private/docs/0 /home/develop/tomcat/mf/ROOT/private/docs/0/35_invoice.fodt": java.io.IOException: error=2, No such file or directory
I tried some different approaches without success. Here is a sample of the last test
List<String> command = new ArrayList<String>();
command.add("/usr/bin/libreoffice");
command.add("--headless");
command.add("--convert-to pdf:'writer_pdf_Export' --outdir " + getDestinationDirectory(order) + " " + getInvoiceFilename() + ".fodt");
ProcessBuilder builder = new ProcessBuilder(command);
Process process = null;
try {
process = builder.start();
} catch (IOException ex) {
Logger.getLogger(Documents.class.getName()).log(Level.SEVERE, null, ex);
}
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
try {
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException ex) {
Logger.getLogger(Documents.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Program terminated!");
Upvotes: 10
Views: 59878
Reputation: 883
ProcessBuilder can be erratic sometimes with long command (executable path with lot of arguments.). What you can do is,
Assume your command string is String cmdString = "executableFilePath -param1 -param2"
Convert this to map
List cmdMap = Arrays.asList(cmdString.split(" "));
Pass this cmdMap to ProcessBuilder.
Upvotes: 0
Reputation: 120506
The ProcessBuilder
constructors require each argument of the external program to be separate
(in the form of an array or List
of String
s). The first exception message you got,
Cannot run program "/usr/bin/libreoffice --headless --convert-to pdf:'writer_pdf_Export' --outdir /home/develop/tomcat/mf/ROOT/private/docs/0 /home/develop/tomcat/mf/ROOT/private/docs/0/35_invoice.fodt"
is not complaining that it can find a program named /usr/bin/libreoffice
. It is complaining that it can not find a program with the very long and peculiar name "/usr/bin/libreoffice --headless --convert-to pdf:'writer_pdf_Export' --outdir /home/develop/tomcat/mf/ROOT/private/docs/0 /home/develop/tomcat/mf/ROOT/private/docs/0/35_invoice.fodt
", because you concatenated the arguments into one String
.
Instead of
command.add("--convert-to pdf:'writer_pdf_Export' --outdir " + getDestinationDirectory(order) + " " + getInvoiceFilename() + ".fodt")
and such like, split each of the arguments into its own call to List.add
command.add("--convert-to");
command.add("pdf:writer_pdf_Export");
command.add("--outdir");
command.add(getDestinationDirectory(order).toString());
command.add(getInvoiceFilename() + ".fodt");
Note that there are no apostrophes around "writer_pdf_Export" since those are shell meta-characters and are not required when you're constructing an array to pass to exec
without an intermediating shell.
Upvotes: 6
Reputation: 305
I have tried every solution proposed in this thread and it does not work.
In my app (java webapp using TOMCAT in linux) it only works to create a shell script and execute the script. But you have to put the absolute path in the script, if not, it does not work ($HOME does not work). Besides, you can pass it arguments.
Example:
Runtime.getRuntime().exec("/home/user/myscript.sh param1");
Upvotes: 1
Reputation: 9711
Try this (keep it simple) ...
Process p = Runtime.getRuntime().exec("/usr/bin/libreoffice --headless --convert-to pdf:'writer_pdf_Export' --outdir "+ getDestinationDirectory(order)+" "+getInvoiceFilename()+".fodt");
Fully ...
Process process = null;
try {
process = Runtime.getRuntime().exec("/usr/bin/libreoffice --headless --convert-to pdf:'writer_pdf_Export' --outdir "+ getDestinationDirectory(order)+" "+getInvoiceFilename()+".fodt");
} catch (IOException ex) {
Logger.getLogger(Documents.class.getName()).log(Level.SEVERE, null, ex);
}
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
try {
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException ex) {
Logger.getLogger(Documents.class.getName()).log(Level.SEVERE, null, ex);
}
br.close();
System.out.println("Program terminated!");
Upvotes: 1