Running Background java program - java

I am trying to make a java application which runs another java program at certain point of event occurrence . As I have to run this process in background I am using & symbol . This is part of the application .
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static void runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
// pro.waitFor();
System.out.println(command + " exitValue() " + pro.exitValue());
}
runProcess("javac test2.java");
runProcess("java test2 "+id+" "+pass+" "+choice+" &");//Id,pass,choice are arguments of java program
The problem I am facing is If I am print the lines os that program my actual application does not move to next part until my background process is over which takes long time and if I omit these output lines then the background process exits and gives this error :
java.lang.IllegalThreadStateException: process hasn't exited
And If I use pro.waitFor(); then again the first problem .What should I do?

Related

Java Process getting stopped when run in background in linux

I have the below lines of code `
private String build(String command) {
ShellExecutable obj = new ShellExecutable();
String output = obj.executeCommand(command);
return output;
}
private String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
String[] cmdarray = { "bash", "-c", command };
try {
System.out.println("Before Command Execution in Bash..& command is: " + command);
p = Runtime.getRuntime().exec(cmdarray);
System.out.println("After Command execution in Bash & Before waitFor..");
p.waitFor();
System.out.println("After wait for: " + p.exitValue());
System.out.println("After wait for: " + p.isAlive());
System.out.println("After Command execution in Bash..");
if (p.getInputStream() != null) {
System.out.println("Input Stream is present");
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
}
if (p.getErrorStream() != null) {
System.out.println("Error Stream is present");
BufferedReader errorReader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
String errorLine = "";
while ((errorLine = errorReader.readLine()) != null) {
output.append(errorLine + "\n");
}
}
} catch (Exception e) {
System.out.println("Exception Occured:" + e.getLocalizedMessage() + "Message is:" + e.getMessage());
}
return output.toString();
}
`
I am trying to run this as a foreground process in Linux, it works brilliant. But, when I try to run the same as a background process using nohup the service is stopping. I found similar kind of issues on stack overflow but I couldn't't figure out the solution for this particular case.
For the above code the output I am getting is as follows:
Called listApps...
Before Command Execution in Bash..& command is: xxxxxxxx
After Command execution in Bash & Before waitFor..
[1]+ Stopped nohup java -jar ReadingShell-0.0.1-SNAPSHOT-jar-with-dependencies.jar
I am not getting any exception in the above code, its just stopping without displaying anything. But, when I try displaying p.exitValue() before p.waitFor(), I printed the stacktrace, it is as follows,
java.lang.IllegalThreadStateException: process hasn't exited
at java.lang.UNIXProcess.exitValue(UNIXProcess.java:424)
at org.monitoring.ReadingShell.ShellExecutable.executeCommand(ShellExecutable.java:101)
at org.monitoring.ReadingShell.ShellExecutable.build(ShellExecutable.java:82)
at org.monitoring.ReadingShell.ShellExecutable.getApplicationList(ShellExecutable.java:46)
at spark.RouteImpl$1.handle(RouteImpl.java:72)
at spark.http.matching.Routes.execute(Routes.java:61)
at spark.http.matching.MatcherFilter.doFilter(MatcherFilter.java:130)
at spark.embeddedserver.jetty.JettyHandler.doHandle(JettyHandler.java:50)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1568)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.Server.handle(Server.java:564)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:317)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:110)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
at org.eclipse.jetty.util.thread.Invocable.invokePreferred(Invocable.java:128)
at org.eclipse.jetty.util.thread.Invocable$InvocableExecutor.invoke(Invocable.java:222)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:294)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:126)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:672)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:590)
at java.lang.Thread.run(Thread.java:745)
You have to read the output streams before you wait for the end of the child process. Otherwise if the child writes more than a buffer's worth (512B? 4K?) to one of the streams, it will be made to wait until something reads and empties the buffer. But this won't happen since your parent process is already executing waitFor().
So, you have to create two threads to read these output streams, and start them before calling waitFor().
By reading the opendjk source code for UnixProcess we see the following
public synchronized int waitFor() throws InterruptedException {
while (!hasExited) {
wait();
}
return exitcode;
}
public synchronized int exitValue() {
if (!hasExited) {
throw new IllegalThreadStateException("process hasn't exited");
}
return exitcode;
}
hasExited is never reset in the file so logically exitValue() cannot throw after waitFor() is called. (Unless it is interrupted)
Something must be different when you run it than in the code your question has. A minimal complete example class displaying the issue so we can reproduce it would help.
I had a similar issue. The jar file would be fine if ran in the foreground, but stop when executed in nohup with the process/job going into Stopped.
Figured out that nohup will go into stopped if any of the inner scripts try to read from the terminal - see the post here
I used tmux to solve this as suggested by this thread

Compiling Java program with VBScripts? (NetBeans)

