How to throw an Exception if calling AWT code outside EDT thread? - java

I've searched this along the way on the net but i haven't found an answer yet.. maybe someone of you guy knows this.
I'm developing a swing desktop like application; since I know that swing is not thread-safe (and if I call a method on a JComponent outside the EDT there is always the chance to get a deadlock with the EDT itself), I would like to have an exception thrown by the thread that is trying to call that method.. let me explain better:
suppose I have 2 threads: the EDT and a background worker ("BW").
If I call, for instance, JButton.setText(), or JButton.setIcon() within the BW there is a chance to get a deadlock with the EDT. Now I would like that when the BW calls JButton.setText() and exception is thrown to indicate that I'm doing very wrong..
I see that C# on VS2008 does this by default (I don't know if there is a way to disable this behaviour, but I think it is very useful to detect bad code). Is there a way to achieve a similar effect in java?

Take a look at this article which describes a RepaintManager which checks Swing threading violations. It will not catch all violations, but most of them.
You can easily adjust that class to throw Exceptions iso just printing a stack trace

Take a look at SwingUtilities.isEventDispatchThread. Calling this will return true if the call is made from within EDT, false otherwise.
It will do exactly what you want, the problem is you will probably have to make such calls in multiple places of your code; it's more work.

Wrap each swing object you have in a Proxy, generated with reflection. Make that proxy compare the thread to the known good EDT thread. If doesn't match throw a RuntimeException.

Related

Java, handling potentially large numbers of exceptions in one class - handler class?

I'm working on a Java project and I've come upon an interesting design issue. It's not exactly a problem, but it is a bit ugly with the obvious solution.
I have a class implementing Callable, although with the current implementation it could just as easily be a Runnable as I'm not interested in the outcome, at least not as far as the calling thread is concerned. The calling thread will drop a number of these into a thread pool. Each of these Callables will have a batch of data that was obtained from an external service. The Callables will perform a number of actions, many of which involve making further calls to external services. As a result, there are a good number of places where various Exceptions could be thrown.
The issue I find is that depending on where the Exception occurs, I may need to take different actions. If it happens at point A, then delete the data on the external service. If it happens at point B, move the data to a different location on the server. If it happens at point C, just log it and do nothing further, etc. Any number of Exception types could be thrown at multiple points, although I don't think I'll need to do much filtering on the type itself, but more that one occurred.
The Callable itself isn't terribly huge, so there's not a great deal of code to mess with. However, I am hesitant to kludge it up with a ton of try/catch blocks to handle every possible point/Exception that may need different handling. I realize that this may really be the only viable solution. I don't really have control over most of the Exceptions that will be thrown (maybe a handful) without catching an existing one and rethrowing my own, which seems a bit redundant. I'm wondering if there's a good pattern or method to handle this sort of thing.
I've considered an exception handling class, but I'd still need to catch each Exception somehow and pass it to the handler as the point at which the Exception was thrown is important. I could break the Callable down into more atomic classes, each with their own small block and handling, but that would be trading one kludge for another. Catching everything in the call() method outright or by grabbing the Exception from the Future in the calling thread really isn't an option as this will lose the data on where it occurred unless I want to parse the stack trace, which isn't exactly viable.
Can anyone shed some light? Maybe I'm just quibbling over the try/catch blocks and should just go ahead with it, but I feel like there must be a better way...
Hmmm, it does occur to me that annotations on methods might help here. I could break down all methods until there's only one possible exception-throwing piece of code in each. Annotate each of these with a custom annotation that dictates what is done when that method throws an exception. I'm not sure if it is possible (an exception would somehow need to be caught right there as it may happen within a loop going over each piece of data and only one piece may be problematic, or at least somehow mark that piece for processing further up the chain), but perhaps this could mitigate the need for lots of try/catch blocks and instead handle the behavior with a single annotation and a handler class to deal with the exceptions. I don't believe it's possible to dictate behavior this way with an annotation, but I'd be happy to be wrong on that.

Can I run two EDTs?

