Recently I was trying to implement the functionality of a normal terminal to a graphically designed Swing-based console project. I love how some people in here made this possible, but yet I stumbled upon another big kind of problem. Some people actually spoke about InpuStreamListener although I am not too fond of this. A sample code of my work (pretty much not exactly mine, but it is the source code of my app) would be the following:
// Making an executor
org.apache.commons.exec.DefaultExecutor exec = new org.apache.commons.exec.DefaultExecutor();
// Creating the streams (pretty much ignore this, I just include it as a general idea of the method)
consoleOutputStream = new ConsoleOutputStream();
consoleInputStream = new JTextFieldInputStream(gsc.mainWindow.getConsoleInput().getJTextField());
// Stream Handler with the customized streams I use for the process
org.apache.commons.exec.PumpStreamHandler streamHandler = new org.apache.commons.exec.PumpStreamHandler(consoleOutputStream, consoleOutputStream, consoleInputStream);
// Setting the handler and finally making command line and executing
exec.setStreamHandler(streamHandler);
org.apache.commons.exec.CommandLine commandline = org.apache.commons.exec.CommandLine.parse(String.valueOf(arg));
exec.execute(commandline);
Now the thing is I generally try to run java application through the java commands through this method. OutputStream works really fine, no flaws whatsoever and gives me all it shall, but applications with Input give me a lot of trouble. I beieve the problem resides in the hardcoding to System.in, the Scanner class, the Console class etc. So here's what I need some help with (finally):
I want to either be able to directly access the InputStream passed to my application or someone explaining a way to me of how to actually write an InputStreamListener that will occasionaly be used when I run external java applications (yes, I run them through my interface instead of cmd or terminal, I am trying to make a tool here). If this is too complicated, needs a lot of tweaking on my side or is generally quite impossible, can someone help me just to get the passed InputStream so I can actually write a class that will allow me to write applications specific to my interface?
Thanks in advance and thanks really even for putting the time to read this whole text! :)
Assuming these Apache libraries implement the InputStream and OutputStream interfaces, you can use PipedInputStream and PipedOutputStream to access information. Here's a quick example:
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
public class InputRedirection extends Box{
public InputRedirection() {
super(BoxLayout.X_AXIS);
//Remap input
//Create the input stream to be used as standard in
final PipedInputStream pisIN = new PipedInputStream();
//Create an end so we can put info into standard in
PipedOutputStream posIN = new PipedOutputStream();
//Wrap with a writer (for ease of use)
final BufferedWriter standardIn = new BufferedWriter(new OutputStreamWriter(posIN));
//Set standard in to use this stream
System.setIn(pisIN);
//Connect the pipes
try {
pisIN.connect(posIN);
} catch (IOException e2) {
e2.printStackTrace();
}
//UI element where we're entering standard in
final JTextField field = new JTextField(20);
ActionListener sendText = new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
try {
//Transfering the text to the Standard Input stream
standardIn.append(field.getText());
standardIn.flush();
field.setText("");
field.requestFocus();
} catch (IOException e) {
e.printStackTrace();
}
}};
field.addActionListener(sendText);
add(field);
//Why not - now it looks like a real messaging system
JButton button = new JButton("Send");
button.addActionListener(sendText);
add(button);
//Something using standard in
//Prints everything from standard in to standard out.
Thread standardInReader = new Thread(new Runnable(){
#Override
public void run() {
boolean update = false;
final StringBuffer s = new StringBuffer();
while(true){
try {
BufferedInputStream stream = new BufferedInputStream(System.in);
while(stream.available() > 0){
int charCode = stream.read();
s.append(Character.toChars(charCode));
update = true;
}
if(update){
//Print whatever was retrieved from standard in to standard out.
System.out.println(s.toString());
s.delete(0, s.length());
update = false;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}});
standardInReader.start();
}
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new InputRedirection());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Oh - and one thing to think about when using PipedStreams: Only one thread can write to the Output and only one can read from the input. Otherwise you get some funky problems (see http://techtavern.wordpress.com/2008/07/16/whats-this-ioexception-write-end-dead/ for more details).
Related
I'm building a chess GUI application whose job is to display the board and the pieces and prevent illegal moves from being entered.
It should also have features that involve communication with a chess engine (e.g. stockfish). This is what I'm struggling with right now. The chess engine is an exe file that is accessed using ProcessBuilder:
Process chessEngineProcess = new ProcessBuilder(chessEngineUrl).start();
InputStream processInputStream = chessEngineProcess.getInputStream();
OutputStream processOutputStream = chessEngineProcess.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(processOutputStream));
BufferedReader reader = new BufferedReader(new InputStreamReader(processInputStream));
I want to send strings (commands in the UCI protocol) to the engine to which it responds by continuously outputting text for a few seconds or longer. This hangs up the GUI. I need to update a textArea (in real-time) in the GUI based on the engine's output. This wouldn't be a one-off type of operation. I would like to randomly do this (send a command and update GUI in real time) whenever certain GUI events happen (e.g. user makes a move).
I know that I need to do the stream reading in another thread and I know about SwingWorker but I simply can't get it to work properly.
What I tried:
Since the stream reading is a blocking operation (we keep waiting for output from the engine) the stream reading thread never terminates.
With that in mind, I tried creating a class that extends SwingWorker<Void, String> and sets up and contains the chessEngineProcess (as well as its stream reader and writer) as a private member variable. I implemented the doInBackground and process methods. I also had a public method in this class for sending a command to the engine.
public void sendCommandToEngine(String command) {
try {
writer.write(command + '\n');
writer.flush();
} catch (IOException e) {
JOptionPane.showMessageDialog(null, e.getMessage());
}
}
I do the stream reading in the doInBackground and then publish the output and update the GUI in the process method.
This results in very strange behavior when I send commands to the engine from my GUI classes (e.g. from event listeners). The displayed output is (sometimes partly and sometimes entirely?) wrong and often I get exceptions thrown.
I am at a loss and very desperate so please help! This is a very important project. Feel free to suggest any solution that you think would work!
EDIT:
I get a null pointer exception with the following stack trace:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Moves.Move.isMovePossible(Move.java:84)
at Moves.Move.executeMove(Move.java:68)
at gui.ChessBoard.performEngineMove(ChessBoard.java:328)
at gui.MainFrame.receiveEnginesBestMove(MainFrame.java:180)
at gui.EngineWorker.process(EngineWorker.java:91)
at javax.swing.SwingWorker$3.run(SwingWorker.java:414)
at sun.swing.AccumulativeRunnable.run(AccumulativeRunnable.java:112)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(SwingWorker.java:832)
at sun.swing.AccumulativeRunnable.run(AccumulativeRunnable.java:112)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionPerformed(SwingWorker.java:842)
at javax.swing.Timer.fireActionPerformed(Timer.java:313)
at javax.swing.Timer$DoPostEvent.run(Timer.java:245)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Some details:
Basically I have a "MainFrame" class that is a JFrame that contains all my GUI elements. This is where I add event listeners to my components. In certain event listeners, I call sendCommandToEngine. This will start the blocked doInBackground as the engine starts sending responses.
The process method can then call performEnginesMove on the chessBoard (which is a MainFrame component displaying the chess board) if it detects that a "best move" was output by the engine.
The performEnginesMove function checks if the move is valid (possible) and then makes the move on the board (with the help of the Move class).
For some reason, this doesn't work right.
I built a delegate for the Process and ProcessBuilder classes to show how the rest of the code should be used. I call those classes GameEngineProcess and GameEngineProcessBuilder respectively.
GameEngineProcess is creating the responses, which are simple Strings to be appended directly into the JTextArea of the player's GUI. It actually extends Thread to let it run asynchronously. So the implementation of this specific class is not what you are asking for, but it is used to simulate the Process class. I added some delay in the responses of this class to simulate the time needed by the engine to generate them.
Then there is the custom class OnUserActionWorker which extends SwingWorker and does asynchronously what you are asking for: it receives the responses from the engine process and forwards them to the GUI which updates its JTextArea. This class is used once per engine request, ie we create and execute a new instance of this class for every request the user creates while interacting with the GUI. Note that this does not mean the engine is closed and reopened for each request. The GameEngineProcess is started once and then remains running for the whole game uptime.
I am assuming you have a means of telling whether a single engine request has all its responses completed. For the sake of simplicity in this code I wrote, there exists a message (of type String) which is written each time at the process stream to indicate the end of the responses per request. This is the END_OF_MESSAGES constant. So this lets the OnUserActionWorker know when to terminate receiving responses, so the next instance of it will be later created for each new request.
And finally there is the GUI, which is a JFrame consisting of a JTextArea and a grid of buttons the player can interact with and send a request-command to the engine depending on the button pressed. Again I am using Strings as the commands but I'm guessing this is probably what you will need too in this case.
Follows the code:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.List;
import java.util.Objects;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
public class Main {
//Just a simple 'flag' to indicate end of responses per engine request:
private static final String END_OF_MESSAGES = "\u0000\u0000\u0000\u0000";
//A class simulating the 'ProcessBuilder' class:
private static class GameEngineProcessBuilder {
private String executionCommand;
public GameEngineProcessBuilder(final String executionCommand) {
this.executionCommand = executionCommand;
}
public GameEngineProcessBuilder command(final String executionCommand) {
this.executionCommand = executionCommand;
return this;
}
public GameEngineProcess start() throws IOException {
final GameEngineProcess gep = new GameEngineProcess(executionCommand);
gep.setDaemon(true);
gep.start();
return gep;
}
}
//A class simulating the 'Process' class:
private static class GameEngineProcess extends Thread {
private final String executionCommand; //Actually not used.
private final PipedInputStream stdin, clientStdin;
private final PipedOutputStream stdout, clientStdout;
public GameEngineProcess(final String executionCommand) throws IOException {
this.executionCommand = Objects.toString(executionCommand); //Assuming nulls allowed.
//Client side streams:
clientStdout = new PipedOutputStream();
clientStdin = new PipedInputStream();
//Remote streams (of the engine):
stdin = new PipedInputStream(clientStdout);
stdout = new PipedOutputStream(clientStdin);
}
public OutputStream getOutputStream() {
return clientStdout;
}
public InputStream getInputStream() {
return clientStdin;
}
#Override
public void run() {
try {
final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(stdout));
final BufferedReader br = new BufferedReader(new InputStreamReader(stdin));
String line = br.readLine();
while (line != null) {
for (int i = 0; i < 10; ++i) { //Simulate many responses per request.
Thread.sleep(333); //Simulate a delay in the responses.
bw.write(line + " (" + i + ')'); //Echo the line with the index.
bw.newLine();
bw.flush();
}
bw.write(END_OF_MESSAGES); //Indicate termination of this particular request.
bw.newLine();
bw.flush();
line = br.readLine();
}
System.out.println("Process gracefull shutdown.");
}
catch (final InterruptedException | IOException x) {
System.err.println("Process termination with error: " + x);
}
}
}
//This is the SwingWorker that handles the responses from the engine and updates the GUI.
private static class OnUserActionWorker extends SwingWorker<Void, String> {
private final GameFrame gui;
private final String commandToEngine;
private OnUserActionWorker(final GameFrame gui,
final String commandToEngine) {
this.gui = Objects.requireNonNull(gui);
this.commandToEngine = Objects.toString(commandToEngine); //Assuming nulls allowed.
}
//Not on the EDT...
#Override
protected Void doInBackground() throws Exception {
final BufferedWriter bw = gui.getEngineProcessWriter();
final BufferedReader br = gui.getEngineProcessReader();
//Send request:
bw.write(commandToEngine);
bw.newLine();
bw.flush();
//Receive responses:
String line = br.readLine();
while (line != null && !line.equals(END_OF_MESSAGES)) {
publish(line); //Use 'publish' to forward the text to the 'process' method.
line = br.readLine();
}
return null;
}
//On the EDT...
#Override
protected void done() {
gui.responseDone(); //Indicate end of responses at the GUI level.
}
//On the EDT...
#Override
protected void process(final List<String> chunks) {
chunks.forEach(chunk -> gui.responsePart(chunk)); //Sets the text of the the text area of the GUI.
}
}
//The main frame of the GUI of the user/player:
private static class GameFrame extends JFrame implements Runnable {
private final JButton[][] grid;
private final JTextArea output;
private BufferedReader procReader;
private BufferedWriter procWriter;
public GameFrame(final int rows,
final int cols) {
super("Chess with remote engine");
output = new JTextArea(rows, cols);
output.setEditable(false);
output.setFont(new Font(Font.MONOSPACED, Font.ITALIC, output.getFont().getSize()));
final JPanel gridPanel = new JPanel(new GridLayout(0, cols));
grid = new JButton[rows][cols];
for (int row = 0; row < rows; ++row)
for (int col = 0; col < cols; ++col) {
final JButton b = new JButton(String.format("Chessman %02d,%02d", row, col));
b.setPreferredSize(new Dimension(b.getPreferredSize().width, 50));
b.addActionListener(e -> sendCommandToEngine("Click \"" + b.getText() + "\"!"));
gridPanel.add(b);
grid[row][col] = b;
}
final JScrollPane outputScroll = new JScrollPane(output);
outputScroll.setPreferredSize(gridPanel.getPreferredSize());
final JPanel contents = new JPanel(new BorderLayout());
contents.add(gridPanel, BorderLayout.LINE_START);
contents.add(outputScroll, BorderLayout.CENTER);
super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
super.getContentPane().add(contents);
super.pack();
}
//Utility method to enable/disable all the buttons of the grid at once:
private void gridSetEnabled(final boolean enabled) {
for (final JButton[] row: grid)
for (final JButton b: row)
b.setEnabled(enabled);
}
//This is the method that sends the next request to the engine:
private void sendCommandToEngine(final String commandToEngine) {
gridSetEnabled(false);
output.setText("> Command accepted.");
new OnUserActionWorker(this, commandToEngine).execute();
}
public BufferedReader getEngineProcessReader() {
return procReader;
}
public BufferedWriter getEngineProcessWriter() {
return procWriter;
}
//Called by 'SwingWorker.process':
public void responsePart(final String msg) {
output.append("\n" + msg);
}
//Called by 'SwingWorker.done':
public void responseDone() {
output.append("\n> Response finished.");
gridSetEnabled(true);
}
#Override
public void run() {
try {
//Here you build and start the process:
final GameEngineProcess proc = new GameEngineProcessBuilder("stockfish").start();
//Here you obtain the I/O streams:
procWriter = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
procReader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
//Finally show the GUI:
setLocationRelativeTo(null);
setVisible(true);
}
catch (final IOException iox) {
JOptionPane.showMessageDialog(null, iox.toString());
}
}
}
public static void main(final String[] args) {
new GameFrame(3, 3).run(); //The main thread starts the game, which shows the GUI...
}
}
And finally, another important assumption I made is that when the user interacts with the GUI, the GUI blocks input (but keeps on responding to other events). This prevents the user to have more than one active requests to the engine simultaneously. By blocking input I simply mean that when you click on a button, first all buttons are disabled and then the command is sent to the engine. The buttons are all then reenabled when all the responses for the latest made request finish.
If you need to have more than one requests possible at the same time to a single engine then you will probably need to synchronize the access of some of the GUI's methods and also make sure that each OnUserActionWorker can distinguish its responses from the others. So that would be a different story, but let me know if this is what you want instead.
To test the responsiveness of the EDT while the responses are being received you can for example simply resize the window with the mouse while the (ten) responses are still being received, or just notice that the responses are printed into the JTextArea at real time.
Hope it helps.
I have the below code where I made a simple GUI. I would like Button2 to navigate to class 'Project2', which should start another piece of code. Just to note, in its current state, 'Project2' has no GUI, though I intend to add one soon. Anyway, this 'code jump' which I used by adding: String[] args = {};
Project2.main(args);
is not working, as the IDE says 'IOException must be caught or thrown'. I know how this works, though I am not sure how to implement it in the program.
Thanks in advance!
You can try to use dynamic class loading for your program. Below you can find lambda, which calls main method from com.stackoverflow.ExternalCaller class.
If you do not like to use lambda, you can create a simple anonymous class.
button.addActionListener(s -> {
try {
Class<?> externalCaller = Class.forName("com.stackoverflow.ExternalCaller");
Method main = externalCaller.getDeclaredMethod("main", new Class[]{String[].class});
main.invoke(null, new Object[]{new String[0]});
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
});
ExternalCaller class in its turn looks something like that:
package com.stackoverflow;
public class ExternalCaller {
public static void main(String args[]) {
System.out.println("Hello World");
}
}
In result once you click on the button you will get Hello World output in console.
If you would like to work with external jars etc. please look on Process class. Quick example:
Process proc = Runtime.getRuntime().exec("java -jar External.jar");
Or even more on fork/exec. You can read From Runtime.exec() to ProcessBuilder for more details.
Hope this will help. Good luck.
In most of the IDE's, when you right-click on the Button2 in the Design(GUI) pane, you can travel through:
Events -> Actions -> actionPerformed().
And write this code in the selected method to switch classes:
this.setVisible(false); //turns off the visibility of the current class
outputClass out = new outputClass(); //creating the object of the class you want to redirect to
out.setVisible(true);//turns on the visibility of the class you want to redirect to
I am learning a tutorial about how to consume json web service.
But I have two doubts can you please help me in understanding.
I am learning from this link
http://codeoncloud.blogspot.in/2013/05/blackberry-java-json-tutorial.html
Here is one class extend by thread
public class ConnectJson extends Thread {
private String url;
public String response;
private String myinterface = ";interface=wifi";
public void run() {
HttpConnection conn = null;
InputStream in = null;
int code;
try {
conn = (HttpConnection) Connector.open(this.url + this.myinterface, Connector.READ);
conn.setRequestMethod(HttpConnection.GET);
code = conn.getResponseCode();
if (code == HttpConnection.HTTP_OK) {
in = conn.openInputStream();
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[in.available()];
int len = 0;
while (-1 != (len = in.read(buffer))) {
out.write(buffer);
}
out.flush();
this.response = new String(out.toByteArray());
if (out != null){
out.close();
}
if (in != null){
in.close();
}
if (conn != null){
conn.close();
}
}
} catch (Exception e) {
Dialog.inform(e.toString());
}
}
public String jsonResult(String url){
this.url = url;
this.start();
this.run();
return response;
}
}
It is making one object of that class and call method of that class .In that method it call start as well as run method why ?
this.start();
this.run();?
In that method it call start as well as run method why ?
You'd have to ask the author of the code; looking at that class's code, it looks incorrect. It's also fairly unusual.
In the normal course of things, you don't call run directly; you start the thread (with start) and the JVM is then responsible for creating a new thread and calling run on it.
You can call run yourself if you really want that code to run right away on the current thread, but it's unusual and that class doesn't immediately look like it's designed to do that correctly. What that code actually does is start a new thread (which means run will eventually get called on that new thread), but then as you observed it also calls run directly. So run will run twice, and may well run twice simultaneously. Since the code in run uses instances variables that will be used by both threads but doesn't do anything to coordinate access to those instance variables...well, again, it looks incorrect.
I don't think I'd keep following that tutorial. You may find the Concurrency trail in the Java tutorials from Oracle might be useful. (Threads are part of it.)
I am working on java Application where I am dealing with read and
write file. But I want to do this process simultaneously. As my file
is log file from which I am reading contents by some time interval for
this I used java.util.Timer. And during this time interval I am trying
to writing some contents in the file, but this is not updating in my
log file.
My Timer class is
public class Timer extends java.util.Timer {
public void startTimer() {
Timer t = new Timer();
Task task = new Task();
t.schedule(task, 0, 10000);
}
}
My class form which file read write class is called
public class Task extends TimerTask {
#Override
public void run() {
System.out.println("In task ....");
try {
SMSQuestions smsQuestions = new SMSQuestions();
smsQuestions.sendSMSAnswer();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
My file read write class is
public void sendSMSAnswer()
{
long sender;
String question;
try {
BufferedReader br = new BufferedReader(new FileReader("C:/temp/NowSMS/TEST.log"));
String line = br.readLine();
while (line != null) {
sender = 0;
question = "";
System.out.println(line);
line = br.readLine();
}
//To delete all contents in file
BufferedWriter bw = new BufferedWriter(new FileWriter("C:/temp/NowSMS/TEST.log"));
bw.write("");
getDetails();
}catch(Exception exp)
{
exp.printStackTrace();
}
}
My problem is when i updated my log file by writing new contents it
can't be updated so my question is: is it possible in java to simultaneously read write file or not?
I would suggest you have a look at random access files (see http://docs.oracle.com/javase/tutorial/essential/io/rafs.html). This API is a little more complicated to work with since you'll be reading bytes, not lines, but it should give you what you need.
If you don't want to deal with NIO you can use http://docs.oracle.com/javase/7/docs/api/java/io/RandomAccessFile.html instead.
Try this topic. But the only answer you will get is, its only working with a few OSs.
I have two things to say about your code.
First:
I think that you are missing the finally block where you are supposed to close br and bw.
Try:
finally {
br.close();
bw.close();
}
after the catch block.
Second: It is not a good idea to write content to a file while it is opened. I mean, if you open a file with br maybe it is better to gives another file path to bw
I'm trying to pass String as parameter from one Java Aplications to second as StartUp parameter
for example I have Aplications that must call start another Java Aplication (just contains only JOptionPane, JDialog or simple JFrame) before System.exit(0);, there I trying to send some descriptions from closing application to another,
these code is simulations what I tried that and in this form, code works correctly and displayed String into the JTextArea ...
import java.io.IOException;
import java.util.concurrent.*;
public class TestScheduler {
public static void main(String[] args) throws InterruptedException {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10);
executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(true);
executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(true);
for (int i = 0; i < 10; i++) {
final int j = i;
System.out.println("assign : " + i);
ScheduledFuture<?> future = executor.schedule(new Runnable() {
#Override
public void run() {
System.out.println("run : " + j);
}
}, 2, TimeUnit.SECONDS);
}
System.out.println("executor.shutdown() ....");
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
try {
Process p = Runtime.getRuntime().exec("cmd /c start java -jar C:\\Dialog.jar 'Passed info'");
} catch (IOException ex) {
ex.printStackTrace();
}
System.out.println("System.exit(0) .....");
System.exit(0);
}
private TestScheduler() {
}
}
//
import java.awt.*;
import java.util.ArrayList;
import javax.swing.*;
public class Main {
private static ArrayList<String> list = new ArrayList<String>();
public Main() {
JFrame frm = new JFrame();
JTextArea text = new JTextArea();
if (list.size() > 0) {
for (int i = 0; i < list.size(); ++i) {
text.append(list.get(i));
}
}
JScrollPane scroll = new JScrollPane(text,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frm.add(scroll, BorderLayout.CENTER);
frm.setLocation(150, 100);
frm.setSize(new Dimension(400, 300));
frm.setVisible(true);
}
public static void main(String[] args) {
if (args.length > 0) {
for (String s : args) {
list.add(s);
System.out.print(s + " ");
}
}
Main m = new Main();
}
}
my question :
EDIT1: if is there exist another way how to pass some value from one Java Aplication (there must be called System.exit(0);) to another Java Aplication, another way as I tried by using Process/ProcessBuilder
EDIT2: my crosspost http://forums.oracle.com/forums/thread.jspa?threadID=2229798&tstart=0
accepted answer from OTN
accepted answer by jverd on OTN
Yes, there are other ways. Is this way not meeting your needs?
There's another exec() signature that takes an array, where the first element is the command and the rest of the elements are its args. It may or may not be a varargs call. That would look something like this, although it might not work exactly as I have it.
exec("cmd", "/c", "start", "java", "-jar", "C:\Dialog.jar", "Passed info");
// OR
exec(new String[] {"cmd", "/c", "start", "java", "-jar", "C:\\Dialog.jar", "Passed info"});
You could put the information in a file that the second process reads.
You could store the information in a database that the second process queries.
You could have one process open a ServerSocket and the other connect to it and send the data that way.
You could use a higher-level messaging tool like JMS, Active MQ, etc.
You could use RMI.
You could use CORBA.
I'm sure there are other approaches as well.
I have no idea which approach is best suited to your needs. That's something you'll need to figure out, although if you can't decide, if you post more details about your requirements here, somebody may offer some advice.
Dude,
Read When runtime exec won't and get back to us if you're still stuck.
It's a good article. I'm guessing you've got "a problem with your parameter" ;-)
Cheers. Keith.