I have a Java program created that runs VBSscripts after button clicks.
examplescript.vbs
How do I compile these vbs files and then call them to run in the program code? I've been troubleshooting for several days and can't find an answer. Once again I need to be able to run these scripts, at one point I had an input stream created to it but couldn't get it as a vbs file. Hopefully I'm overlooking something here
Edit:
This is what I currently have. With this code I receive the error "Windows Script Host. There is no script extension for file extension ".BufferedInputStream#4e34904""
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream("hello.vbs");
try {
Runtime.getRuntime().exec("wscript " + is);
}
catch( IOException e ) {
System.out.println(e);
System.exit(0);
}
System.out.print(is);
You can run your VBScript as below.
Runtime.getRuntime().exec( "wscript path/to/examplescript.vbs" );
As already mentioned, VBScript is a script and doesn't need compiling. If you want to run code written in VBScript then you can do it this way:
This example uses VBScript to get the Motherboard Serial Number of a computer that is running Microsoft Windows:
try {
// Create a temporary script file named MBSerialxxxxxxxx.vbs
File file = File.createTempFile("MBSerial",".vbs");
// Delete the temporary file when virtual machines terminates
file.deleteOnExit();
try (FileWriter fw = new java.io.FileWriter(file)) {
String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
+ "Set colItems = objWMIService.ExecQuery _ \n"
+ " (\"Select * from Win32_BaseBoard\") \n"
+ "For Each objItem in colItems \n"
+ " Wscript.Echo objItem.SerialNumber \n"
+ " exit for ' do the first cpu only! \n"
+ "Next \n";
fw.write(vbs);
}
// Run the VBScript file....
Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
// Read in any output to the command window.
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = input.readLine()) != null) {
// display the output...
System.out.println(line.trim());
}
input.close();
}
catch(IOException e){
e.printStackTrace();
}

How to execute a java program from another java program in eclipse

I'm trying to run a java program, called Test.java from another java program Demo.java. Both programs are in the same package, I'm doing something like this:
try{
System.out.println("Executing another client");
runProcess("javac -cp gridgain-examples C:/Users/Desktop/gridgain/examples/src/main/java/apache/ignite/schemas/Test.java");
System.out.println("******");
runProcess("java -cp gridgain-examples C:/Users/Desktop/gridgain/examples/src/main/java/apache/ignite/schemas/Test.java");
} catch(Exception e) {
e.printStackTrace();
}
And the runProcess and printlines methods are:
private static void printLines(String cmd, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(cmd + " " + line);
}
}
private static void runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
System.out.println(command + " exitValue() " + pro.exitValue());
}
But it's not executing. Please tell me how to do it?
Have you tried "C:\Users\Desktop\gridgain\examples\src\main\java\apache\ignite\schemas\Test.java"?
I'd comment this but don't have the reputation :(

Running Java Program in another Program gives error

I want to execute another Java program in my program. I have taken reference from here. For testing I have pasted same code as accepted answer shows.I have passed a simple HelloWorld program. Program compiles perfectly but gives Main class not found error.
Here is my code:
Server.java
public static void main(String args[]) {
try {
runProcess("javac D:\\HelloWorld.java");
runProcess("java D:\\HelloWorld");
} catch (Exception e) {
e.printStackTrace();
}
}
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static void runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
System.out.println(command + " exitValue() " + pro.exitValue());
}
HelloWorld.java:
`public static void main(String args[]){
System.out.println("Hello World!");
}`
Output:
exitValue() 0 for javac
stderr: Error: Could not find or load main class D:\HelloWorld
exitValue() 1 for java
Compiling and running same program on CMD or IDE gives perfect output.
You want to start main from HelloWorld class? I think, in that case you should run program something like this:
java -cp 'D:\' HelloWorld
So, you need to specify ClassPath - 'D:\' and entry class name from classpath - HelloWorld.
Why try to do things the hard way? Use the inline compiler API and then simply execute the main() method on your new class after loading the class itself into your root classloader.

How to change path while running java file?

I am trying to run a java file through another java program . this is my code:
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static void runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
System.out.println(command + " exitValue() " + pro.exitValue());
}
public static void main(String[] args) {
String[] credentials=new String[4];int k=0;
for (String s: args) {
System.out.println(s);
credentials[k]=s;k++;
if(k==4)
break;
}
try {
//runProcess("javac test2.java");
runProcess("java test2 "+credentials[0]+" "+credentials[1]+" "+credentials[2]+" "+credentials[3]+" ");
} catch (Exception e) {
e.printStackTrace();
}System.out.println("hI");
}
The problem is I have kept both the files(which I execute and the one which is executed by that file) in same folder but when I run this file it displays class not found error.. for test2.java and it probably due to the fact that it searches the class file test2.class in some other folder . what should I do?
my file structure:
x/y/Laj.java
x/y/test2.java
and it seaches the class file in x folder?
Use
Runtime.getRuntime().exec(command, null, workingDir);
where workingDir is :
workingDir- the working directory of the subprocess, or null if the subprocess should inherit the working directory of the current process.
If you run the first program using
java x.y.Laj
then you should change the line where you compose the command:
runProcess("java x.y.test2 "+credentials[0]+...
** Later **
Since the x.y is just a red herring, try setting the system property:
runProcess("java -Djava.class.path=\"/.../x/y\" " + credentials[0]+...
For production (start of Laj not from an IDE) consider setting CLASSPATH so that all class files can be found via the class path.

Categories

Resources