Calling a Python app from Java - java

I am unfamiliar of the way how to use Jython to call a Python app from my Java (Spring Boot) Application, so I usually use the following method to retrieve the json response from the python app: (the Java app is running on a CentOS7 environment)
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec("python test.py");
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
log.debug(line + "\n");
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
That is helpful when I call any python application, which gives me back nothing but a single line, like {"status":"ok"}
But if it gives me back multiple lines, or an exception after giving me back the json answer I expect, my Java application returns an empty string, like if it wouldn't get any response back from the Python app.
Though when I run the same command via terminal, I get the multiple line answers.
So I wonder if the issue is with my code? Am I missing something to see here which obstructs me to have multiple lines from the answer? I need the answer regardless of how many lines I get back.

Your methode has nothing to do with Jython or Python in general. You are just starting a new Process and reading its standard output.
It just happens that in your case this is a python app and the output should be json (but could be anything).
If I understand you correctly, you only want to "accept" one line json outputs from your python process. Try this:
public String getOutputFromProcess() {
//Use StringBuilder instead of Buffer if you dont need the thread safety
StringBuilder output = new StringBuilder();
StringBuilder error = new StringBuilder();
//Removed error handling for simplicity
Process p = Runtime.getRuntime().exec("python test.py");
p.waitFor(); //Maybe this needs to be moved after the reading part
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
//You also need to read the standard error output
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
String line = "";
int counter = 0;
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
counter++;
}
while ((line = stdError.readLine()) != null) {
error.append(line + "\n");
}
//Check if we have read more than one line
//If yes return empty string or null etc.
if(counter > 1) return "";
//Here you should check if this is a valid json string
return output.toString();
}
In general I would suggest you have a look at Jython and call the python function directly. If you want to use your methode, have a look at ProcessBuilder.

So apparently the solution in my case was to create a shell script serving as a bridge between the Java and the Python app.
For some reason this python app I want to use simply doesn't return with any answer when there would be multiple lines.
There are several workaround on this, probably the best to go with is Jython, as #HectorLector advised.
Also it works when I create a shell script which calls the Python app, and my Java app calls the shell script instead of the Python file.
Another solution is to run the command with an additional > output.txt
in the command, which will make sure that the called process' output will flow into the specified file. Then later the application can retrieve the data from that file, and delete it when it is not necessary anymore.

Related

Identifying Operations of a Process

I'm developing a system monitoring tool which shows processes and their operations. I was able to retrieve process list process id etc by executing tasklist.exe. Here is what i tried.
try {
String line;
Process p = Runtime.getRuntime().exec(System.getenv("windir") + "\\system32\\" + "tasklist.exe");
BufferedReader input
= new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line); //<-- Parse data here.
}
input.close();
} catch (Exception err) {
err.printStackTrace();
}
My Requirement is to find Operations of this process.
Please refer sample screenshot.
I've tried java api doc. There are 6 methods mentioned in api. But none of them giving information about sub processes or operations in a Process.
Just like in attached image i want to retrieve operation list of a task.
Any help is highly appreciated.
Thank you.
This cannot be done using Java. There is no method for this.

calling stand alone java application from a java servlet

I am new to Java. I have been trying to do some Java application development.
I have created a stand alone Java application. Its a basic calculator application which does basic operations like addition, subtraction, multiplication and division. It is developed using Java swings and AWT.Its GUI
I have a Java servlet application which takes two inputs (numbers) from the user and returns back the result. Basically whatever basic calculator does, the servlet can do such operations on the numbers and return back the result to the client which is a web browser. (client is just an HTML file)
Instead of servlet doing the operations, I want to invoke(from the servlet) stand alone application to do the operations and return back the result to servlet. Then servlet returns back the result to client. Is it possible to call stand alone java application from a servlet. If so what are the different ways?
To invoke your application,you have to write bat or sh file based on your operating system.
-- invoke the command by using processbuilder
-- sample code match with your requirement
if (osname.indexOf("nux") >= 0 || osname.indexOf("nix") >= 0)
{
//for sending request to sh file
filePath = request.getSession().getServletContext().getRealPath("")+"/WEB-INF/classes/";
cmdList.add("sh");
cmdList.add("callDesktopApp.sh");
cmdList.add(path);
}
else
{
// for windows
String jrePath="";
String f="C:/Windows/SysWOW64";
if(new File(f).exists())
{
jrePath="C:\\Program Files (x86)\\Java\\jre6\\bin\\java";
jrePath="\""+jrePath+"\"";
}
else
{
jrePath="C:\\Program Files\\Java\\jre6\\bin\\java";
jrePath="\""+jrePath+"\"";
}
filePath = request.getSession().getServletContext().getRealPath("")+"\\WEB-INF\\classes\\";
cmdList.add("cmd");
cmdList.add("/c");
cmdList.add("callDesktopApp.bat");
cmdList.add(path);
cmdList.add(jrePath);
}
pb=new ProcessBuilder(cmdList);
pb.directory(new File(filePath));
process = pb.start();
//Read out dir output
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
is.close();
isr.close();
}
Hope it may help you.