This is mostly a theoretical question. The example below is what made me think of it, but it may not be the best example. Please assume that the reason's below are concrete, and can't for the moment be worked around.
The Program I have been running has an optional Debug frame that is created on the program startup, and it made visible by the user pressing buttons/keyboard shortcut.
My issue is that as I have lengthy processes on the EDT, if it is hanging for some reason or fails I'd like to see straight away, and not wait for that thread to end running, to update the Debug Log Frame.
My solution would be to have two separate EDT for two separate GUIs that are updated by a separate thread.
Is this possible, or am I not able to do so? I haven't found any online resourcethat would show me how to. I know that EDTs should be single threaded, but if I keep the threads disentangled, can I have two? Please?
The answer is simple: No you cannot have 2 EDTs, that is not possible.
But you are not stuck with a frozen GUI, you have some options available.
First and foremost, two important rules:
Never do lengthy calculations in the EDT. Ever.
Never manipulate Swing components from outside the EDT. Ever.
Breaking the first rule will result in your GUI being frozen and no events of any sort being processed during that time. This includes updates to the GUI you want to do during the calculations which will not appear until after the calculations are done.
The latter is often ignored which will go by unnoticed most of the time, but it can - and will - bite you in the ass and then most of the time it is a huge pita to go back and fix it. So do it the correct way from the start. What can happen? Components can suddenly display in a broken state, they may appear white, or the whole application can freeze because there is a deadlock between the EDT and your other threads (been there, done that). Adhere to the Oracle Swing Threading Policy!
So, how to avoid doing lengthy calculations on the EDT after for example the user pressed a button? Options:
use a SwingWorker. Advantage: Has a done() method you can use which is automatically executed in the EDT once the worker is done. Also implements the Future interface and can therefore be used to return a result.
you can just create your own Runnable and do the calculations in there.
use any other way Java provides for parallel execution.
Ok, and how to avoid ever manipulating GUI from outside the EDT?
call SwingUtilities.invokeLater() and execute Swing manipulations in there.
use the SwingWorkers done() method as described above.
If you follow these two rules, your Swing GUI will be in a much better shape and you can focus more on your application development rather than Swing issues.

Is creating an image with Swing thread-safe?

