In JME I try to use threading but when I run the program the function never starts.
I have a server socket who is listening to input from Netbeans.
Listener
while (isRunning) {
//Reads and prints the input
String receivedString = (String) in.readObject();
System.out.println(receivedString);
String[] parts = receivedString.split(";");
if(parts[0].equals("craneCon"))
{
final int containerId = Integer.parseInt(parts[1]);
m.enqueue(new Callable<Spatial>(){
public Spatial call() throws Exception{
m.removeContainersFromMaritime(containerId);
return null;
}
});
}
So in the main there is the function removeContainersFromMaritime
public void removeContainersFromMaritime(final int idContainer)
{
Node container = Maritime.listOfContainers.get(idContainer);
martime.detachChild(Maritime.listOfContainers.get(idContainer));
seagoingcrane.attachChild(Maritime.listOfContainers.get(idContainer));
container.setLocalTranslation(0,5,0);
System.out.println(Maritime.listOfContainers.get(0).getWorldTranslation().z);
}
The connection is alright but the method is never executed. How can I fix this?
jMonkeyEngine uses a swing-style threading model where there is a single render thread that does all the work. Any changes to the scene graph have to be done from that render thread.
To get into the render thread you can implement AppStates, Controls or you can enqueue Callables which are then executed on the render thread in a similar way to Swing's invokeLater.
The code snippet you posted looks about right, so assuming m is your running jME3 SimpleApplication then m.enqueue() will cause the enqueued callable to be executed next time around the render loop (i.e. at the start of the next frame).
If you are not seeing it executed then either:
Your application is not running
You created more than one application and enqueued it to the wrong one
The code is actually running and you just think it isn't.
Stepping through the code in the debugger and/or adding debug statements (for example breakpoint inside removeContainersFromMaritime to see if it is actually called should allow you to narrow this down.
I might be missing something but what is "m" in m.enqueue(...)?
I'm guessing it is an executor service of some sort and it's probably where the problem lies.
You could try instead:
new Thread() {public void run()
{
m.removeContainersFromMaritime(containerId);
}}.start();
It will at least show you if the problem is coming from "m" as an executor.
Related
EDIT:
I noticed that my question was linked to another. While our goals are similar, the other question's set up is different: they are creating all the GUI aspects of the program within the main class of their program, they are also setting the trigger event of the button press within the start method. Therefore the solution of using the "setOnAction(event->" coupled with Task works. It is a single class program, I was able to make the solution work if I created a new, single class program, this application does not work for me for my situation.
In my set up I am not running this event out of the main class, but out of the Controller class that is linked to my FXML and I have the event that triggers the method already defined. I did not post my entire Controller class as that seemed unnecessary. If there is a way to make the linked question's solution work for my different set up, or a link for guidance that would be stellar. I have looked into the "task" set up, taking from the linked question, but so far have not been able to get it to work successfully as pictured below:
#FXML
private void goForIt(ActionEvent event)
{
kickTheBaby();
}
private void kickTheBaby()
{
java.util.Date now = calendar.getTime();
java.sql.Timestamp currentTimestamp = new java.sql.Timestamp(now.getTime());
statusFld.setOnAction(event -> {statusFld.setText("Running");
Task task = new Task<Void>() {
#Override
public Void call()
{
(new Thread(new EmailCommunication("", currentTimestamp, "START"))).start();
(new Thread(new DataGathering2())).start();
return null;
}
};
task.setOnSucceeded(taskFinishEvent -> statusFld.setText(statusFld.getText()
+ "All done time to sleep..."));
new Thread(task).start();
});
}
I have a program in Java8 using FXML that downloads and parses data. I wish to make the program update the GUI TextField (called "statusFld" here) to say "Running" when I click the start button. Below is the method in the controller that should be responsible for this series of events.
#FXML
private void goForIt(ActionEvent event)
{
statusFld.setText("Running!");
java.util.Date now = calendar.getTime();
java.sql.Timestamp currentTimestamp = new java.sql.Timestamp(now.getTime());
(new Thread(new EmailCommunication("", currentTimestamp, "START"))).start();
(new Thread(new DataGathering2())).start();
}
However, when I attempt to run the program the GUI does not visually update and goes straight into the other two threads. So I attempted to utilize the "Platform.runLater()" methodology in one of the other threads by passing the status field to it as so:
Platform.runLater(() ->
{
statusFld.setText("Running!");
});
But after 20 minutes it had not given a visual update to the GUI. My guess is that this is probably due to the sheer amount of data processing that I am having it do, so who knows what "later" will actually be in this case.
My question is how can I be sure that the GUI visually updates before moving on to the other, very processing intense, threads?
Thank you!
I'm struggling with this issue since some days ago and I'm not able to find a solution.
I have a listener which receives market data (orders at bid and ask). If market is quiet (pre-market or post-market (low volatility)) everything works fine. But once the market is open the listener receives events too fast. So after a couple of minutes my app freezes.
Right now the listener only assigns the received data to a var.
orderBookBid.getBuyOrders().addListener(new ObservableListModelListener<Order>() {
#Override
public void modelChanged(final Change<? extends Order> change) {
System.out.println("bid event");
bidChange = change.getSource();
}
});
The program only freezes when uses real data. When market is closed and uses test data from a local file works fine.
Is there any way to set the maximum number of events per second? Or any way to ignore events for a short time period?
Any idea on how can I handle this would be very appreciated.
Thanks.
You could put a load balancer in your application, that way it will create a queue and will not freeze the application.
If you want to let go some events, in the logic of your listener, you should have something that check if it's been X time since the last time you managed the event.
private long timeSinceLastEventManaged = 0;
private final static long MINIMUM_TIME = 2000; //2 seconds
In your listener
public void modelChanged(final Change<? extends Order> change) {
long timeSystem = System.currentTimeMillis();
if(timeSystem - timeSinceLastEventManaged > MINIMUM_TIME){
//do your stuff
timeSinceLastEventManaged = timeSystem;
}
}
First of all you should get rid of the println as it is really slow
The rest depends on what you are doing. Right now it seems that you are just getting the value and writing it to a variable. You will only see the latest change that way and if that is what you want the solution #TyMarc suggested will work fine.
If what you showed us is just an example and you really need every change things get a bit more complicated. Your modelChanged method should be changed to add the current value to a queue (e.g a LinkedList or Stack).
public void modelChanged(final Change<? extends Order> change)
{
syncronized(syncObject)
{
//add to your preffered queue
syncObject.notifyAll()
}
}
This frees your listener from the real work and it can keep collecting data.
I added a syncronized as someone has to do the work. For this you can use a Thread that runs something like this:
Order current;
while(keeprunning)
{
syncronized(syncObject)
{
if(queue.hasNext())
{
current = queue.getNext()
}
else
{
Thread.wait()
}
}
//do the real work here
}
Now someone else has the problem. Literally. If the Thread can't handle the inflow of data the queue will grow in size until you run out of memory or hit some other limit. But that's another story.
And yes, nothing of this will compile as I only wanted to show an example
Such a piece of code:
private void log(String message) {
LogBox.append(message + "\n");
}
private void log(Exception e) {
log(e.getMessage());
}
private void ConvertButtonActionPerformed(java.awt.event.ActionEvent evt) {
String url = UrlBox.getText();
if (url.isEmpty()) {
log("Empty URL");
return;
}
LogBox.setText("");
try {
log("URL "+url+" accepted. Trying to download...");
String content = URLConnectionReader.getText(url);
log("Downloaded. Parsing the content...");
//
} catch (Exception e) {
log(e);
}
}
should output each message to the LogBox (JTextArea) immediately after each log call, but outputs URL ... accepted only when URLConnectionReader.getText(url) finishes.
There were several ways do do an immediate output:
Application.DoEvents in Visual Basic 6 and .NET
Application.ProcessMessages in Delphi
Is there some simple way to do an immediate output? I was studying questions about the DoEvents and how to do this in Java, but I think that starting to learn Java from multi-threading isn't a right approach.
Create a SwingWorker to do the download: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
The role of an ActionListener is just that: to listen for user action, and initiate a response to that action by the program.
Sometimes, the program's response is very quick, and only involves the GUI. For example, in a calculator app, you could have a listener attached to an "equals" button that calculates the result of the current expression and writes it to a textbox. This can all be done within the listener method (although you might want to separate behavior for testing).
If the response to an user action is to initiate some long-running process, like downloading and parsing the file, then you don't want to do this within the listener body, because it will freeze the UI. Instead, gather any information (in your case, the URL value) from within the listener, and spin up a SwingWorker to handle the program's response.
In my comment, I suggested moving everything after the getText() into a SwingWorker. This is because, to me, the response is "download a file if you have a valid URL, and log the progress." And as I see it, testing for an empty string is part of that response. If you want to leave the empty-string test inside the listener, that's fine, but imo it's less testable.
You must leave the call to getText() inside the body of the listener, because you are only allowed to access Swing components from the event dispatch thread. If you moved that call into the worker, then it might access the textbox at the same time the textbox is updating itself, resulting in corrupt data.
Read up on Concurrency.
You should probably use a SwingWorker for the long running task, then you can publish results to the GUI as they become available.
My application basically uses apache's httpclient to connect to a server and do something for the user.
I am a java beginner (though not a development beginner), so many java specific approaches may have been calmly ignored.
DESCRIPTION
the app uses a TrayIcon with a popup menu as the only user interface and reacts with either tray messages or popup [confirm] dialogs.
it uses threads because the httpclient was effectively blocking the main thread when waiting for a response
employs a client-server to assure a single instance only and reactions to second instance attempts
employs observer/observable pattern to react to the httpclient's and the single instance watchdog server's messages
the main behavior is controlled by a Controller class, which is the only Observer; everything related to the httpclient is in a separater WebClient class, which implements Runnable and extends Observable; then there's the AttServer which is again Runnable and Observable and controls everything around the server listener (there's not much actually).
This is my first application in Java, so many obscurities are possible..:(
PROBLEM
The desired behavior is that whenever a user attempts to run a second instance of this app, then it tries to bind a socket listener on port X and, failing, sends a string message to that port. The 'main' app accepts the message and reacts with a confirm dialog being shown asking the user for some input.
Everything was working just fine up to the point when I've added the client-server; the second instance successfully triggers the update() method of the observer, the observer correctly distinguishes what's going on and fires the corresponding method; and then at the point of the first new GUI component (a confirm dialog) should show up, NOTHING happens:
the app doesn't do anything
no errors or exceptions thrown in System.out
the tray icon CONTINUES to work just fine (right click shows a menu etc)
..it's just that all the instructions coming after the dialog doesn't get executed and the dialog doesn't show up.
WEIRDNESS #1
When the user uses the tray icon menu to fire some other command that shows a dialog, the GUI somehow coughs up and shows BOTH (or more when appropriate) dialogs in the correct order (first the stuck hidden dialog shows up and then the second fresh one) and everything just seems that this is the correct state and all commands get executed correctly (albeit some of them 'a bit' later).
WEIRDNESS #2
I guess this is caused by the swing being not really compatible with threads; however, when the update() method gets fired up from the httpclient (which is a separate thread as well), the GUI works just fine. The only difference in the way the Observer gets notified is that the WebClient calls the notifyObservers() after some user action (albeit in a separate thread and after (at worst) 30s timeout and the AttServer calls notifyObservers() in a catch() block, because IOException is thrown when the specified port has been already bound.
WEIRDNESS #3
This problem is irregular to say the least. It USUALLY occurs in the development environment (netbeans), although sometimes it doesn't --- at first I've got the impression it was solved by calling another (dummy) JDialog, which remained hidden intentionally, before the actual problematic dialog --- it seemed that swing needed a little 'nudge outta the door'; though after building the project into a jar or an exe (via launch4j), the problem was back. Then I've tried to use a single JFrame component for ALL the swing dialogs and it helped somehow --- sometimes when the output jar is run it works as it should and the next day it hides dialogs again.
I am totally lost, scoured the Earth for a solution, found nothing really. I hope that somebody else might bump into some similar problem and, being a more experienced Javaman, found a solution. I've also tried some doLayout(), validate(), revalidate(), repaint(), update() calls on the main JFrame instance, but no go.
There's hope :) Thanks for reading and thanks even more for any ideas.
CODE EXAMPLES
This is the run() function from AttServer -- the source of the non-working update()s.. (it's a bit hard coded as the main functionality is there and I got stuck elsewhere..)
public void run() {
this.addObserver( Controller.getInstance() );
setChanged();
// this.command == INIT set and new thread with AttServer called in the beginning of the main()
if( null != this.command ) {
switch( this.command ) {
case INIT:
try {
init();
} catch( IOException ex ) {
notifyObservers( new ErrorEvent( 100 , "Could not bind the specified port." ) );
}
break;
default:
} //switch
// no command, looks like an incoming connection
} else {
try {
DataInputStream in = new DataInputStream( socket.getInputStream() );
String inputLine;
while( ( inputLine = in.readLine() ) != null ) {
if( inputLine.trim().equals( EventType.CLOCKIN.toString() ) ) {
notifyObservers( EventType.CLOCKIN );
return;
}
}
} catch( IOException ex ) {
//todo
}
}
}
..this is the opposite side of the fence, the update() method:
public void update( Observable obj, Object arg) {
// received a remote request *******************************************
if( obj instanceof AttServer
&& arg instanceof EventType ) {
EventType command = (EventType) arg;
Attendance.debugMsg( "Received " + command.toString() + " request from AttServer" );
if( false == isOnClock ) {
doClock( true , true );
}
} // ..........
.. and this is the essence of the doClock() method called from update() -- there's nothing really, and even when the dialog is shown right after the call, or event when it's shown right in the update() method, it doesn't work.
(overloaded with default data)
public static void doClock( Boolean clockIn , Boolean confirm , String message , String title ) {
Event lastEvent = Log.getLastClock();
if( confirm ) {
if( JOptionPane.NO_OPTION == JOptionPane.showConfirmDialog( mainFrame , message , title , JOptionPane.YES_NO_OPTION ) ) {
return;
}
}
Without reading through this whole document (!!!) I would guess that you are not updating the GUI via the Event Dispatch Thread (EDT).
The GUI is supposed to be updated only by a single thread, the EDT.
You can have background threads in your applications, but the update of the GUI must be passed to be done to the EDT only.
Do not touch any Swing control in a thread of your own i.e. other than EDT.
Otherwise you will have tons of problems.
It is plainly wrong not to go through the EDT
I'm making a desktop application which watches a folder using watchservice from java.nio.file . But I need the gui to be loaded before I start watching, because the path to be watched is in a JFieldText on the UI.
public class FileArchiverApp extends SingleFrameApplication {
static FileArchiverView gui;
#Override protected void startup() {
gui = new FileArchiverView(this); //HERE0 I have to wait for this.
show(gui);
...
public static void main(String[] args) throws IOException {
launch(FileArchiverApp.class, args);
....
WatchService watcher = FileSystems.getDefault().newWatchService();
// HERE1 while(gui==null) System.out.println("hi") ;
try {
Path dir = Paths.get(gui.getOriginPath()); // HERE2 I get nullpointer if gui was not ready
WatchKey key = dir.register(watcher, ENTRY_CREATE );
} catch ( Exception x) {
System.err.println(x);
}
while(true){ /*wait for new file event loop*/ }
}
The function getOriginPath() returns the getText() form the text field I mentioned.
In HERE0 is the attribution I mentioned. I get a nullpointer in HERE2 if gui wasn't ready.
I've tried things. If I put that thing in HERE1 it works, but of course I don't want to do that.
How could I make it?
And its taking to long(like two seconds) or the gui to stop being null with this HERE1 I don't know if it is because of the println, but I was expecting it to be almost instantaneous. Is it normal?
Thanks.
Given the limited information posted, I have to make some assumptions. Assumption 1 is that you give the JTextField a default value and use that as the path to the file you wish to watch. Assumption 2 is that you have not coded with an eye towards MVC-like design.
If both are correct, then it sounds like you have the tail wagging the dog -- the view holding the critical data, not the model. Why not fix your problem by going towards MVC and not getting the critical data from the view but rather from the model. Start the model up first thing, including getting the default path from your program Properties, get your listener going, start your view, and then if the view asks the controller to change the watched file, have the controller change the model. And then listeners in the model will notify your any observers of change.