I've been working on some web project and one of its requests execute command line using Java Process.
This is the method.
#ResponseBody
#RequestMapping(value = "/startTest", method = RequestMethod.POST)
public String startTest(int test_id) {
...
String cmd = "..."
ProcessUtil pu = new ProcessUtil();
try {
pu.execute(cmd);
File file = new File(System.getProperty("user.dir")
+ "\\datas\\cypress\\videos\\examples\\main.spec.js.mp4");
File fileToMove = new File(
".\\\\datas\\\\results\\" + uitest.getTest_filename() + ".mp4");
file.renameTo(fileToMove);
return "success";
} catch (Exception e) {
return "fail";
}
}
And Here is the ProcessUtil.java
public class ProcessUtil {
public static void execute(String cmd) {
Process process = null;
Runtime runtime = Runtime.getRuntime();
StringBuffer successOutput = new StringBuffer();
StringBuffer errorOutput = new StringBuffer();
BufferedReader successBufferReader = null;
BufferedReader errorBufferReader = null;
String msg = null;
List<String> cmdList = new ArrayList<String>();
if (System.getProperty("os.name").indexOf("Windows") > -1) {
cmdList.add("cmd");
cmdList.add("/c");
} else {
cmdList.add("/bin/sh");
cmdList.add("-c");
}
cmdList.add(cmd);
String[] array = cmdList.toArray(new String[cmdList.size()]);
try {
process = runtime.exec(array);
successBufferReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
while ((msg = successBufferReader.readLine()) != null) {
successOutput.append(msg + System.getProperty("line.separator"));
}
errorBufferReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
while ((msg = errorBufferReader.readLine()) != null) {
errorOutput.append(msg + System.getProperty("line.separator"));
}
process.waitFor();
if (process.exitValue() == 0) {
System.out.println("success!");
System.out.println(successOutput.toString());
} else {
System.out.println("fail...");
System.out.println(successOutput.toString());
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
try {
process.destroy();
if (successBufferReader != null)
successBufferReader.close();
if (errorBufferReader != null)
errorBufferReader.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
The problem that I'm facing is when I open two Windows command windows and execute simultaneously it seemingly works fine. However, when I run that 'startTest' method by requesting to my server simultaneously, it pushes my CPU and RAM to nearly 100% and results seemed odd. I don't know much about multi-threading, but I guess I should execute the command via multiple windows(I think my commands were executed in the same environment and they crashed each other...). Please give me some advice to resolve this problem... Thank you in advance.
Related
I made a client-server application where the server has to send a list of emails to the client, which after load that into a ListView gives the possibility, through a menuBar, to delete them. In the client all these operations are made in the Data Model (I followed the MVC pattern). This is the server:
class ThreadedEchoHandler implements Runnable {
private Socket incoming;
private String nomeAccount = "";
public void run() {
try {
incoming = s.accept();
} catch (IOException ex) {
System.out.println("Unable to accept requests");
}
contenutoTextArea.append("Connected from: " + incoming.getLocalAddress() + "\n");
textarea.setText(contenutoTextArea.toString());
try {
//PHASE 1: The server receives the email
try {
BufferedReader in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
nomeAccount = in.readLine();
} catch (IOException ex) {
System.out.println("Not works");
}
//PHASE 2: I'm getting all the emails from the files
File dir = new File("src/server/" + nomeAccount);
String[] tmp = new String[100];
int i = 0;
for (File file : dir.listFiles()) {
if (file.isFile() && !(file.getName().equals(".DS_Store"))) {
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
while ((line = br.readLine()) != null) {
tmp[i++] = line;
}
} catch (IOException ex) {
System.out.println("Cannot read from file");
}
}
}
//PHASE 3: The server sends the ArrayList to the client
PrintWriter out = new PrintWriter(incoming.getOutputStream(), true);
for (int j = 0; j < i; j++) {
out.println(tmp[j]); // send the strings to the client
}
} catch (IOException ex) {
System.out.println("Cannot send the strings to the client");
}
//PHASE 4: Here I loop and wait for the client choise
BufferedReader in;
String op;
try {
in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
while ((op = in.readLine()) != null) {
if (op.equals("Elimina")) {
String tmp = in.readLine();
File file = new File("src/server/" + nomeAccount + "/" + tmp + ".txt");
file.delete();
} else if (op.equals("Invia")) {
//...
} else {
//...
}
}
} catch (IOException ex) {
System.out.println("Non so");
} finally {
try {
incoming.close();
} catch (IOException ex) {
System.out.println("Cannot closing the socket");
}
}
}
}
These are the methods of the client:
public void loadData() throws IOException, ClassNotFoundException, ParseException {
try {
s = new Socket("127.0.0.1", 5000);
ArrayList<Email> email = new ArrayList<Email>();
DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
Date data;
/* PHASE 1: The client sends a string to the server */
//try {
PrintWriter out = new PrintWriter(s.getOutputStream(), true);
out.println(account); // send the account name to server
/* PHASE 2: The client receives the ArrayList with the emails */
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line;
String message[] = new String[5];
for (int j=0; (line = in.readLine()) != null;) {
message[j++] = line;
if (j==5) {
data = format.parse(message[3]);
email.add(new Email((Integer.parseInt(message[0])), message[1], account, message[2], message[4], data));
j=0;
}
}
//Casting the arrayList
emailList = FXCollections.observableArrayList(email);
//Sorting the emails
Collections.sort(emailList, (Email o1, Email o2) -> {
if (o1.getData() == null || o2.getData() == null) {
return 0;
}
return o1.getData().compareTo(o2.getData());
});
/*} finally {
s.close();*/
//}
} catch (SocketException se) {
emailList.setAll(null, null);
}
}
public void deleteMail(Email da_elim) throws IOException {
int id_del = da_elim.getID();
emailList.remove(da_elim);
PrintWriter out = new PrintWriter(s.getOutputStream(), true);
out.println("Elimina");
out.println(id_del);
}
The PHASE 1, 2, 3 of the Server are for the upload of the emails, and work with the loadData() method. Without the PHASE 4 the program works. Now, if I write that loop, the GUI of the client doesn't load and I cannot press on the DELETE button (which should make the input to innescate something (in this the elimination of the file) into that loop. Why the client doesn't load even if they are two different threads? And why without that loop it works?
EDIT: with the Listener class implemented but still doesn't works
//PHASE 4: Here I loop and wait for the client choise
BufferedReader in;
String op;
try {
in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
/*while ((op = in.readLine()) != null) {
System.out.println("OP: " + op);
if (op.equals("Elimina")) {
String tmp = in.readLine();
contenutoTextArea.append("Ho eliminato la mail ").append(tmp).append(" \n");
textarea.setText(contenutoTextArea.toString());
File file = new File("src/server/" + nomeAccount + "/" + tmp + ".txt");
file.delete();
}
}*/
Listener lis = new Listener(in, new LinkedBlockingQueue<String>());
lis.run();
System.out.println("bbbbb");
} catch (IOException ex) {
System.out.println("Unable to read messages");
} finally {
try {
incoming.close();
} catch (IOException ex) {
System.out.println("Cannot close the socket");
}
}
I think you should run jvisualvm (it's a tool installed with jdk in /bin/ location of your jdk) and look for that Thread lifecycle you create on server. Also check if your Thread don't go through the code and just ends his life skipping waiting for client.
Is this Thread somehow connected with client? Because you cannot run client App. Are they separated? Another think that came to my mind is using
Platform.runLater(()->{
});
if your client GUI is in JavaFX. Use it if you are creating GUI, changing values in fields and anything you do on your GUI. Maybe your server is waiting for user response and after that GUI is built? Which causes that you can't press DELETE button.
I'm not currently able to comment, so I can't ask for clarification, but I think I'm correctly interpreting what's wrong. "The program hangs when it enters a loop that waits for input from two controllers". Assuming I got that part right, the most likely culprit would be that buffered reader is hanging indefinitely because its not receiving input. When I first ran into this issue, I threw it inside its own "receiver" class and used a Queue to bus over anything it received to a loop in my main class. my code looked something like this:
import java.io.BufferedReader;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
public class Listener implements Runnable
{
private BufferedReader br;
private BlockingQueue<String> q;
private boolean shouldClose = false;
public Listener(BufferedReader br, BlockingQueue<String> q)
{
this.q = q;
this.br = br;
}
public void run()
{
loop();
System.out.println("listener has stopped");
}
public void loop()
{
String line = "";
try
{
while((line = br.readLine()) != null && !shouldClose)
{
q.put(line);
}
}
catch (IOException | InterruptedException e)
{
e.printStackTrace();
}
}
public void shutdown()
{
shouldClose = true;
}
}
apologies if I've misunderstood in any way, or missed something in your code.
I want to create an App, it can show the newest movies datas, with trailers from Movie Database
I try to connect url, with threads to search the trailers. But its load only the first 38 connect succes, but i need 60. I have no idea why.
Is anyone has?
P.S.: I am sorry my English
private Thread loadTrailers = new Thread(){
#Override
public void run(){
int counter = 0;
String str = new String("");
BufferedReader br = null;
try { // try open source site
URL url = new URL("https://api.themoviedb.org/3/movie/"+id+"/videos?api_key="+myApikey);
br = new BufferedReader(new InputStreamReader(url.openConnection().getInputStream())); // problem with openConnection()
if(br != null){
if((str = br.readLine()) != null){
String[] moviedatas = str.split("\"id\"");
for(int i = 1; i < moviedatas.length && counter < 3;++i){
Pattern isTrailer = Pattern.compile(".*Trailer.*");
Matcher matc_tr = isTrailer.matcher(moviedatas[i]);
if(matc_tr.matches()){
Pattern getKey = Pattern.compile(".*key\":\"(.*)\",\"name.*");
Matcher key = getKey.matcher(moviedatas[i]);
if(key.matches()){
links.add("https://www.youtube.com/watch?v="+key.group(1));
counter++;
}
}
}
}
}
} catch (MalformedURLException e) {
System.err.println("Invalid URL!");
} catch (IOException e) {
System.err.println("Connection failed from trailers.");
} finally {
try {
if(br != null)
br.close();
} catch (IOException e) {
System.err.println("File close not success.");
}
}
}
};
I'm fairly new to ProcessBuilder and working with threads. In it's current state I have a J-Button which starts a scheduled executor service. The scheduled executor service is used to delegate a process to one of two process builders. The application is meant to record a user conversation. During the conversation, after x minutes it creates a wav and delegates it to an available process for transcription. The problem begins when the transcription class is called. The process is started and the application runs as expected. However, the transcription process doesn't actually do anything until I exit the parent application. Only then it will begin. Checking the task manager it shows as a process but uses 0.0% of the CPU and around 238MB of memory until I exit then the two processes jump to 30%-40% and 500-1000 MB of memory. Also, I am using the .waitFor() but am using a thread to run the .waitFor() process as from what I gather it causes the application to hang. How would I go about fixing this. Sorry I am unable to provide more details but I'm new to this. Thanks in advance!
public class TranDelegator {
Future<?> futureTranOne = null;
Future<?> futureTranTwo = null;
ExecutorService transcriberOne = Executors.newFixedThreadPool(1);
ExecutorService transcriberTwo = Executors.newFixedThreadPool(1);
final Runnable transcribeChecker = new Runnable() {
public void run() {
String currentWav = null;
File inputFile = new File("C:\\convoLists/unTranscribed.txt");
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(inputFile));
} catch (FileNotFoundException e1) {
System.out.println("reader didn't initialize");
e1.printStackTrace();
}
try {
currentWav = reader.readLine();
} catch (IOException e) {
System.out.println("currentWav string issue");
e.printStackTrace();
}
try {
reader.close();
} catch (IOException e) {
System.out.println("reader couldn't close");
e.printStackTrace();
}
if(currentWav != null){
if (futureTranOne == null || futureTranOne.isDone()) {
futureTranOne = transcriberOne.submit((transcriptorOne));
}
else if (futureTranTwo == null || futureTranTwo.isDone()) {
futureTranTwo = transcriberTwo.submit((transcriptorTwo));
}
}
}
};
final Runnable transcriptorOne = new Runnable() {
public void run() {
System.out.println("ONE");
try {
String classpath = System.getProperty("java.class.path");
String path = "C:/Program Files/Java/jre7/bin/java.exe";
ProcessBuilder processBuilder = new ProcessBuilder(path, "-cp",
classpath, Transcriber.class.getName());
Process process = processBuilder.start();
try {
process.waitFor();
} catch (InterruptedException e) {
System.out.println("process.waitFor call failed");
e.printStackTrace();
}
} catch (IOException e) {
System.out.println("Unable to call transcribeConvo");
e.printStackTrace();
}
}
};
final Runnable transcriptorTwo = new Runnable() {
public void run() {
System.out.println("TWO");
try {
String classpath = System.getProperty("java.class.path");
String path = "C:/Program Files/Java/jre7/bin/java.exe";
ProcessBuilder processBuilder = new ProcessBuilder(path, "-cp",
classpath, Transcriber.class.getName());
Process process = processBuilder.start();
try {
process.waitFor();
} catch (InterruptedException e) {
System.out.println("process.waitFor call failed");
e.printStackTrace();
}
} catch (IOException e) {
System.out.println("Unable to call transcribeConvo");
e.printStackTrace();
}
}
};
}
public class Transcriber {
public static void main(String[] args) throws IOException,
UnsupportedAudioFileException {
retreiveEmpInfo();
TextoArray saveConvo = new TextoArray();
ArrayList<String> entireConvo = new ArrayList();
URL audioURL;
String currentWav = wavFinder();
ConfigReader configuration = new ConfigReader();
ArrayList<String> serverInfo = configuration
.readFromDoc("serverconfig");
while (currentWav != null) {
audioURL = new URL("file:///" + currentWav);
URL configURL = Transcriber.class.getResource("config.xml");
ConfigurationManager cm = new ConfigurationManager(configURL);
Recognizer recognizer = (Recognizer) cm.lookup("recognizer");
recognizer.allocate(); // allocate the resource necessary for the
// recognizer
System.out.println(configURL);
// configure the audio input for the recognizer
AudioFileDataSource dataSource = (AudioFileDataSource) cm
.lookup("audioFileDataSource");
dataSource.setAudioFile(audioURL, null);
// Loop until last utterance in the audio file has been decoded, in
// which case the recognizer will return null.
Result result;
while ((result = recognizer.recognize()) != null) {
String resultText = result.getBestResultNoFiller();
// System.out.println(result.toString());
Collections.addAll(entireConvo, resultText.split(" "));
}
new File(currentWav).delete();
saveConvo.Indexbuilder(serverInfo, entireConvo);
entireConvo.clear();
currentWav = wavFinder();
}
System.exit(0);
}
private static String wavFinder() throws IOException {
String currentWav = null;
int x = 1;
File inputFile = new File("C:\\convoLists/unTranscribed.txt");
File tempFile = new File("C:\\convoLists/unTranscribedtemp.txt");
BufferedReader reader = new BufferedReader(new FileReader(inputFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile));
String currentLine = null;
String newLine = System.getProperty("line.separator");
while ((currentLine = reader.readLine()) != null) {
if (x == 1) {
currentWav = currentLine;
} else {
writer.write(currentLine);
writer.write(newLine);
}
x = 2;
}
reader.close();
writer.flush();
writer.close();
inputFile.delete();
// boolean successful =
tempFile.renameTo(inputFile);
// System.out.println("Success: " + successful);
// System.out.println("currentWav = " + currentWav);
return currentWav;
}
private static void retreiveEmpInfo() throws IOException {
File tempFile = new File("C:\\convoLists/tmp.txt");
BufferedReader reader = new BufferedReader(new FileReader(tempFile));
CurrentEmployeeInfo.setName(reader.readLine());
CurrentEmployeeInfo.setUserEmail(reader.readLine());
CurrentEmployeeInfo.setManagerEmail(reader.readLine());
reader.close();
}
}
This problem may be related to sub-process's input stream buffers.
You should clear the sub-process's input stream buffers.
These stream buffers got increased within the parent process's memory with time and at some moment your sub-process will stop responding.
There are few options to make sub-process work normally
Read continuously from sub-process's input streams
Redirect sub-process's input streams
Close sub-process's input streams
Closing sub-process's input streams
ProcessBuilder processBuilder = new ProcessBuilder(command);
Process process = processBuilder.start();
InputStream inStream = process.getInputStream();
InputStream errStream = process.getErrorStream();
try {
inStream.close();
errStream.close();
} catch (IOException e1) {
}
process.waitFor();
Reading sub-process's input streams
ProcessBuilder processBuilder = new ProcessBuilder(command);
Process process = processBuilder.start();
InputStreamReader tempReader = new InputStreamReader(new BufferedInputStream(p.getInputStream()));
final BufferedReader reader = new BufferedReader(tempReader);
InputStreamReader tempErrReader = new InputStreamReader(new BufferedInputStream(p.getErrorStream()));
final BufferedReader errReader = new BufferedReader(tempErrReader);
try {
while ((line = reader.readLine()) != null) {
}
} catch (IOException e) {
}
try {
while ((line = errReader.readLine()) != null) {
}
} catch (IOException e) {
}
process.waitFor();
Redirecting sub-process's input streams
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.redirectInput();
processBuilder.redirectError();
Process process = processBuilder.start();
process.waitFor();
(from comments)
Looks like process hang is due to out/error streams becoming full. You need to consume these streams; possibly via a thread.
Java7 provides another way to redirect output.
Related : http://alvinalexander.com/java/java-exec-processbuilder-process-3
I am trying to figure out why the code below is throwing a
java.lang.Exception: No such file or directory
Exception
ProcessBuilder send = new ProcessBuilder("/bin/bash","/opt/ftp/scripts/XFER.sh | /opt/ftp/myftp -c /opt/ftp/ftp.conf >> /logging/ftp.log2>&1");
Process sendProcess = send.start();
br = new BufferedReader(new InputStreamReader(sendProcess.getErrorStream()));
builder = new StringBuilder();
line = null;
while ( (line = br.readLine()) != null) {
builder.append(line);
builder.append(System.getProperty("line.separator"));
}
if(!builder.toString().isEmpty()){
throw new Exception( "ERROR with XFER.sh: "+builder.toString() );
}
I've tried isolating the arguments within a String Array, but that did not work either. Any ideas as to what may be causing this stacktrace?
I have success using the following code. Maybe you have to use the -c option:
private static int execute(String command) {
Runtime runtime = null;
Process process = null;
int exitValue = -1;
BufferedInputStream bis = null;
try {
runtime = Runtime.getRuntime();
process = runtime.exec(new String[] { "/bin/bash", "-c", command });
bis = new BufferedInputStream(process.getInputStream());
byte[] b = new byte[1892];
while (bis.read(b) != -1) {
}
exitValue = process.waitFor();
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
}
}
if (process != null) {
process.destroy();
}
} catch (Exception e) {
//Logging
}
return exitValue;
}
I am using the following code to scan the wifi devices connected to my Hotspot enabled device. It is detecting almost all the devices except one device.
following is the code snippet
public ArrayList getClientList(boolean onlyReachables, int reachableTimeout) {
BufferedReader br = null;
ArrayList<ClientScanResultSO> result = null;
try {
result = new ArrayList<ClientScanResultSO>();
br = new BufferedReader(new FileReader("/proc/net/arp"));
String line;
while ((line = br.readLine()) != null) {
String[] splitted = line.split(" +");
if ((splitted != null) && (splitted.length >= 4)) {
// Basic sanity check
String mac = splitted[3];
System.out.println("mac is***************"+ mac);
if (mac.matches("..:..:..:..:..:..")) {
boolean isReachable = InetAddress.getByName(splitted[0]).isReachable(reachableTimeout);
String name = InetAddress.getByName(splitted[0]).getHostName();
if (!onlyReachables || isReachable) {
result.add(new ClientScanResultSO(splitted[0], splitted[3], splitted[5], isReachable, name));
}
}
}
}
} catch (Exception e) {
Log.e(this.getClass().toString(), e.getMessage());
} finally {
try {
br.close();
} catch (IOException e) {
Log.e(this.getClass().toString(), e.getMessage());
}
}
return result;
}
I am unable to find the issue with it. Is "/proc/net/arp" not registering all the device details ?
can somebody help me in this...thanks!