I want to use this Swing snippet to create an image from a text label from a non-Swing based app (a web service written using Play Framework, to be specific).
I've never used Swing, and saw that "it is not thread safe". Does this apply to the minimal code that I'm planning to run? Should I synchronize access to this code?
If I understand the answers about Swing thread-safety correctly, then unless a method explicitally says it's safe, then it isn't ... and the methods I use (specifically BufferedImage.getGraphics() don't seem to have this piece of javadoc). So, unless shown otherwise, I'm going to synchronize.
"Not thread-safe" means that you must not access the same thing from multiple threads at once.
There is nothing wrong with running that code on a background thread, as long as you don't share the objects across threads.
Note that most (non-UI) objects are thread-safe for read-only operation.
EDIT: actually, you can cut out all the Swing related parts in your "Swing snippet" since you really only care about the image manipulation part, which has nothing to do with Swing.
Don't worry about anything: your code is not multi-threaded.
Where it gets complicated with Swing is when you have some actual interface. The interface is run from a special thread (the event-dispatch thread or EDT), which is a different thread from the main thread where you program runs. If you update some value in your main program, you have to be careful with multi-threading issue otherwise your updated value will never show on screen.
Since you are just using some methods from the Swing library without having any EDT it's just like using any method from a normal library.

Use of multiple threads in a Java program and vs need to create Swing objects on EDT

Re: Requirement to create Swing Object on Event-Dispatch Thread.
I am working on an application, the purpose of which is to monitor and display the condition of various remote embedded servers. I'm pretty new to Java, and my understanding of the requirement with respect to the Swing Objects and the EDT is incomplete.
The main GUI is started on the EDT in the usual fashion as follows,
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
The user may then select one or more menu options corresponding to the one or other of the remote machines. The effect of this is to create a new thread each time as follows
new Thread(new VoterStatus(itemNumber)).start();
which invokes VoterStatus's class "run" method which in turn creates a new window with a JFrame. The new thread, an instance of VoterStatus class, then interrogates (TCP etc) the particular remote specified (itemNumber), collecting various bits of information and displaying them in the JFrame.
There may be any number of such threads corresponding to an instance of VoterStatus, all updating their own windows. There is no sharing of data between these various windows/JFrame/tasks.
This seems to work just fine, but is is safe?
Have I violated the rule about creating Swing components on the EDT?
Would use of the SwingWorker class be beneficial?
I would appreciate any comments from Java programmers more experienced in such matters.
Thanks
Steve
From the section in the Swing tutorial titled The Event Dispatch Thread
Some Swing component methods are labelled "thread safe" in the API specification; these can be safely invoked from any thread. All other Swing component methods must be invoked from the event dispatch thread. Programs that ignore this rule may function correctly most of the time, but are subject to unpredictable errors that are difficult to reproduce.
I always invoke my methods on the EDT so I don't waste time chasing gremlins.
Edit:
I just read another posting which states that the comment "thread safe" has been removed from many methods in the JDK7 API. http://forums.oracle.com/forums/thread.jspa?threadID=2167051. This looks like another reason to make sure all methods that affect the GUI are executed on the EDT.
#camickr has the right of it. Incorrectly synchronized programs may appear to work most of the time, but the result is not reliable. Several related approaches are discussed here. SwingWorker is an especially convenient implementation of the Future interface, as process() runs on the event dispatch thread.
You might be safe, but you can be sure by creating your other UI components in the EDT, just like you did for the main application.
However, I would suggest a different approach. Rather than firing off a new Thread which creates the windows and stuff for each new VoterStatus, create the UI components in the EDT in response to ActionEvents from menus or whatever, and do processing of the network stuff only in a different thread. Then get the results and use the EDT to display them. As you've suggested, a SwingWorker is ideal for this - this is exactly the sort of use it was designed for. This represents a cleaner separation for me, separating the UI stuff from the network stuff as much as possible.
I'm not really answering my own question, but I do want to thank those that responded and ask a follow up question or two.
Rogash commented that if I was only creating the GUI on the EDT, I would be ok, but this doesn't seem quite in accordance with a strict interpretation of the rule?
The additional threads are created in the EDT, but they are still separate threads.
Whilst slightly better separation of the GUI and comms may be desirable, I expect this will add considerable complexity to the main GUI code, since it will have to determine which window originated various events and then update the correct window, not to mention the communication between the various threads and the main GUI thread. Perhaps I am overstating this difficulty (I haven't designed or thought about how to code it yet) but it would seem more complicated. Each of the threads/JFrame already has a couple of JToggleButton arrays (30 elements) causing potential events and 10 or so JTextField arrays with the same number of elements requiring updating.
Of course, if my method is unsafe, I'll have to change it, and that's that!
Actually, I wonder if I might be better off leaving things the way they are, and using a mutex or semaphore to make sure only one thread is accessing Swing methods at a time. There is really no long user actions or any other activity takes a long time, just lots of TCP or UDP packets being received that require the screen display to be updated.
Thanks again
Steve
PS I tried to register on this forum, but I think this discussion will stay with my unregistered persona.

Why a EDT violation happens?

I started to use CheckThreadViolationRepaintManager to detect EDT violations.
It complains about:
partner = getParameter("partner",generatePartnerSelectionPanel(),Design.partnerSelectionDuration);
Because it does not like generatePartnerSelectionPanel() because it does not like JPanel panel = new JPanel(); in this method. But I cannot find out why there should be a problem around that.
In more details, generatePartnerSelectionPanel() generates a JPanel (I do it not in the EDT) but then, in the getParameter I add the JPanel to the main JFrame and I do it in the EDT (using invokeLater).
So, why there should be a problem?
An EDT violation doesn't mean something necessarily did go wrong, it means you tried to do a GUI related action on a thread other than the EDT (a situation where something might go wrong).
Creating a new Swing component is covered by "doing something GUI related", hence the warning about the violation.
This forum has quite a discussion on why it's not recommended to create Swing components on other threads.
Usually this will happen if you create any GUI components in the thread handed to you in main.
Now, in reality nothing bad will ever happen as long as you don't modify it after you've realized it (setVisible(true) or pack() will realize a frame), BUT Sun found some edge case that they claim make it so this can cause a problem.
So to be perfectly correct have your main construct your first window inside an invokeLater or invokeAndWait.
Actually, I wonder if exiting your main thread right after the invokeLater might allow your entire app to exit (since the window almost certainly hasn't had time to come up yet)... You might want to use invokeAndWait unless your main thread doesn't exit.
Swing is thread-hostile. Even if a component is not realised, it may still access shared resources or call EventQueue.invokeLater. There was a period when it was widely stated that Swing components could be created off the, but that was incorrect.
In addition to using the CheckThreadViolationRepaintManager I've been using an Aspect Oriented solution to detect when any Swing components are constructed off of the EDT. This is an elegant way to troubleshooting EDT violations if you use AspectJ.
See this blog post for details:
Debugging Swing, the final summary (from archive.org)

Categories

Resources