I am getting "0" value while calling exitValue() for java process object in linux but occasionally child threads (error & output stream readers) are not completed and getting stuck in join. Shouldn't "0" value of exitValue() of process guarantee that all sub processes terminated successfully?
private class ReadStdoutThread extends Thread {
private Process m_prc;
private StringBuffer m_sb;
public ReadStdoutThread(Process prc, StringBuffer sb) {
m_prc = prc;
m_sb = sb;
}
public void run() {
BufferedReader stdout =
new BufferedReader(new InputStreamReader(m_prc.getInputStream()));
String line = null;
try {
while ((line = stdout.readLine()) != null) {
System.out.println("Stdout: " + line);
m_sb.append(line + "\n");
}
stdout.close();
} catch (IOException e) {
System.out.println(e.toString());
return;
}
}
}
private class ReadStderrThread extends Thread {
private Process m_prc;
private StringBuffer m_sb;
public ReadStderrThread(Process prc, StringBuffer sb) {
m_prc = prc;
m_sb = sb;
}
public void run() {
BufferedReader stderr =
new BufferedReader(new InputStreamReader(m_prc.getErrorStream()));
String line = null;
try {
while ((line = stderr.readLine()) != null) {
System.out.println("Stderr: " + line);
m_sb.append(line + "\n");
}
stderr.close();
} catch (IOException e) {
System.out.println(e.toString());
return;
}
}
}
public static String runCmd(String cmd, long timeoutMS) throws IOException,
InterruptedException {
Process prc = Runtime.getRuntime().exec(cmd);
long startTimeMS = System.currentTimeMillis();
boolean isRunning = true;
System.out.println("Command has started.");
StringBuffer sb = new StringBuffer();
ReadStdoutThread ot = new HostCommand().new ReadStdoutThread(prc, sb);
ReadStderrThread et = new HostCommand().new ReadStderrThread(prc, sb);
ot.start();
et.start();
if (timeoutMS == 0) {
System.out.println("Thread will wait until command is completed.");
prc.waitFor();
} else {
System.out.println("Command timeout (ms): " + timeoutMS);
synchronized (prc) {
int n = -1;
while (isRunning) {
prc.wait(1000);
try {
n = prc.exitValue();
System.out.println("Command has completed with value: " +
n);
m_processExitValue = n;
isRunning = false;
} catch (IllegalThreadStateException e) {
// command is still running
isRunning = true;
}
if ((System.currentTimeMillis() - startTimeMS >
timeoutMS) && isRunning) {
System.out.println("Timeout has reached, and command is still running. Command will be interrupted.");
prc.destroy();
m_processExitValue = n;
isRunning = false;
}
}
}
}
try {
ot.join(timeoutMS);
}
catch(InterruptedException e) {
throw e;
}
try {
et.join(timeoutMS);
}
catch(InterruptedException e) {
throw e;
}
return sb.toString();
}
According to the documentation, the method should return a IllegalThreadStateException if any subprocess is not yet terminated, otherwise it will return 0 which indicates normal termination.
Source: https://docs.oracle.com/javase/7/docs/api/java/lang/Process.html
There is no guarantee that the ReadStdoutThread and ReadStderrThread have finished execution. There is no sync between Process's waitFor API and the two seperate threads that you have spawned to read the standard input and error streams from the Process. You need to use : ot.join();et.join(); after invoking ot.start();et.start();.Basically, join should be invoked before calling Process.waitFor()
Related
here is code
private static class NgrokRunner implements Runnable {
private InputStream inputStream;
private boolean doStop = false;
public NgrokRunner(InputStream inputStream) {
this.inputStream = inputStream;
}
#Override
public void run() {
// TODO Auto-generated method stub
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
try {
while((line = reader.readLine()) != null) {
System.out.println(line);
if (keepRunning()) {
continue;
} else {
System.out.println("break ----");
break;
}
}
} catch (Exception e) {
//TODO: handle exception
System.out.println("Ngrok exception");
}
}
public synchronized void doStop() {
this.doStop = true;
}
private synchronized boolean keepRunning() {
return this.doStop == false;
}
}
and i started above thread like this
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("ngrok", "http","8080", "--log=stdout");
try {
Process process = processBuilder.start();
NgrokRunner runner = new NgrokRunner(process.getInputStream());
Thread ngrokThread = new Thread(runner);
ngrokThread.start();
for (int i = 0; i < 4; i++) {
System.out.println(i);
Thread.sleep(10L * 100L);
}
//System.out.println("It works");
runner.doStop();
} catch (Exception e) {
//TODO: handle exception System.out.println(e);
}
But in while loop my child thread which is reading input from ngrok , blocking and even after calling doStop() it never reached at if condition where i am checking bool flag to exit from thread.
Well can anyone suggest me logic to achieve my ideal situation.
what i want is "Run ngrok server through binary file of ngrok in a thread and close the thread/ngrok whenever i want ( like when user wants through a pause/end button )"
ok so i solved it and here is final solution
run() code :
#Override
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
try {
while(!Thread.interrupted()) {
if (!reader.ready()) {
try {
Thread.sleep(1000);
continue;
} catch (InterruptedException e) {
//TODO: handle exception
System.out.println("We got interrupted");
return;
}
}
line = reader.readLine();
System.out.println(line);
}
} catch (IOException e) {
//TODO: handle exception
System.out.println("Ngrok exception" + e);
}
}
Now from main thread
try {
process = processBuilder.start();
NgrokRunner runner = new NgrokRunner(process.getInputStream());
ngrokThread = new Thread(runner);
ngrokThread.start();
for (int i = 0; i < 8; i++) {
System.out.println(i);
Thread.sleep(1000);
}
ngrokThread.interrupt();
} catch (Exception e) {
//TODO: handle exception
System.out.println(e);
}
UPDATE: Thank you very Antoniossss and Peter Lawrey!
I created a Multi-Threaded Server - Client Communication.
I have 3 Classes: Server, Client, RequestHandler.
The server opens a ServerSocket and then starts to listen for clients via accept() and if a client connects, he refers the client's task(some String) to the RequestHandler.
The command important to me is "SHUTDOWN".
If the RequestHandler finds this command, he calls a method within the Server to shutdown.
This method is based on the usage Example of the Executor Service:
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html (if you do not want to click on the link, see the FAT text for the method)
You do not have to read the code provided below, but in case someone is interested in it I am providing it
The method of the usage Example:
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
public class MulServer_v1 {
protected static int portNumber = 8540;
protected static int max_Clients = 3;
protected static boolean shutdownFlag = false;
private static ServerSocket serverSocket;
protected ExecutorService executor;
protected static ArrayList<Socket> socketList = new ArrayList<>();
public MulServer_v1(int portNumber, int poolSize) {
}
public void runServer() {
try {
serverSocket = new ServerSocket(portNumber);
executor = Executors.newFixedThreadPool(max_Clients);
} catch (IOException e) {
System.out.println("Could not create server on specific port");
e.printStackTrace();
}
while (!shutdownFlag) {
try {
Socket clientSocket = serverSocket.accept();
socketList.add(clientSocket);
executor.submit(new RequestHandler_v1(clientSocket));
} catch (IOException e) {
System.out.println("Couldn't accept on the Socket");
executor.shutdown();
e.printStackTrace();
}
}
shutdownAndAwaitTermination();
}
public void shutdownAndAwaitTermination() {
System.out.println("Shutting down..");
executor.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
executor.shutdownNow();
// Cancel currently executing tasks
System.out.println("komme ich hierhin?");
// Wait a while for tasks to respond to being cancelled
if (!executor.awaitTermination(10, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
executor.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
try {
serverSocket.close();
} catch (IOException e) {
System.out.println("Serversocket konnte nicht geschlossen werden");
e.printStackTrace();
}
System.out.println("I got here!");
for (Socket s : socketList) {
if (s != null) {
try {
s.close();
} catch (IOException e) {
System.out.println("Couldn't close the socket");
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
MulServer_v1 server = new MulServer_v1(portNumber, max_Clients);
server.runServer();
}
}
public class Client_v1 {
public static final String HOSTNAME = "localhost";
public static final int PORTNUMBER = 8540;
private static boolean clientClose = false;
public static void main(String[] args) throws IOException {
System.out.println("Client started");
try (Socket socket = new Socket(HOSTNAME, PORTNUMBER);
PrintWriter out = new PrintWriter(socket.getOutputStream(),
true);
// InputStream test = echoSocket.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
BufferedReader stdIn = new BufferedReader(
new InputStreamReader(System.in))) {
String userInput;
while ((userInput = stdIn.readLine()) != null && !clientClose) {
out.println(userInput);
System.out.println("echo: " + in.readLine());
// if (userInput.equals("BYE")) {
// break;
// }
}
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + HOSTNAME);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to "
+ HOSTNAME);
System.exit(1);
}
}
protected static void closeClient() {
clientClose = true;
}
}
public class RequestHandler_v1 implements Runnable {
// private final String password = "passwort";
private final Socket client;
private boolean closeFlag = false;
public RequestHandler_v1(Socket client) {
this.client = client;
}
#Override
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(
client.getInputStream()));
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(client.getOutputStream()));) {
System.out.println("Thread started with name:"
+ Thread.currentThread().getName());
String userInput;
String serverResponse;
while ((userInput = in.readLine()) != null) {
serverResponse = processInput(userInput);
System.out.println("Received message from "
+ Thread.currentThread().getName() + " : " + userInput);
writer.write("Sever Response : " + serverResponse);
writer.newLine();
writer.flush();
if (closeFlag) {
Client_v1.closeClient();
MulServer_v1.socketList.remove(client);
client.close();
}
}
} catch (IOException e) {
System.out.println("I/O exception: " + e);
} catch (Exception ex) {
System.out.println("Exception in Thread Run. Exception : " + ex);
}
}
public String processInput(String input) {
boolean commandFound = false;
String output = "";
try {
if (input.getBytes("UTF-8").length > 255)
output = "Max string length exceeded";
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Pattern allPattern = Pattern
.compile("(?<lower>^LOWERCASE\\s.+)|(?<upper>^UPPERCASE\\s.+)|(?<reverse>^REVERSE\\s.+)|(?<bye>^BYE)|(?<shutdown>^SHUTDOWN passwort)");
Matcher allMatcher = allPattern.matcher(input);
if (allMatcher.find()) {
String lower = allMatcher.group("lower");
String upper = allMatcher.group("upper");
String reverse = allMatcher.group("reverse");
String bye = allMatcher.group("bye");
String shutdown = allMatcher.group("shutdown");
commandFound = true;
if (lower != null) {
output = lower.substring(10).toLowerCase();
}
if (upper != null) {
output = upper.substring(10).toUpperCase();
}
if (reverse != null) {
output = new StringBuilder(reverse.substring(8)).reverse()
.toString();
}
if (bye != null) {
output = "BYE";
closeFlag = true;
}
if (shutdown != null) {
output = "SHUTDOWN";
MulServer_v1.shutdownFlag = true;
closeFlag = true;
}
} else {
commandFound = false;
output = "UNKNOWN COMMAND";
}
if (commandFound) {
output = "OK ".concat(output);
} else {
output = "ERROR ".concat(output);
}
return output;
}
}
Now the shutting down works, but new clients can connect after the shutdown. How is that possible?
This is Sysout I used to check:
Shutting down..
Thread started with name:pool-1-thread-3
Received message from pool-1-thread-3 : . //<--This (Sending a message) should //NOT be able to happen, since executor.shutdown(); has already been called.
The thing is that your signaling is broken:
while (!shutdownFlag) {
try {
Socket clientSocket = serverSocket.accept();
executor.execute(new RequestHandler_v1(clientSocket));
} catch (IOException e) {
accept() is blocking operation - it blocks until new connection comes right? And here is the culrpit. After you send your "shutdown" command, current thread will unblock, submit the tast, pass the while condition and block again on accept(). After this, proper executor will set the flag to false, but server is still accepting so pool is never shut down.
Another attempt to connect should wake the server and honor shutdownFlag breaking out of the loop and causing all handlers to die after 10 seconds.
Also:
while ((userInput = in.readLine()) != null) {
is a blocking operation - it block your tasks from finishing thus pool will newer shut down. null will be returned if stream will end - either naturally or by an exception. You are not ending the stream on neither of sides. So it will block.
ExecutorsService#shutdownNow() does not mean that threads from pool will be killed - they are signalled to terminate, and threads are to gracefully terminate just like #PeterLawrey mentioned, using Thread.isTerminated() flag.
Proof of concept that closing the socket will break from blocked IO operation:
public class Buffers {
private static Socket client;
static class ServerThread extends Thread {
#Override
public void run() {
try {
ServerSocket serverS = new ServerSocket(1099);
client = serverS.accept();
client.getOutputStream().write('a');
client.getOutputStream().flush();
Thread.sleep(2000);
client.close();
} catch (IOException | InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
static class ClientThread extends Thread {
#Override
public void run() {
try {
Thread.sleep(500);
Socket socket = new Socket("127.0.0.1", 1099);
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("Will try to read");
String line=null;
while ((line = input.readLine()) != null) { // block here
System.out.println("Read " + line); // will never come here
}
} catch (Exception e) {
System.out.println("Server closed the connection!");
}
super.run();
}
}
public static void main(String[] args) throws InterruptedException {
new ServerThread().start();
ClientThread t = new ClientThread();
t.start();
t.join();
}
If you comment client.close(); app will never end just like in your case.
I want a solution for printing value of process variable p. How can we print value of p? Currently value of p is: java.lang.UNIXProcess#727896
public class shellscript{
public static void main(String[] args) {
Runtime r = Runtime.getRuntime();
Process p = null;
String cmd[] = {
"/bin/bash",
"/home/aminul/myscript"
};
try {
p = r.exec(cmd);
System.out.println("testing..." + p);
System.out.println(p);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
If you want to log the standard output and the exit code of the process, try the following:
public static void main(String[] args) throws Exception
{
final Runtime r = Runtime.getRuntime();
final String cmd[] = { "/bin/bash", "/home/aminul/myscript" };
try
{
final Process p = r.exec(cmd);
new Thread()
{
public void run()
{
BufferedReader br = null;
try
{
br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = br.readLine();
while (line != null)
{
System.out.println(line);
line = br.readLine();
}
}
catch (final Exception e)
{
e.printStackTrace();
}
finally
{
if (br != null)
try
{
br.close();
}
catch (final IOException ioe)
{
ioe.printStackTrace();
}
}
};
}.start();
p.waitFor();//wait for process to terminate
System.out.println("Exit code: "+p.exitValue());
}
catch (Exception e)
{
e.printStackTrace();
}
}
Of course, if you want to log the ErrorStream as well, you will have to start another thread.
Process don't have name attribute. But you can use pid.
You can try it in this way
Field field=p.getClass().getField("pid"); // use reflection since pid is private
System.out.println(field);
But you can't use
System.out.println(p)
Since Process don't have a override toString() method
I need to extract the input stream of the process after I start it.
Today I can get the initial information but the method doesn't return until I close the application (in this case the application started by the process: gedit and firefox). I mean, I know it just return after I close the process, but I'd like to have a workaround to get that prior to the process closing.
See my code below.
public class ProcessInvokerExtractingProcessInformation {
public static void main(String args[]) {
try {
Process pOpenApp = new ProcessBuilder(new String[] { "gedit",
"/home/thais/Documents/gedit_doc1" }).start();
printInformation("pOpenApp", pOpenApp);
// * just for testing error message and input stream
Process openFirefox = new ProcessBuilder(new String[] { "firefox" })
.start();
printInformation("lsInstruction", openFirefox);
deleteProcess(pOpenApp);
deleteProcess(openFirefox);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// method for testing information we can see regarding the process
public static void printInformation(String id, final Process process) {
System.out.println(" Process " + id + ":");
//tried to run in a separated thread but didn't work as well
Runnable r = new Runnable(){
public void run(){
System.out.print("\n Process error message -> ");
printScannedStream(process.getErrorStream());
System.out.println("\n Process input message -> ");
printScannedStream(process.getInputStream());
}
};
Thread a = new Thread(r);
a.start();
/* other approaches to print the streams, tried before
StringWriter writer = new StringWriter();
try {
PrintWriter pWriter = new PrintWriter(new
BufferedOutputStream(process.getOutputStream()));
pWriter.write("Hi"); pWriter.flush(); System.out.println(
" Process output stream is for writing so there is no information "
);
*//*
InputStreamReader isr = new InputStreamReader(
process.getErrorStream());
BufferedReader br = new BufferedReader(isr);
System.out.print("\n Process error message -> ");
while (br.readLine() != null) {
System.out.print(br.readLine());
}
System.out.println("\n Process input message -> ");
isr = new InputStreamReader(process.getInputStream());
br = new BufferedReader(isr);
while (br.readLine() != null) {
System.out.print(br.readLine());
}
br.close();
isr.close();*/
/*
* IOUtils.copy(process.getErrorStream(), writer, null);
* System.out.println(" Process error message -> " +
* writer.toString());
*
* IOUtils.copy(process.getInputStream(), writer, null);
* System.out.println(" Process input stream message -> " +
* writer.toString()+"\n");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
}
/**
* Method that close all streams and after destroy the process It's
* important to close the streams to avoid file descriptions leaking
*
* #param process
*/
public static void deleteProcess(Process process) {
try {
process.getInputStream().close();
process.getOutputStream().close();
process.getErrorStream().close();
process.destroy();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void printScannedStream(java.io.InputStream is) {
try {
Scanner scanner = new Scanner(is);
while(scanner.hasNext()) {
System.out.print(scanner.next());
}
} catch (java.util.NoSuchElementException e) {
e.printStackTrace();
}
}
}
I had the same problem and I solved it with using an additional thread.
class InputHandler implements Runnable {
InputStream input_;
InputHandler(InputStream input) {
input_ = input;
}
public void run() {
try {
int c;
String line = "";
while ((c = input_.read()) != -1) {
if (((char) c == '\r') || ((char) c == '\n')) {
if (!line.isEmpty()) flushString(line);
line = "";
} else
line += (char) c;
}
} catch (Throwable t) {
t.printStackTrace();
}
}
private void flushString(String s) {
// any code to process data from stream
Logger.debug("library: " + getClass().getName() + ": compress: output: " + s);
}
}
Process process = run.exec(ffmpegCmdString);
// read output
InputHandler stderrHandler = new InputHandler(process.getErrorStream());
new Thread(stderrHandler).start();
InputHandler stdoutHandler = new InputHandler(process.getInputStream());
new Thread(stdoutHandler).start();
process.waitFor();
I have socket connection which keep reading data and then it will send it via a queue for next processing in another thread. I notice at times it just stop sending data to the queue. I will print this System.out.println("\n\nSending TO QUEUE : "+message); and stop but I do not see any error being capture any method to capture the errors? What could also be the possible error here?
class ConnectionHandler implements Runnable {
private Socket receivedSocketConn1;
ConnectionHandler(Socket receivedSocketConn1) {
this.receivedSocketConn1=receivedSocketConn1;
}
public void run() {
BufferedWriter w = null;
BufferedReader r = null;
String message="";
try {
PrintStream out = System.out;
BufferedWriter fout = null;
w = new BufferedWriter(new OutputStreamWriter(receivedSocketConn1.getOutputStream()));
r = new BufferedReader(new InputStreamReader(receivedSocketConn1.getInputStream()));
int m = 0, count=0;
int nextChar=0;
System.out.println( "\n\n\n THE device"+" "+ receivedSocketConn1.getInetAddress() +":"+receivedSocketConn1.getPort()+" IS CONNECTED ");
while ((nextChar=r.read()) != -1)
{
message += (char) nextChar;
int i = message.indexOf("GET");
if(i != -1) {
break;
}
if (nextChar == '#')
{
w.flush();
System.out.println("\n\nSending TO QUEUE : "+message);
databaseQueue.add(message);
System.out.println("\n\nSent TO QUEUE : "+message);
message="";
}
}
System.out.println( "\n\n\n THE device close connection"+" "+ receivedSocketConn1.getInetAddress() +":"+receivedSocketConn1.getPort()+" IS CONNECTED ");
}
catch (Exception ex)
{
ex.printStackTrace(System.out);
}
finally
{
try
{
if ( w != null )
{
w.close();
}
}
catch(IOException ex){
ex.printStackTrace(System.out);
}
}
}
}
Database processing queue thread snippet code.
class DatabaseProcessor implements Runnable {
// updates databaase with data queued by ConnectionHandler
Connection dbconn = null;
Statement stmt = null;
Statement stmt1 = null;
Statement stmt2 = null;
Date connCreated = null;
public void run()
{
// this is just like the QueueProcessor example I gave you
// open database connection
createConnection();
while (true)
{
try
{
int count=0;
String message = "";
message = databaseQueue.take();
System.out.println("\n\nPICKED AT QUEUE : "+message);
if (message.equals(null)) {
System.out.println("QueueProcessor is shutting down");
break; // exit while loop, ends run() method
}
//there is more codes but is too long to be put here.
}
}
}
}
I edited the code from your example a bit (simplied and removed stuff for testing) and I get the following output:
Client (telnet):
telnet localhost 7777
Trying ::1...
Connected to localhost.
Escape character is '^]'.
peter
test
Server:
PICKED AT QUEUE : peter
PICKED AT QUEUE : test
Code:
public class Trash {
private final static LinkedBlockingQueue<String> databaseQueue = new LinkedBlockingQueue<String>();
public static void main(String[] args) {
new Thread(new DatabaseProcessor()).start();
try {
ServerSocket serverSocket = new ServerSocket(7777);
Socket socket = serverSocket.accept();
new Thread(new ConnectionHandler(socket)).start();
Thread.sleep(10000000);
} catch (Exception e) {
e.printStackTrace();
}
}
static class ConnectionHandler implements Runnable {
private Socket receivedSocketConn1;
ConnectionHandler(Socket receivedSocketConn1) {
this.receivedSocketConn1 = receivedSocketConn1;
}
public void run() {
try {
BufferedReader r = new BufferedReader(new InputStreamReader(receivedSocketConn1.getInputStream()));
String message = "";
while (message == null || !message.equals("") || !message.equalsIgnoreCase("quit")) {
message = r.readLine();
if (message == null) {
continue;
}
databaseQueue.add(message);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
static class DatabaseProcessor implements Runnable {
public void run() {
while (true) {
try {
String message = "";
message = databaseQueue.take();
System.out.println("\n\nPICKED AT QUEUE : " + message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}