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.
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.
So a little background;
I am working on a project in which a servlet is going to release crawlers upon a lot of text files within a file system. I was thinking of dividing the load under multiple threads, for example:
a crawler enters a directory, finds 3 files and 6 directories. it will start processing the files and start a thread with a new crawler for the other directories. So from my creator class I would create a single crawler upon a base directory. The crawler would assess the workload and if deemed needed it would spawn another crawler under another thread.
My crawler class looks like this
package com.fujitsu.spider;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
public class DocumentSpider implements Runnable, Serializable {
private static final long serialVersionUID = 8401649393078703808L;
private Spidermode currentMode = null;
private String URL = null;
private String[] terms = null;
private float score = 0;
private ArrayList<SpiderDataPair> resultList = null;
public enum Spidermode {
FILE, DIRECTORY
}
public DocumentSpider(String resourceURL, Spidermode mode, ArrayList<SpiderDataPair> resultList) {
currentMode = mode;
setURL(resourceURL);
this.setResultList(resultList);
}
#Override
public void run() {
try {
if (currentMode == Spidermode.FILE) {
doCrawlFile();
} else {
doCrawlDirectory();
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("SPIDER # " + URL + " HAS FINISHED.");
}
public Spidermode getCurrentMode() {
return currentMode;
}
public void setCurrentMode(Spidermode currentMode) {
this.currentMode = currentMode;
}
public String getURL() {
return URL;
}
public void setURL(String uRL) {
URL = uRL;
}
public void doCrawlFile() throws Exception {
File target = new File(URL);
if (target.isDirectory()) {
throw new Exception(
"This URL points to a directory while the spider is in FILE mode. Please change this spider to FILE mode.");
}
procesFile(target);
}
public void doCrawlDirectory() throws Exception {
File baseDir = new File(URL);
if (!baseDir.isDirectory()) {
throw new Exception(
"This URL points to a FILE while the spider is in DIRECTORY mode. Please change this spider to DIRECTORY mode.");
}
File[] directoryContent = baseDir.listFiles();
for (File f : directoryContent) {
if (f.isDirectory()) {
DocumentSpider spider = new DocumentSpider(f.getPath(), Spidermode.DIRECTORY, this.resultList);
spider.terms = this.terms;
(new Thread(spider)).start();
} else {
DocumentSpider spider = new DocumentSpider(f.getPath(), Spidermode.FILE, this.resultList);
spider.terms = this.terms;
(new Thread(spider)).start();
}
}
}
public void procesDirectory(String target) throws IOException {
File base = new File(target);
File[] directoryContent = base.listFiles();
for (File f : directoryContent) {
if (f.isDirectory()) {
procesDirectory(f.getPath());
} else {
procesFile(f);
}
}
}
public void procesFile(File target) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(target));
String line;
while ((line = br.readLine()) != null) {
String[] words = line.split(" ");
for (String currentWord : words) {
for (String a : terms) {
if (a.toLowerCase().equalsIgnoreCase(currentWord)) {
score += 1f;
}
;
if (currentWord.toLowerCase().contains(a)) {
score += 1f;
}
;
}
}
}
br.close();
resultList.add(new SpiderDataPair(this, URL));
}
public String[] getTerms() {
return terms;
}
public void setTerms(String[] terms) {
this.terms = terms;
}
public float getScore() {
return score;
}
public void setScore(float score) {
this.score = score;
}
public ArrayList<SpiderDataPair> getResultList() {
return resultList;
}
public void setResultList(ArrayList<SpiderDataPair> resultList) {
this.resultList = resultList;
}
}
The problem I am facing is that in my root crawler I have this list of results from every crawler that I want to process further. The operation to process the data from this list is called from the servlet (or main method for this example). However the operations is always called before all of the crawlers have completed their processing. thus launching the operation to process the results too soon, which leads to incomplete data.
I tried solving this using the join methods but unfortunately I cant seems to figure this one out.
package com.fujitsu.spider;
import java.util.ArrayList;
import com.fujitsu.spider.DocumentSpider.Spidermode;
public class Main {
public static void main(String[] args) throws InterruptedException {
ArrayList<SpiderDataPair> results = new ArrayList<SpiderDataPair>();
String [] terms = {"SERVER","CHANGE","MO"};
DocumentSpider spider1 = new DocumentSpider("C:\\Users\\Mark\\workspace\\Spider\\Files", Spidermode.DIRECTORY, results);
spider1.setTerms(terms);
DocumentSpider spider2 = new DocumentSpider("C:\\Users\\Mark\\workspace\\Spider\\File2", Spidermode.DIRECTORY, results);
spider2.setTerms(terms);
Thread t1 = new Thread(spider1);
Thread t2 = new Thread(spider2);
t1.start();
t1.join();
t2.start();
t2.join();
for(SpiderDataPair d : spider1.getResultList()){
System.out.println("PATH -> " + d.getFile() + " SCORE -> " + d.getSpider().getScore());
}
for(SpiderDataPair d : spider2.getResultList()){
System.out.println("PATH -> " + d.getFile() + " SCORE -> " + d.getSpider().getScore());
}
}
}
TL:DR
I really wish to understand this subject so any help would be immensely appreciated!.
You need a couple of changes in your code:
In the spider:
List<Thread> threads = new LinkedList<Thread>();
for (File f : directoryContent) {
if (f.isDirectory()) {
DocumentSpider spider = new DocumentSpider(f.getPath(), Spidermode.DIRECTORY, this.resultList);
spider.terms = this.terms;
Thread thread = new Thread(spider);
threads.add(thread)
thread.start();
} else {
DocumentSpider spider = new DocumentSpider(f.getPath(), Spidermode.FILE, this.resultList);
spider.terms = this.terms;
Thread thread = new Thread(spider);
threads.add(thread)
thread.start();
}
}
for (Thread thread: threads) thread.join()
The idea is to create a new thread for each spider and start it. Once they are all running, you wait until each on is done before the Spider itself finishes. This way each spider thread keeps running until all of its work is done (thus the top thread runs until all children and their children are finished).
You also need to change your runner so that it runs the two spiders in parallel instead of one after another like this:
Thread t1 = new Thread(spider1);
Thread t2 = new Thread(spider2);
t1.start();
t2.start();
t1.join();
t2.join();
You should use a higher-level library than bare Thread for this task. I would suggest looking into ExecutorService in particular and all of java.util.concurrent generally. There are abstractions there that can manage all of the threading issues while providing well-formed tasks a properly protected environment in which to run.
For your specific problem, I would recommend some sort of blocking queue of tasks and a standard producer-consumer architecture. Each task knows how to determine if its path is a file or directory. If it is a file, process the file; if it is a directory, crawl the directory's immediate contents and enqueue new tasks for each sub-path. You could also use some properly-synchronized shared state to cap the number of files processed, depth, etc. Also, the service provides the ability to await termination of its tasks, making the "join" simpler.
With this architecture, you decouple the notion of threads and thread management (handled by the ExecutorService) with your business logic of tasks (typically a Runnable or Callable). The service itself has the ability to tune how to instantiate, such as a fixed maximum number of threads or a scalable number depending on how many concurrent tasks exist (See factory methods on java.util.concurrent.Executors). Threads, which are more expensive than the Runnables they execute, are re-used to conserve resources.
If your objective is primarily something functional that works in production quality, then the library is the way to go. However, if your objective is to understand the lower-level details of thread management, then you may want to investigate the use of latches and perhaps thread groups to manage them at a lower level, exposing the details of the implementation so you can work with the details.
I made a windows service from a jar file using WinRun4J, so far it's very basic.
package org.boris.winrun4j.test;
import java.io.BufferedWriter;
import java.io.FileWriter;
import org.boris.winrun4j.Service;
import org.boris.winrun4j.ServiceException;
public class ServiceWrite implements Service
{
private volatile boolean shutdown = false;
public int serviceMain(String[] args) throws ServiceException {
int count = 0;
while (!shutdown) {
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
}
try {
FileWriter fstream = new FileWriter("result.txt");
BufferedWriter out = new BufferedWriter(fstream);
out.write("Counts: " + count);
out.close();
} catch (Exception e){
}
count++;
}
return 0;
}
public int serviceRequest(int control) throws ServiceException {
switch (control) {
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
shutdown = true;
break;
}
return 0;
}
}
When the service is started it just keeps writing every couple of seconds to result.txt located in the root folder.. (Just for trying out WinRun4J)
Now my question is, can I do a method in the service jar, like this
public void write(String s){
//Write some string s to result.txt
}
And then invoke this method from a different java file on the system, i.e
java WriteToFile SomeString
Where WriteToFile is supposed to invoke write with some argument.
Is it possible? if so, how ?
The overall purpose of this is to have a service running where I can invoke methods via a GUI.
to "invoke methods via a GUI", you can't do it with WinRun4J.
in general rule, a Windows Service can't have a GUI for security reason (except for special cases).
However, there are other tools to create a windows service from a Java application, with which it will be possible to have a service with GUI and able to interact with the Desktop.
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).
I'm having some trouble with getting input from the command line before opening a GUI window. I asked this question previously on Apple Exchange but was sent here after we determined it to be a Programming problem. Basically I'm running a Scanner to get user input before I open up a window but it starts the program, switching spaces on my Mac, and then I have to switch back to the workspace with the terminal in it to answer the question. Here's a link to the original question.
https://apple.stackexchange.com/questions/45058/lion-fullscreen-desktop-switching-quirk/45065#comment51527_45065
Here's the code I've tested with...
public class Client extends JFrame {
public static void main(String[]args) {
Scanner in = new Scanner(System.in);
System.out.printf("\nGive me a size for the screen: ");
String response = in.nextLine();
new Client(response);
}
public Client(String title) {
super(title);
super.setVisible(true);
}
}
Use invokeLater() to start the GUI after you get the input.
final String response = in.nextLine();
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Client(response);
}
});
Note that your example runs fine on my platform due to timing differences. Also consider using the args array to pass parameters, or ask the implementation, as shown in FullScreenTest
Addendum: Reading your other thread a little closer, you can use the following approach that launches a NamedFrame in a separate JVM.
package cli;
import java.awt.EventQueue;
import java.io.IOException;
import java.util.Scanner;
import javax.swing.JFrame;
/** #see https://stackoverflow.com/q/9832252/230513 */
public class CommandLineClient {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Give me a name for the screen: ");
final String response = in.nextLine();
try {
ProcessBuilder pb = new ProcessBuilder(
"java", "-cp", "build/classes", "cli.NamedFrame", response);
Process proc = pb.start();
} catch (IOException ex) {
ex.printStackTrace(System.err);
}
}
}
class NamedFrame extends JFrame {
public NamedFrame(String title) {
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationByPlatform(true);
setVisible(true);
}
public static void main(final String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new NamedFrame(args[0]);
}
});
}
}
Code appears to be ok. Is there any class level stuff in Client that you haven't shown here (e.g. static members etc?)
The whole switching workspaces description in your link is an OS level thing NOT java specifically.
Is there options to the java command or something on mac you could use?