As is widely known, anything related to Swing components must be done on the event dispatch thread. This also applies to the models behind the components, such as TableModel. Easy enough in elementary cases, but things become pretty complicated if the model is a "live view" of something that must run on a separate thread because it's changing quickly. For example, a live view of a stock market on a JTable. Stock markets don't usually happen on the EDT.
So, what is the preferable pattern to (de)couple the Swing model that must be on the EDT, and a "real", thread-safe model that must be updateable from anywhere, anytime? One possible solution would be to actually split the model into two separate copies: the "real" model plus its Swing counterpart, which is is a snapshot of the "real" model. They're then (bidirectionally) synchronized on the EDT every now and then. But this feels like bloat. Is this really the only viable approach, or are there any other, or more standard, ways? Helpful libraries? Anything?
I can recommend the following approach:
Place events that should modify the table on a "pending event" queue, and when an event is placed on the queue and the queue is empty then invoke the Event Dispatch thread to drain the queue of all events and update the table model. This optimisation means you are no longer invoking the event dispatch thread for every event received, which solves the problem of the event dispatch thread not keeping up with the underlying event stream.
Avoid creation of a new Runnable when invoking the event dispatch thread by using a stateless inner class to drain the pending event queue within your table panel implementation.
Optional further optimisation: When draining the pending event queue minimise the number of table update events fired by remembering which table rows need to be repainted and then firing a single event (or one event per row) after processing all events.
Example Code
public class MyStockPanel extends JPanel {
private final BlockingQueue<StockEvent> stockEvents;
// Runnable invoked on event dispatch thread and responsible for applying any
// pending events to the table model.
private final Runnable processEventsRunnable = new Runnable() {
public void run() {
StockEvent evt;
while ((evt = stockEvents.poll() != null) {
// Update table model and fire table event.
// Could optimise here by firing a single table changed event
// when the queue is empty if processing a large #events.
}
}
}
// Called by thread other than event dispatch thread. Adds event to
// "pending" queue ready to be processed.
public void addStockEvent(StockEvent evt) {
stockEvents.add(evt);
// Optimisation 1: Only invoke EDT if the queue was previously empty before
// adding this event. If the size is 0 at this point then the EDT must have
// already been active and removed the event from the queue, and if the size
// is > 0 we know that the EDT must have already been invoked in a previous
// method call but not yet drained the queue (i.e. so no need to invoke it
// again).
if (stockEvents.size() == 1) {
// Optimisation 2: Do not create a new Runnable each time but use a stateless
// inner class to drain the queue and update the table model.
SwingUtilities.invokeLater(processEventsRunnable);
}
}
}
As far as I understand, you don't want to implement Swing model interfaces in your real model, do you? Can you implement a Swing model as a "view" over a part of a real model? It will translate its read-access getValueAt() to the calls of the real model, and the real model will notify Swing model about the changes , either providing a list of changes or assuming that Swing model will take care of quering the new values of everything it currently is showing.
The usual approach is to send "signals" of some kind to which the UI listens. In my code, I often use a central dispatcher which sends signals that contain the object that was modified, the name of the field/property plus the old and new value. No signal is sent for the case oldValue.equals(newValue) or oldValue.compareTo(newValue) == 0 (the latter for dates and BigDecimal).
The UI thread then registers a listener for all signals. It then examines the object and the name and then translates that to a change in the UI which is executed via asyncExec().
You could turn that into a listener per object and have each UI element register itself to the model. But I've found that this just spreads the code all over the place. When I have a huge set of objects on both sides, I sometimes just use several signals (or events) to make things more manageable.
Related
I have a custom composer/controller class that extends GenericForwardComposer. Inside this class I have some methods that are being used to initialize UI components with data. This is a very long operation and takes time to complete. Due to performance issues I am trying to asynchronously load this data using Event Queues. This way it will not block users from accessing other functions while the process runs in the background.
In my custom class there is an init method that starts the processing. This method invokes several other methods that handle the majority of the work.
My thinking was that I can use Event Queues something as such:
public class MyWidgetController extends GenericForwardComposer
{
public void init(final Component comp)
{
//other method logic ...
EventQueue queue = EventQueues.lookup("myQueue", EventQueues.SESSION, true);
queue.subscribe(this); //not sure
queue.publish(new Event("onInitPrimaryLoad", componentA, ""));
queue.publish(new Event("onInitSecondaryLoad", componentB, ""));
}
#ViewEvent(componentID = "componentA", eventName = "onInitPrimaryLoad")
public void onInitPrimary( final Event event){ //logic }
#ViewEvent(componentID = "componentB", eventName = "onInitSecondaryLoad")
public void onInitSecondary( final Event event){ //logic }
//other class methods…
}
Not sure if this is all correct. Don't really need a callback method as the Events (publish) themselves are loading the UI components with data. The application runs with no issue but I'm not sure if I'm implementing this correctly.
Any advice or corrections are appreciated
The #ViewEvent seems to be Hybris specific and is not part of the ZK framework, that's why I can't comment on it.
Your example doesn't do async processing at all, the events are published into the current thread and the ui will block and only return after all these events have been processed. (even worse using a SESSION scoped event queue the events are published into all desktops (roughly browser tabs) of that user - most likely executing your heavy work multiple times. You should use a DESKTOP scoped event queue instead.
Also I don't fully understand why you don't need a callback ... when doing async processing you always need some kind of callback or create a thread manually.
Especially in ZK it is vital to perform the heavy work in a separate thread. Once the data is retrieved lock the UI as short as possible to perform updates to the component tree or component models - this keeps the UI as responsive to the user as possible.
The EventQueue usage is described in the official docs.
Based on those I create 2 runnable examples illustrating the simplified and the more generic approach.
As an alternative you can activate/deactivate a ZK desktop directly without using event queues as in this (my preferred) example.
I have a usecase where I would like to publish a non-state-chaninging event as a trigger.
In the vast majority of cases, the Aggregates will publish events by applying them. However, occasionally, it is necessary to publish an event (possibly from within another component), directly to the Event Bus. To publish an event, simply wrap the payload describing the event in an EventMessage. The GenericEventMessage.asEventMessage(Object) method allows you to wrap any object into an EventMessage ...
The event is published from inside a Saga.
When I use asEventMessageand look at the events table I'm a little confused. The event has an aggregate identifier that does not exist in the rest of the system and the type entry is null (when reading the docs, for a moment it sounds like the expected behavior of asEventMessage is equal to applying events from within aggregates).
Since I consider the event I'm talking about conceptionally part of the aggregate it should be referring to it, right?
So I craft a GenericDomainMessage myself and set its aggregate identifier, sequence number and type manually:
#SagaEventHandler
public void on (AnotherEvent event, #SequenceNumber long sequenceNr) {
// ...
GenericDomainEventMessage myEvent = new GenericDomainEventMessage(
MyAggregate.class.getSimpleName(),
identifier.toString(),
sequenceNr + 1,
payload);
eventStore.publish(myEvent);
}
This event does not introduce (data) state change to its underlying aggregate. I treat it as a flag/trigger that has a strong meaning in the domain.
I could also publish the event from within the aggregate, in a command handler but some of the operations that need to be performed are outside of the aggregate's scope. That's why a Saga seems to be more suitable.
So my questions are:
Is publishing a GenericDomainEventMessage equal to the behavior of AggrgateLifeCycle#apply?
Should there be a no-op handler in the aggregate or will axon handle this correctly?
In Axon 3, publishing the event to the EventBus is the same as apply()ing them from within the Aggregate, with one difference: apply() will invoke any available handlers as well. If no handler is available, there is no difference.
EventBus.publish is meant to publish Events that should not be directly tied to the Aggregate. In the Event Store table, it does get an Aggregate identifier (equal to the message identifier), but that's a technical detail.
In your case, the recommended solution would be to apply() the Event. The fact that the event doesn't trigger a state change doesn't matter at that point. You're not obliged to define an #EventSourcingHandler for it.
I have a simple JAVA program with gui that just increments int variable and displays its value in JLabel.
I create new thread for proper(thread-safe) updating JLabel by calling inside it EventQueue.invokeLater() with Runnable class which run method simply does
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
label.setText("" + number);
}
});
When i run program, as expected label's number starts to grow rapidly from 1 to about 5000 but then it starts to slow down and i'm starting to see such label's updates like 100255, 173735, 235678 and big pauses between them with blocked GUI.
But when i compile without using EventQueue.invokeLater(), just calling directly label.setText("" + number); everything works fine and perfect and i can see how each number of my label is changing extremely fast. But of course i realize in that case my method isn't thread-safe.
What's the problem? It seems to me that EventQueue works slow or something.
Probably, the event queue is being choked up. You may want to look at coalescing the events to remove redundant entries when you are queuing event faster than they can be dequeued and actioned.
Every time an event is added to the queue, the existing events are queried to see if they merge the new event with themselves. As the queue backs up, more and more events have to be so queried, and the system gets progressively further behind. This is useful for mouse events, but in a simple (and artificial) case like this it can be detrimental.
Having said that, I vaguely recall that the GUI code is optimized to not attempt coalescing events that don't override the appropriate method, so your problem may be just a simple backlog.
Instead of calling setText directly, you could create a custom event for setting text on a component, implement coalescing for it and use that instead so that at any given time only the most recent text is pending. If you do this and you want to set the text based on what was previously set it's better to retain the value and always set the GUI widget from that rather than recalling the GUI widget's current value with getText. Otherwise merging is much more difficult.
My project is built upon Java's Swing library. It spawns the EDT which displays my GUI (which works correctly).
The entrance to the program, which initializes the EDT:
public final class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Start());
}
class Start implements Runnable {
private Model model = new Model();
private Controller controller = new Controller(model);
private View view = new View(controller);
#Override
public void run() {
// Initialize the view and display its JFrame...
}
}
}
}
However, when a button / radio box / etc. is clicked within my GUI, the Controller class must perform an action on the model.
My questions are the following:
Should I wrap the controller's code in a new SwingWorker?
If no, should I wrap my model's code in a new SwingWorker?
If I wrap the controller's code with threads, do I need to synchronize the shared state variables within my model?
If my model, running on a new thread, notifies my GUI of changes, will this occur on the EDT or on the new thread?
For example:
public class Controller {
public void updateModel() {
new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
model.somethingSomethingSomething();
}
}.execute();
}
}
public class Model {
public void somethingSomethingSomething() {
notifyListeners(); // This is going to notify whichever GUI
// is listening to the model.
// Does it have to be wrapped with Swing.invokeLater?
}
}
public class View {
// This function is called when the model notifies its listeners.
public void modelChangedNotifier() {
button.setText("THE MODEL HAS CHANGED"); // Does this occur on the EDT?
}
}
Instead of updating your model from doInBackground(), publish() interim results and update your model from process(), which executes on the EDT. In this example, JTable corresponds to your View and TableModel corresponds to your Model. Note that JTable listens to its own TableModel.
You can read about it here: Improve Application Performance With SwingWorker in Java SE 6. In short: all time consuming operations, which are not affected UI must be done in another thread. To show results of operation you must go back to EDT. For example, if you make database search, you should show a progress bar (usually infinite) and start the search using SwingWorker. To show search results in a table, you must be in EDT. Alternatively you can use foxtrot lib (it allows to make your code more Swing convenient without to redesign it).
If your controller code permanently updates the swing widgets you should execute it in EDT or at least perform these updates of UI in EDT (using SwingUtilities.invokeLater, chunk processing in SwingWorker or swing.Timer).
So your sample is wrong: model update should be up-to-date in EDT.
One alternative approach, from Java Concurrency in Practice 9.4.2, uses a "Split" or a "Shared Data Model". You update your Business Model on whatever thread you want, likely the long-running non-EDT thread. But then, instead of directly calling notifyListeners() and worrying about which thread you are on, simply call myComponent.repaint(), which will queue up a repaint request on the EDT.
Then, somewhere in your paintComponent() method, you explicitly grab all new data from the Model, typically in a method called modelToView()
commentTextArea.setText(myModel.getCommentText());
fooLabel.setText(myModel.getFooText());
...
The upsides are that threading is not an issue, and, at least to some minds, this "makes sense", and the model is nicely decoupled from the view. A downside is that you are resetting all the values every time. So if you have 100 JComponents, that's 100 things getting set. Also, the view is pretty tightly coupled to the model.
Working Code Examples
#MadProgrammer and #kleopatra are correct that, if the view directly contains the components that are being updated, you get an "infinite loop of doom". For proof, see
Demo_14716901_Fails
However, if the view is isolated from the components, you avoid the infinite loop. Normally, the higher level view would contain stuff like JSplitPanes, holding JScrollPanes, holding Boxes or more JPanels, holding the actual low level components. So this requirement, IMO, is not unreasonable.
Working code at Demo_14716901_Works
Some Comments Added for the Downvoters:
Some people want to defeat Swing. They are writing instrument control code or algorithms and just want to get their job done without worrying about the EDT, endless SwingWorkers and invokeLaters. This technique lets them get their job done. With the one important caveat noted, it works. (Personally, I understand and generally like Swing, but many don't).
While Swing components are nicely MVC, they are generally at far too micro a level. The "real" model is not a single String, it is dozens of values. The "real" view is not a single JLabel, it is many JPanels, each with many components, combined with scrollers, splitters, etc. This technique usually fits the real world better, allowing the programmer to think naturally at a higher level.
As far as "bad practice", take it up with Brian Goetz, Josh Bloch, etc. o.k., that's "appeal to authority", but it works for me. :-)
I'm working on a project that does some intense math calculations (arrays of matrices, vectors, etc.), so naturally I'm splitting the work into jobs, and submitting them to a CompletionService to perform the work in parallel.
Each of the job objects can fire events to notify applications when the job starts, ends, progresses, and/or fails.
Currently, each of the jobs receive a handle to the entire list of event listeners, and simply iterate through, passing an event object to each one (in the same thread). This doesn't sit well with me, so I'd like to get other peoples' experience with doing this sort of thing with custom events/listeners.
Should I send my events to the GUI thread? Some of the listeners may or may not be GUI-related, and I'd like to not force users of my code to have to manually send their events onto the GUI thread, something like the following:
public class MyFooEventListener implements FooEventListener {
public void notifyJobStarted(FooEvent evt) {
// I want to avoid having users of my library write the following, right?
SwingUtilities.invokeLater(new Runnable(){
// update GUI here.
});
}
}
I wouldn't mind writing my own EventQueue, as this is for a research project in school, and I suppose it would be a good exercise in concurrency. Just trying to figure out what the "proper" way of implementing an event-driven system is, how to properly fire events, etc. Links to articles/tutorials and howtos are also greatly appreciated.
Thanks!
EDIT:
My event model has multiple event types, such as JobStartedEvent, JobEndedEvent, JobProgressEvent, etc. Is this a bad approach? Should I have a single event type, and if so, how do I pass information to the listeners that is not common to all events? Example: I want to pass a double in the range [0-1] for the progress event, but that is not applicable for an event like JobFailureEvent. What's the best approach to handling this?
I could put the extra information in the "source" object itself, but my source objects are the Job objects themselves, and it doesn't sit well with me to "leak" references to the job object, especially while it is running:
FooJob jobObject = (FooJob)event.getSource();
int progressPercent = jobObject.getCurrentProgress() * 100;
progressLabel.setText(progressPercent + "%");
No. Emit your events on whatever thread needs to raise them and leave it up to the users of your subsystem to decide how they wish to handle them. If they wish to message the results to a GUI, fine, if not, they can do whatever they want, eg. queue them to another thread. Just document 'Events are raised on an internal thread and event handlers must not block'.
Anything else puts constraints on users that they may well not want, as you say.
there are many ways to distribute events, each with their own pros and cons. if the consumer is not necessarily the GUI, then you definitely should not tie yourself to the awt EDT. unless you know for sure how the event consumers are going to work i would start simple and go from there. simple being: synchronously notify each consumer. if that ends up delaying the main task, then you should think about asynchronous notification. if the consumer is ultimately the GUI, then the consumer's notification method should be responsible for calling SwingUtilities.invokeLater.
Only threads that directly impact the GUI should be on the EDT. If you have other threads you need synchronized, just use the synchronized keyword (either on the method or on an object)
Spring has event handling and you can define custom events http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html#context-functionality-events.