Running "ProcessBuilder.start" on Docker fails - java

Installation of libreoffice package in Docker container.
I'm trying to convert a JAVA application from Excel to a PDF file, but an error occurs.
(The container is running on Google Cloud Run.)
The Dockerfile is below.
FROM maven:3.8-jdk-11
RUN apt-get -y update
RUN apt-get -y install libreoffice
RUN mvn package
FROM adoptopenjdk/openjdk11:alpine-jre
CMD ["java", "-jar", "/app.jar"]
The java code running in the container is below.
ProcessBuilder builder = new ProcessBuilder("/bin/sh", "-c", "soffice --headless -convert-to pdf --outdir '/out' '/out/file.xlsx'");
Process process = builder.start();
The error message that is output is as follows.
line 1: soffice:not found
After installing the package in the Dockerfile, when I executed the which command, usr/bin/libreoffice existed, so I think the path is correct. (I may be wrong)
I'm thinking that there might be information that's missing but I'm not so sure since I'm a newbie with Docker.
Any help would be greatly appreciated.

The error says that /bin/sh does not know where the binary soffice is. The "soffice" binary must be on the PATH for /bin/sh. Launch a shell and check with which soffice, you may be able to fix your shell profile to include the correct PATH directories for soffice before your code will work:
ProcessBuilder builder = new ProcessBuilder("/bin/sh", "-c", "soffice --headless -convert-to pdf --outdir '/out' '/out/file.xlsx'");
But if you know the fully qualified path to the soffice binary you should be able to eliminate the use of sub-process shell and separate the command line arguments:
String soffice = "/full/path/to/soffice"; // eg /usr/lib/libreoffice/program/soffice.bin
// Check with:
System.out.println(soffice +" exists: "+new File(soffice).exists());
ProcessBuilder builder = new ProcessBuilder(soffice, "--headless", "-convert-to pdf", "--outdir", "/out", "/out/file.xlsx");
If "soffice" is in the PATH provided to your JVM, then launch without sub-process shell and path ought to work. You may be able to check which soffice before launching your Java application to see if this may work:
String soffice = "soffice";
ProcessBuilder builder = new ProcessBuilder(soffice, "--headless", "-convert-to pdf", "--outdir", "/out", "/out/file.xlsx");

Related

Cannot run program "wkhtmltopdf": error=2, No such file or directory - Getting this error from Java

