When launching a Java program like this (or equivalent):
Runtime.getRuntime().exec("java -jar someJar.jar")
Is it possible to get a reference to the JFrame of the launched program so it can be automated with libraries like FEST (e.g in tests)?
It's easy to do this when the program is launched inside the same VM, as illustrated in this example below, but for several reasons I cannot do that. The program must be separated from the VM/process launching it like above or similar. However, when using the above code to launch the process, the FEST code below does not find the frame.
Example using FEST with adapted code from Java Reflection. Running a external jar and referring to its classes?: (FrameFixture is just an automation wrapper for a JFrame):
Thread t = new Thread(new Runnable() {
public void run() {
File file = new File("someJar.jar");
URLClassLoader cl;
try {
cl = new URLClassLoader( new URL[]{file.toURI().toURL()} );
}
catch (MalformedURLException e) {}
Class<?> clazz = null;
try {
clazz = cl.loadClass("Main");
}
catch (ClassNotFoundException e) {}
Method main = null;
try {
main = clazz.getMethod("main", String[].class);
}
catch (NoSuchMethodException e) {}
try {
main.invoke(null, new Object[]{new String[]{}});
}
catch (Exception e) {}
}
});
t.start();
GenericTypeMatcher<JFrame> matcher = new GenericTypeMatcher<JFrame>(JFrame.class) {
protected boolean isMatching(JFrame frame) {
return "TestFrame".equals(frame.getTitle()) && frame.isShowing();
}
};
FrameFixture frame = WindowFinder.findFrame(matcher).using(BasicRobot.robotWithCurrentAwtHierarchy());
frame.maximize();
No, you cannot get a reference to a JFrame in another process. When you use Runtime.exec() a totally new OS process is created with its own memory space and protections.
To accomplish what you want you could create a JMX-like interface that accepts commands that will either execute actions within a process or report back information from the process.
Related
I am currently working on a programm where I try to open another application (such as eg Notepad) from a link.
As sometimes it will take some time to open that programm, I wanted to implement either a loading screen, or simply indicate the program being loaded by changing the cursorstyle, but only for the period, until the application has been launched and is running.
Whenever I try to implement this feature the cursor is only changed after the application is already running.
The application is launched via the following method:
public void run(String path) {
try {
Runtime runTime = Runtime.getRuntime();
Process process = runTime.exec(path);
try {
Thread.sleep(5000);
} catch (Exception e) {
new Warnings().AppOpenError(dataBean.getLinkPath());
}
process.destroy();
dataBean.getPrimaryStage().getScene().setCursor(Cursor.DEFAULT);
} catch (IOException e) {
new Warnings().ioException(e);
}
}
How can I achieve the loading bar only being shown during loadingtime of the application?
I have created a simple plot with matlab and created a java jar with matlab compiler sdk.
I can run the java function created by matlab and see my plot.
I wanted to create multiple plots and started the function in separate threads.
It works. But if i start my java function for creating multiple plots, the waitforFigure() method of the first thread is waiting for the other plots to be closed too. So my first thread does not continue and blocks till the other plots who are created after it also are closed.
I thought instantiating a Object of the Java class, produced by the Matlab compiler SDK creates a new Matlab compiler runtime?!.
Why is the waitforFigure method waiting for the other plots too, if it is run on seperate thread?
Here is my function runFunction of the RunAlgorithm class i created.
The runFunction methods instantiates the Matlab Compiler SDK created Class, Class1. Its the default name of the class. The thePlot function is the matlab code running in the Matlab runtime and plots my data.
void runFunction( MWNumericArray x1, MWNumericArray y1, MWNumericArray z1) throws MWException {
Class1 thePlot = new Class1;
/* Number of points to plot */
try {
/* Plot data */
thePlot.runAlgorithm( x1, y1, z1);
thePlot.waitForFigures();
}
catch (Exception e) {
System.out.println("Exception: " + e.toString());
}
finally {
/* Free native resources */
MWArray.disposeArray(x1);
MWArray.disposeArray(y1);
MWArray.disposeArray(z1);
if (thePlot != null)
thePlot.dispose();
}
}
Here my simple thread how it executes the Function containing my Matlab class.
I instantiate the RunAlgorithm class, read data from file, and pass it converted to MWNumericArray to the runFunction method.
In my runFunction method there is the waitforFigures method blocking.
Thread t1=new Thread() {
public void run() {
RunAlgorithm a = new RunAlgorithm();
RunAlgorithm.Measurements n = null;
try {
n= a.readFile(selectecValue);
System.out.println("File REad");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
a.runFunction(n.mX, n.mY, n.mZ);
} catch (MWException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
t1.start();
Basically i read a csv File, parse my Data in to MWnumericArray, and pass it to the RunAlgorithm class. That Class internally creates the Class1 Object with the runFunction and plots my Matlab- Plot with Matlab runtime.
EDIT:
If i run my application twice. The waitforFigure method is just waiting for the threads generated by one application.
That would mean, the matlab runtime is run once with the application, independent from the threads i created?
So the Class1 instantiation is not starting a new matlab runtime everytime?
EDIT:
If i compile my matlab code as Singleton,then my plot is refreshed. That would mean, the instatiation of my Class1 Object is starting a new matlab runtime ?
I had a look into your problem and tried to create a Matlab jar on my machine. However, for some reason, creating a jar file failed, so instead I created a dll for .net application. The underlying principle should be similar anyway.
Here is a snap of the constructors found in the generated C# code:
private static MWMCR mcr= null;
static Plotter()
{
if (MWMCR.MCRAppInitialized)
{
try
{
/* a lot of codes here but deleted to make what is important stands out */
mcr= new MWMCR("",
ctfFilePath, embeddedCtfStream, true);
}
catch(Exception ex) { //some code here }
}
}
public Plotter()
{
if(ex_ != null)
{
throw ex_;
}
}
And the drawplot() method which tells the Matlab runtime to run the packaged M-script.
public void drawplot()
{
mcr.EvaluateFunction(0, "drawplot", new MWArray[]{});
}
As you can see, the MWMCR class is the actual Matlab instance that runs the M-script and it is a static object. Therefore, no matter how many Plotter or Class1 is instantiated, there is only one Matlab instance. Multiple mcr.EvaluateFunction requests are queued and executed one after one. Therefore, theoretically running multiple Matlab scripts simultaneously is not possible without having two MWMCR objects generated, which means you will need multiple instances of your java assembly (experimentally confirmed).
In your case, all figures are plotted by the same instance of MWMCR, and WaitForFiguresToDie or waitForFigures() checks for any unclosed figures plotted by MWMCR.
public void WaitForFiguresToDie()
{
mcr.WaitForFiguresToDie();
}
A solution I can propose to you is to include an empty Matlab code (EmptyCode()) in your jar package. Then implement something similar to the following in your java code:
void runFunction()
{
Class1 thePlot = new Class1;
Thread t1=new Thread() {
public void run() {
Class1 thePlot = new Class1;
thePlot.waitForFigures();
}
}
Thread t2=new Thread() {
public void run() {
Class1 thePlot = new Class1;
thePlot.waitForFigures();
}
}
thePlot.waitForFigures();
t1.start();
t2.start();
//your java code
thePlot.EmptyCode();
thePlot.waitForFigures();
}
I am working on a Java program that opens multiple instances of a command line concurrently. To do this, I am using Threads with Runnables as shown here:
//Handles the command line running
private Process p;
private String port;
private String path;
#Override
public void run() {
ProcessBuilder pb = //Initialization of ProcessBuilder
pb.directory(new File(this.path));
...
try {
p = pb.start();
p.waitFor(); //Using this since the server must continue after it is started.
... //This is the part I need to cancel when I close the thread.
}
} catch (IOException e) { //These exceptions are thrown from the process inside the Runnable.
...
} catch (InterruptedException e) {
...
}
}
public void stopServer() {
p.destroy();
}
And in my Main application class:
ArrayList<Thread> threads = new ArrayList<>();
public void startServer(String port, String path) {
//Instantiate my Runnable Class, with port and path parameters
MyRunnable rss = new MyRunnable(port, path);
//Spawn a new thread with the Runnable
Thread thread = new Thread(rss);
//Set the name of the thread (presumably for finding it later?)
thread.setName("server-" + threads.size());
//Start the thread.
thread.start();
//Add the thread to an ArrayList<Thread>?
threads.add(thread);
}
So my question is: How do I use my stopServer() method to stop the process from the Main class?
Disclaimer: I'm very new to Multithreaded programming, so any help you can give would be awesome, there may be something simple that I simply do not know about how Threads work.
Thank you!
Instead of ArrayList<Thread>, I'd instead use ArrayList<MyRunnable>.
This way, I could iterate through the list calling stopServer() if the object is not null.
I've been trying to figure it out for some time,
I'm trying to write a chat - server app, just for learning.
I have an obstacle that I cannot understand,
The while loop inside of the GUI class freeze, but just when it trying to read:
public void run(){
Platform.runLater(() -> {
do {
try {
msg = getFromServer.readUTF(); // <--- freeze GUI
chatWindow.appendText(msg);
} catch (IOException e) {
e.printStackTrace();
}
} while (true);
});
}
You can see that it's running in a thread, but i did try to run it in other ways...
Only the DataInputStream make it stuck,
msg = getFromServer.readUTF();
And this it the methud that it's coming from:
public void connectToServer(){
try {
serverConectionState = new Socket("127.0.0.1", 6789);
getFromServer = new DataInputStream(serverConectionState.getInputStream());
sendToServer = new DataOutputStream(serverConectionState.getOutputStream());
onlineOffline.setText("Online");
onlineOffline.setTextFill(javafx.scene.paint.Color.web("#0076a3"));
} catch (IOException ex){
chatWindow.appendText("server connection fail\n");
}
}
This class, is the Controller.class - if it's make any diffrent.
My first question in stackoverflow, after a lot of help from the community.
Thanks in advance
I'm assuming the run method you showed is part of a Runnable that is executed in a background thread.
You are running the entire loop on the FX Application Thread (by using Platform.runLater()). So you block that thread and prevent it from repainting. You should run only the UI updates on the FX Application Thread:
public void run(){
do {
try {
String msg = getFromServer.readUTF(); // <--- freeze GUI
Platform.runLater(() -> chatWindow.appendText(msg));
} catch (IOException e) {
e.printStackTrace();
}
} while (true);
}
instead of using platform.runlater you should use java task, so that you can run the code in different thread, without freezing the UI thread
I have a program where I am loading a file while at the same time I am displaying a window to inform the user that the file is being loaded. I decided to make a FileLoader class that was a SwingWorker which actually handled loading the file and a ProgressWindow that implements PropertyChangeListener to inform the user about the status of the SwingWorker that was passed into it.
My code currently looks like this:
FileLoader loader = new FileLoader(filePath);
new ProgressWindow(loader, "Loading File", "Loading File");
//ProgressWindow's constructor calls loader.execute() inherited from SwingWorker
doc = loader.get(); //GUI Freezes when called
The problem is that whenever I call loader.get(), it freezes the GUI, thus the progress bar in the Progress Window doesn't run and the whole thing is pointless. As far as I can tell, this is because the thread controlling the GUI is the same thread that calls loader.get(), which goes on hold while loader.execute() is running.
So far, I've tried creating a new thread for either the loader.get() command or the loader.execute() method, and calling SwingUtilities.invokeLater() on the thread, but then the whole program freezes.
I've considered creating a ChangeListener for when SwingWorker.isDone() and then running loader.get(), but this would require some reworking of my code that I would rather not do.
Could anyone tell me what the best way is to get this to work?
get() is like join() in that it will block until called, and will wait for the SwingWorker to finish before being called. Using it wrongly can completely nullify all the advantages of using a SwingWorker in the first place.
Solution: Don't call get() until you know that the SwingWorker is done with its processing, by either calling it in the SwingWorker's done() method, or if you need to call it from the calling code, then in a PropertyChangeListener that has been added to the SwingWorker when the SwingWorker's "state" property is SwingWorker.StateValue.DONE.
Something like:
final FileLoader loader = new FileLoader(filePath);
loader.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if ("state".equals(evt.getPropertyName())) {
// since DONE is enum, no need for equals(...) method
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
try {
loader.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
});
new ProgressWindow(loader, "Loading File", "Loading File");
Note: code not compiled nor tested
Edit: try/catch added.
So far, I've tried creating a new thread for either the loader.get() command or the loader.execute() method, and calling SwingUtilities.invokeLater() on the thread, but then the whole program freezes.
If you call SwingUtilities.invokeLater() on the thread that will execute the thread in the EDT which freezes the GUI. Instead, run the thread by calling it's start() method and only use SwingUtilities.invokeLater() when you need to update the progress bar in the PropertyChangeListener.
I have create a WorkerThread class which take care of Threads and GUI current/main thread .
i have put my GUI application in construct() method of WorkerThread when an event fire to start XXXServer then all threads are activate and GUI work smoothlly wihout freeze. have a look.
/**
* Action Event
*
* #see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
public void actionPerformed(ActionEvent ae) {
log.info("actionPerformed begin..." + ae.getActionCommand());
try {
if (ae.getActionCommand().equals(btnStart.getText())) {
final int portNumber = 9990;
try {
WorkerThread workerThread = new WorkerThread(){
public Object construct(){
log.info("Initializing the Server GUI...");
// initializing the Server
try {
xxxServer = new XXXServer(portNumber);
xxxServer.start();
btnStart.setEnabled(false);
} catch (IOException e) {
// TODO Auto-generated catch block
log.info("actionPerformed() Start button ERROR IOEXCEPTION..." + e.getMessage());
e.printStackTrace();
}
return null;
}
};workerThread.start();
} catch (Exception e) {
log.info("actionPerformed() Start button ERROR..." + e.getMessage());
e.printStackTrace();
}
} else if (ae.getActionCommand().equals(btnStop.getText())) {
log.info("Exit..." + btnStop.getText());
closeWindow();
}
} catch (Exception e) {
log
.info("Error in ServerGUI actionPerformed==="
+ e.getMessage());
}
}