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.
Related
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.
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:
I have a computer algebra program (called Reduce) that works in the shell in an interactive manner: launch Reduce in the shell, then you can define variables, compute this and that, and what not. Reduce prints the output into the shell. My idea is that I want to build a frontend for this text-based program that evaluates its output and converts it into a nice LaTeX style formula. For this I want to use Java.
I can start Reduce via exec(). But how can I emulate text input to the opened shell, and how can I read back what Reduce writes into the shell?
Thanks
Jens
Edit 1: Current Code
// get the shell
Runtime rt = Runtime.getRuntime();
// execute reduce
String[] commands = {"D:/Programme/Reduce/reduce.com", "", ""};
Process proc = null;
try {
proc = rt.exec(commands);
} catch (Exception e) {
System.out.println("Error!\n");
}
// get the associated input / output / error streams
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedWriter stdOutput = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
String s = null;
try {
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
} catch (Exception e) {
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
try {
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
} catch (Exception e) {
}
You need to get the streams associated with the process including the InputStream, OutputStream, and ErrorStream. You then can send messages to the process via the OutputStream and then read info from the process via the InputStream and the ErrorStream.
From some code of mine:
final ProcessBuilder pBuilder = new ProcessBuilder(TEST_PROCESS_ARRAY);
final Process proc = pBuilder.start();
procInputStream = proc.getInputStream();
errorStream = proc.getErrorStream();
errorSBuffer = new StringBuffer();
streamGobblerSb = new StreamGobblerSb(errorStream, "Autoit Error", errorSBuffer);
new Thread(streamGobblerSb).start();
final Scanner scan = new Scanner(procInputStream);
You may want to look into using the Process class.
http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html
I believe you may be able to start the process, and then use getOutputStream() to feed commands into the process.
While this is not strictly an answer, I discovered that it is more convenient for me to stick with PHP's function proc_open(). That way I can include the output directly in the frontend and do not need to worry about the communication between my Java program and the html frontend.
For everybody who wants to stick to the Java method: the article http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html is a good reference.
Suppose I have a java bean named "Mainbean", which is used to handle a request from web page.
I want to create a process "proc" in this bean, and get the output of proc, return them to the web page asynchronously, and show them in a inputTextArea in JSF.
Since "proc" may has so many lines of output, I want to return them line by line and real-time, but not show all them after the process finished.
I used following code to create a process and try to get the output. But it seems like the process failed to exit normally, cause the exit value always be -1.
builder = new ProcessBuilder("java", "-Xms1024m","-Xmx1024m","-Xss65536k","-cp ",spaceMaker,"SmartBridge", solution," ",this.specFile,"1000000");
proc = builder.start();
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
returnValue = proc.waitFor();
while ((line = br.readLine()) != null) {
// Outputs your process execution
System.out.println(line);
this.metaOutput = this.metaOutput.concat(line);
exit = proc.exitValue();
if (exit == 0) {
// Process finished
break;
}
return output;
}
And in JSF page, I use following code:
<h:form>
<h:inputTextarea id="processOutput" value="#{mainBean.metaOutput}" cols="80" rows="20">
<f:ajax render="processOutput"/>
</h:inputTextarea>
</h:form>
My question is: How can I use these technology to meet my requirement in high-level?
Of course, code examples will help me definitely.
If you are looking for Reverse ajax kind of response.
You could use PRIMEFACES PUSH reverse ajax Technology.
Here is the link. PrimPush
Im facing this strange issue of not being able to execute a simple "whoami" unix command on a AIX server. I have a webapplication that is deployed on an AIX server. Now I want to see under which WAS user my webapplication is currently running. So I added the below code:
public String whoami() throws Exception {
Process p = Runtime.getRuntime().exec("whoami");
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
String output = "";
while ((line = in.readLine()) != null) {
//System.out.println(line);
output += line;
}
in.close();
p.destroy();
return output;
}
}
The above code is added in a jar file which is referred by a JSP. The JSP has to receive the output of the code above and it displays the WAS User name. But when i deploy the webapplication on the server and try to observe the output, im getting an error message like
Error 500: access denied (java.io.FilePermission <> execute)
However, When I remove the above code and run my webapplication, everything runs fine. What wron am i doing here. Did I miss doing anything? Please help. This is the first time im working on UNIX
It looks like your web server has been configured with a Java security policy that prohibits executing external applications.
See http://java.sun.com/developer/onlineTraining/Programming/JDCBook/appA.html for information about Java Security Policies, and the documentation for your web server.
You will need to supply (or edit) a policy file to contain something like:
grant {
permission java.io.FilePermission
"/usr/bin/whoami", "execute";
};
Just out of curiosity
Have you considered to use:
user.name
System property in Java?
AFAIK whoami is a shell command and Runtime#exec() executes programs only.
you can try Runtime.getRuntime().exec(new String[]{"sh","-c","whoami"}) to call sh and let it execute whoami
another thing: do you need to destroy the process after reading?
You can use the ProcessBuilder class instead of getRuntime().exec("whoami").
Here is sample code
import java.io.*;
import java.util.*;
public class DoProcessBuilder {
public static void main(String args[]) throws IOException {
if (args.length <= 0) {
System.err.println("Need command to run");
System.exit(-1);
}
Process process = new ProcessBuilder(args).start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
System.out.printf("Output of running %s is:", Arrays.toString(args));
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
}