I am executing wkhtmltopdf command line tool from Java but it is throwing below error.
Cannot run program "wkhtmltopdf": error=2, No such file or directory
But note that when I execute this command line tool from my mac terminal then pdf got generated successfully. Please see below.
MacBook-Air-2:~ inDiscover$ wkhtmltopdf /var/folders/7y/2vr28n113p908ksnk0fnpqch0000gn/T/test7896850081571855407.html /Users/mymac/Documents/Project/emailbody/test2.pdf
Loading pages (1/6)
Counting pages (2/6)
Resolving links (4/6)
Loading headers and footers (5/6)
Printing pages (6/6)
Done
I have seen lot many similar questions here (for ex: wkhtmltopdf: No such file or directory [ Closed ]) but issue with those questions are related to $PATH. In my case I believe that I have set the path to the executable to $PATH correctly. Please see below.
MacBook-Air-2:~ inDiscover$ locate wkhtmltopdf
/private/var/db/receipts/org.wkhtmltopdf.wkhtmltox.bom
/private/var/db/receipts/org.wkhtmltopdf.wkhtmltox.plist
/usr/local/bin/wkhtmltopdf
/usr/local/share/man/man1/wkhtmltopdf.1.gz
You can see here wkhtmltopdf has been added to $PATH (/usr/local/bin)
Also , see below the response for echo $PATH.
MacBook-Air-2:~ inDiscover$ echo $PATH
/Users/mymac/anaconda/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
MacBook-Air-2:~ inDiscover$
I am getting this issue only when I try to execute the command from Java. Please see my java code below.
String VIEWPORT_SIZE = "2480x3508";
int CONVERSION_DPI = 300;
int IMAGE_QUALITY = 100;
List<String> cmd = new ArrayList<String>(Arrays.asList("wkhtmltopdf",
"--viewport-size", VIEWPORT_SIZE,
"--enable-local-file-access",
// "--disable-smart-shrinking",
"--dpi", String.valueOf(CONVERSION_DPI),
"--image-quality", String.valueOf(IMAGE_QUALITY)));
//cmd.addAll(extParams);
cmd.add("/var/folders/7y/2vr28n113p908ksnk0fnpqch0000gn/T/test7896850081571855407.html");
cmd.add("/Users/mymac/Documents/Project/emailbody/test3.pdf");
try {
ProcessBuilder pb = new ProcessBuilder(cmd);
if (Logger.level.compareTo(LogLevel.Info) >= 0) {
pb.inheritIO();
}
Process p = pb.start();
p.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
Am I really missing something?
Here are a few things you can check, one will hopefully resolve your issue.
Nearly all occasions I've seen where java is not finding an application that your shell or terminal does run are down to use of commands built into the shell / terminal (such as an alias), or because of PATH used in a script that you use to launch your java yourapp.ClassName ... is different to that set for the interactive shell / terminal.
The interactive shell / terminal may include or source from other scripts on startup - for example it may have run code in ~/.bashrc, ~/.login, ~/.profile, ... meaning that PATH declared inside interactive shell is not same as PATH presented to Java app when you launched it.
Hence you see terminal show PATH has /usr/local/bin:
MacBook-Air-2:~ inDiscover$ echo $PATH
/Users/mymac/anaconda/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
But Java says no /usr/local/bin in PATH:
System.out.println("PATH="+System.getenv("PATH"));
/usr/bin:/usr/sbin:/sbin
So to fix your problem you could make java use absolute path to run the app wkhtmltopdf:
Arrays.asList("wkhtmltopdf" -> Arrays.asList("/usr/local/bin/wkhtmltopdf" ...
OR you could make java launch your shell / terminal so the terminal sources its env scripts as normal and runs the command:
# Confirm which shell your Terminal uses:
echo $SHELL
If you have say SHELL=/bin/bash you can run /bin/bash from java and let it work out where wkhtmltopdf is:
Arrays.asList("wkhtmltopdf" -> Arrays.asList("/bin/bash", "-c", "wkhtmltopdf" ...
OR if you have a script say runMyApp.sh to launch your java app, set the PATH before java yourclass.Name,
export PATH=/usr/local/bin:$PATH
java yourclass.Name
OR if you have a script say runMyApp.sh to launch your java app, make that it sources the same profile environment as your Terminal does. This depends on the SHELL but for some systems could be something like:
#!/bin/bash
# Load env from current user - "source" and "." may or may not work in the SHELL you are using:
source ~/.bashrc
# OR maybe other shell
. ~/.somefilerc
echo $PATH # Now hopefully includes same /usr/local/bin
java yourclass.Name
Try to add sudo in the front of wkhtmltopdf.

Writing cmd output to a file is not working with Tomcat :(

I'm using a java process to open cmd to run a command, then save the output to a text file.
ArrayList<String> commands = new ArrayList<>();
commands.add("cmd.exe");
commands.add("/c");
commands.add("cd "+System.getenv("LOGSTASH_PATH")+" && start /B cmd.exe /c \"logstash --config.test_and_exit -f "+configFileName+"\""+" > testing.txt");
ProcessBuilder builder = new ProcessBuilder(commands);
Process subProcess = builder.start();
Thread.sleep(50000);
subProcess.destroy();
This piece of code works when i try this with eclipse,But when i generate a war out of this and deploy in tomcat, it doesn't work. What could be the problem?
How to solve this?
I suspect the problem may be with the CD instruction:
Check that the LOGSTASH_PATH environment variable is available in the Tomcat process.
In case the current Tomcat directory and the LOGSTASH_PATH belong to different drives, add a /d qualifier:
"cd /d "+System.getenv("LOGSTASH_PATH")+ ...
(Tough is much better to replace the cd call by a Java call to directory(File) instead, as #nitind pointed).

Running/Sending CMD command in Java

I want to get rid of a .bat file in java and have the code post directly to CMD.
I have tried multiple variances of the below but i'm not getting it right.
The .bat file contains the following:
CD C:\"Program Files (x86)"\"UiPath Platform"\UIRobot.exe -file C:\ProgramData\UiPath\Projects\DM9\Main.xaml
I would like Java to post this directly to CMD instead.
Currently my code looks like:
String test = in.readUTF();
if (test.equals("Start"))
{
String[] command = {"cmd.exe", "/C", "Start", "C:Unipath\\start.bat"};
Process child = Runtime.getRuntime().exec(command);
}
Any advice?
Thanks in advance.
You haven't actually specified the problem, but I can run a batch file no problem without the cmd.exe argument. i.e. batch file
echo off
echo %1
can be run using
String[] command = {"test.bat", "HELLO"};
Process proc = Runtime.getRuntime().exec(command);
So I suspect your problem lies either with the cmd.exe argument or with the fact that your batch command doesn't seem to be valid
CD C:\"Program Files (x86)"\"UiPath Platform"\UIRobot.exe -file C:\ProgramData\UiPath\Projects\DM9\Main.xaml
Is this a Change Directory command with three arguments, a filename, a -file then another filename. Have you tested the batch file by itself?
Refer to this link for detailed example: Run Dos commands using JAVA
Courtesy of #akshay-pethani's answer in below question.
How do I execute Windows commands in Java?

Execute cmd commands from inside a java program

I am trying to execute cmd commands inside a java program using the following code
String command = "clingo F:\\clingo\\food1.lp F:\\clingo\\fooddata.txt"
+ " 0"+" >>F:\\clingo\\foodout.txt";
Process p1 = Runtime.getRuntime().exec(command);
This is executing in java without any exceptions, but the actual command is not running. If the command is run it should create text file foodout.txt in the location mentioned. Nothing is happening.
The actual command is
clingo food1.lp fooddata.txt 0 >>foodout.txt
clingo is a windows executable program. This command works fine when run in command prompt. I want to run this inside java program from click of a button. I have set environment variable for clingo. Clingo and this java project are in the same directory.
Before this i tried below code
String[] command = {"clingo", "food1.lp","fooddata.txt", "0", ">>foodout.txt"};
ProcessBuilder builder = new ProcessBuilder(command);
builder.directory(new File(WorkingDirectoryArea.getText()));
Process process = builder.start();
where Workingdirectoryarea contains the directory location for commands to be run. This code does nothing.
Can someone guide me or provide code sample on how to run the cmd command inside this java program. I am using Netbeans IDE. Thanks.
you said your command works with a command prompt. OK. If you look closely, the command window has a path entry (cmd= echo %PATH%). That's the difference between executing a command in a command window and executing a java process. You have 2 options.
1. Add the path to the process.
2. Add the path to the clingo command (i.e. "f:\path\clingo.exe ...)
Item 1 is especially needed when using dos commands. To add a path environment:
Runtime.getRuntime().exec not finding file in java environment
You are redirecting standard output to a file. This is not part of the command nor a command line parameter. Is the command interpreter that handles this.
You must invoke the command interpreter to run your program like this:
String command = "cmd /c clingo F:\\clingo\\food1.lp F:\\clingo\\fooddata.txt"
+ " 0"+" >>F:\\clingo\\foodout.txt";
Process p1 = Runtime.getRuntime().exec(command);
Note the cmd /cpart which invokes the command interpreter to run your command like you would do on a Windows terminal.
On Linux it would be sh -c or whatever shell you like.
EDIT 1
When running the command, clingo.exe must be in your path or it must be in the default directory for the Java interpreter. If not, you should give the full path to the executable, like this:
String command = "cmd /c F:\\clingo\\clingo F:\\clingo\\food1.lp F:\\clingo\\fooddata.txt"
+ " 0"+" >>F:\\clingo\\foodout.txt";
Try to run
F:\\clingo\\clingo F:\\clingo\\food1.lp F:\\clingo\\fooddata.txt 0 >> F:\\clingo\\foodout.txt
at a Windows prompt and see if it works as expected. If it works it also should work when run from a Java program. Please, replace the clingo path with the right one for your environment.
Your command must be like this: java -jar yourExecuteable.jar yourParameter
In your case: java -jar clingo.jar food1.lp fooddata.txt 0 >>foodout.txt

How to execute my own commands on terminal from java File

I am trying to make a eclipse project in Java to launch commands with some buttons. The libraries of Ros fuerte (These ones i want to use) are correctly installed and concretly i am trying to launch a ros command from a Java File using:
String cmd = "roscore";
Runtime rt = Runtime.getRuntime();
Process p = rt.exec(cmd);
If i launch this command from a current terminal it works, but if i do it from the java file i have a problem because the terminal doesnt recognize the command.
java.io.IOException: Cannot run program "roscore": java.io.IOException: error=2, No such file or directory
at java.lang.ProcessBuilder.start(ProcessBuilder.java:475)
at java.lang.Runtime.exec(Runtime.java:610)
at java.lang.Runtime.exec(Runtime.java:448)
at java.lang.Runtime.exec(Runtime.java:345)
at LaunchTerminal.main(LaunchTerminal.java:24)
I think that i need to add some path or similar but i dont find the information. Does anybody know how to do it?
Thank u.
only normal commands are possible to execute like rm or cd ... al others must be referenced with full path of context
Do the following if you are using the groovy distribution:
String cmd = "source /opt/ros/groovy/setup.bash && roscore";

Categories

Resources