How to find the list of only application running in windows?

I want to find the list of all application running in windows.The list should consist of application only and not all process
Process p = Runtime.getRuntime().exec
(System.getenv("windir") +"\\system32\\"+"tasklist.exe");
try (BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
while ((line = input.readLine()) != null) {
System.out.println(line); //<-- Parse data here.
}
}
An application is a program which you interact with on the desktop. This is what you spend almost all of your time using on the computer. Internet explorer, microsoft word, iTunes, skype - they are all applications.
A process is an instance of a particular executable (.exe program file) running. A given application may have several processes running simultaneously. For example, some modern browsers such as google chrome run several processes at once, with each tab actually being a separate instance/process of the same executable.
So, what you could do is:
try {
String line;
Process p = Runtime.getRuntime().exec(System.getenv("windir") +"\\system32\\"+"tasklist.exe");
BufferedReader input =
new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
//<-- Parse the line and insert into a set using image field as a key
}
input.close();
} catch (Exception err) {
err.printStackTrace();
} // do not forget to handle exceptions!
you will need some filtering though, for example inserting the result of the tasklist command into a Set by the name in the 'image' column because they are all associated with the same app:

Reading InputStream from Java Interactive Process using ProcessBuilder

I am trying to run an interactive executable from Java application using ProcessBuilder; it's supposed to take input, produce output and then wait for the next input. The main problem here with Input/Output streams. I send an input and get nothing. Here is the code:
private static Process process;
private static BufferedReader result;
private static PrintWriter input;
process = new ProcessBuilder("compile-lm", lmFile.toString(), " --score yes").redirectErrorStream(true).start();
input = new PrintWriter(new OutputStreamWriter(process.getOutputStream()), true);
input.println(message);
System.out.println(message);
result = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = new String();
while ((line = result.readLine()) != null)
{
/* Some processing for the read line */
System.out.println("output:\t" + line);
}
I have tried your code it works fine there is no problem with the code. I think that the problem with the command that you are trying to execute ( it returns nothing ). try to change parameters or even change the entire command to test. and if you can execute the comand in other place ( terminal for example try it and see the output with the same parameters )
I have used a similar setup many times over but can not find a working copy right now :( My first instinct though is to move the line where you initialise the reader (result variable) to before the one where you send the command out to the process (input.println(message)).
Try closing the output stream to the process. Basically you're at the mercy of whatever buffering is happening in the output side of the child process.

Communicating with C++ process from Java

First, I saw a few Q's about this issue in the site, but didn't see any answer that solve my problem.
I have a program written in Java and it calls a cmd program written in C++. (this is an assumption since I don't have the actual source) I know the expected I/O of the C++ program, in the cmd it is two lines of output and then it waits for string input.
I know that the first output line of the program is through error stream, and I receive it properly (this is expected), but I don't get the second line in error or input stream.
I tried to write to the program right after the first line ( the error line) and didn't got stuck, but there was no response.
I tried using 3 different threads, for each stream, but again, nothing was received in input/error stream after the first line, and the program didn't respond to writing through output stream.
My initializers are:
Process p = Runtime.getRuntime().exec("c:\\my_prog.exe");
BufferedReader err = new BufferedReader(new InputStreamReader(p.getErrorStream()));
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedWriter output = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
Is it possible at all or maybe it depends on the C++ program?
Thanks,
Binyamin
If you want to call native applications like C and C++ from Java, you need to use JNI.
I would suggest to put the input in the program when it has started, it will propably use that as input when it wants it.
Here is how I execute any command line in Java. This command line may execute any program:
private String executionCommandLine(final String cmd) {
StringBuilder returnContent = new StringBuilder();
Process pr;
try {
Runtime rt = Runtime.getRuntime();
pr = rt.exec(cmd);
BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line = null;
while ((line = input.readLine()) != null) {
returnContent.append(line);
}
input.close();
LOG.debug(returnContent.toString());
// return the exit code
pr.waitFor();
} catch (IOException e) {
LOG.error(e.getMessage());
returnContent = new StringBuilder();
} catch (InterruptedException e) {
LOG.error(e.getMessage());
returnContent = new StringBuilder();
}
return returnContent.toString();
}

Categories

Resources