|
Replies:
20
-
Last Post:
Nov 6, 2008 2:52 PM
by: kirillcool
|
Threads:
[
Previous
|
Next
]
|
|
|
|
|
|
JApplet instantiation outside of EDT
Posted:
Oct 29, 2008 6:36 AM
|
|
|
Hi all, I have recently been stuck with a problem with one of my application which is an applet. The problem was encountered when I attempted to use the Substance look and feel (https://substance.dev.java.net/), whose author is very adamant about adhering to Swing's rule of creating components inside EDT (event dispatching thread) only, and will throw exceptions if this rule is violated. Below is the call trace that illustrates the problem (Java plugin 1.6.0_10-rc on Fire Fox 3, Ubuntu8.04 x86 + Win XP x86).
org.jvnet.substance.api.UiThreadingViolationException: Component creation must be done on Event Dispatch Thread at org.jvnet.substance.utils.SubstanceCoreUtilities.testComponentCreationThreadingViolation(SubstanceCoreUtilities.java:2312) at org.jvnet.substance.SubstancePanelUI.createUI(SubstancePanelUI.java:57) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at sun.reflect.misc.Trampoline.invoke(Unknown Source) at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at sun.reflect.misc.MethodUtil.invoke(Unknown Source) at javax.swing.UIDefaults.getUI(Unknown Source) at javax.swing.UIManager.getUI(Unknown Source) at javax.swing.JPanel.updateUI(Unknown Source) at javax.swing.JPanel.<init>(Unknown Source) at javax.swing.JPanel.<init>(Unknown Source) at javax.swing.JPanel.<init>(Unknown Source) at javax.swing.JRootPane.createGlassPane(Unknown Source) at javax.swing.JRootPane.<init>(Unknown Source) at javax.swing.JApplet.createRootPane(Unknown Source) at javax.swing.JApplet.<init>(Unknown Source) at FusionLogIn.<init>(FusionLogIn.java:29) <------ My applet's constructor. at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at java.lang.reflect.Constructor.newInstance(Unknown Source) at java.lang.Class.newInstance0(Unknown Source) at java.lang.Class.newInstance(Unknown Source) at sun.plugin2.applet.Plugin2Manager.createApplet(Unknown Source) at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source) at java.lang.Thread.run(Unknown Source)
If this is a bug in the Java plugin implementation, how would one go about getting it to the development team?
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Oct 29, 2008 7:26 AM
in response to: haihovu
|
|
|
Just curious, but can you post the code for your applet's constructor?
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Oct 29, 2008 7:38 AM
in response to: dkkopp
|
|
|
Below is an excerpt (there is not much to it, which is the way it should be), the exception was thrown in the call to super() when the applet is reloaded after the first instantiation (say when the page is reloaded or reopen in a new browser tab/window). On first instantiation no exception is thrown since the look and feel had not been set.
public FusionLogIn() { super(); MiLookAndFeel.setCurrentLookAndFeel("Substance Creme Coffee"); }
The custom code MiLookAndFeel.setCurrentLookAndFeel("Substance Creme Coffee"); uses the EDT to do its work.
|
|
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Oct 29, 2008 8:07 AM
in response to: sauvage
|
|
|
That makes no difference since the L&F is set using EDT (SwingUtilities.invokeAndWait) anyway. Plus the exception is thrown from inside super(), before the L&F set code is executed.
Note that this exception is thrown on second/third... instantiation of the applet after the L&F had been set in the first instantiation.
In any case the plugin should not invoke the applet's constructor from outside of the EDT.
I currently had to use a different look and feel that does not enforce this rule.
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Oct 29, 2008 3:10 PM
in response to: haihovu
|
|
|
"For legacy reasons," applets are constructed and their lifecycle methods called on an applet thread (which is not the EDT).
In fact, if init was called from the EDT, then correctly written applets would throw an Error from a call to EventQueue.invokeAndWait.
The obvious fixes would be to override JApplet.createRootPane and delay creation, or use some form of proxy look and feel which doesn't install the real PL&F until later in this case.
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Oct 30, 2008 7:08 AM
in response to: tackline
|
|
|
Given this fact, I think a bug report could be submitted to substance.
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Oct 30, 2008 8:42 AM
in response to: sauvage
|
|
|
> Given this fact, I think a bug report could be submitted to substance.
As the developer of Substance, i have my reservations about calling this a "bug report". Unless Swing team comes forward and makes a very clear and official statement about the EDT rule in general, and about the applet environment in particular, i don't see this as a bug in Substance.
Thanks Kirill
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Nov 6, 2008 1:57 PM
in response to: kirillcool
|
|
|
Hi,
I deeply agree with you, in fact I think this is a bug in plugin implementation. But you know, it is sun code (I won't go further), then is there an option to disable the call from EDT check in substance ?
Best regards,
Laurent.
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Nov 6, 2008 2:09 PM
in response to: sauvage
|
|
|
If you really believe it is a bug in the plugin then I would suggest you report it: http://bugs.sun.com/
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Nov 6, 2008 2:33 PM
in response to: cowwoc
|
|
|
Well I said I won't go further but you make me lie. My feeling is that submitting bugs to sun is often useless, so my last question to kirill was: is it possible in substance to disable the EDT call check, because it looks easier to workaround the applet lifecycle bad behaviour into substance code than into core applet plugin code.
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Nov 6, 2008 2:49 PM
in response to: sauvage
|
|
|
The plugin just underwent a major rewrite. What makes you think they won't fix yet another bug?
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Nov 6, 2008 2:52 PM
in response to: sauvage
|
|
|
> so my last question to kirill was: is it > possible in substance to disable the EDT call check, > because it looks easier to workaround the applet > lifecycle bad behaviour into substance code than into > core applet plugin code.
I do not have plans to provide a workaround for this scenario. The code is licensed under BSD so you're welcome to remove this check in your private build (and then continue syncing the main CVS repository for all new features and bug fixes).
Thanks Kirill
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Oct 30, 2008 9:08 AM
in response to: tackline
|
|
|
I tried the suggestion with over-riding createRootPane(), which boils down to calling SwingUtilities invoke and wait, which stores the JRootPane in a variable which is retrieved by the calling thread. This didn't seem to work out. The first instantation was fine, but when the page was reloaded the invoke and wait invariably gets interrupted, no matter how long the wait, it's as though when the applet is reloaded, the EDT is dead-locking with the applet creation thread.
In any case I do see the points on both sides; there is the Swing rule, and then there is the legacy implementation. I hope this is resolved at some point soon 'cause I do like Substance but for applets it will have to be something else for now.
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Oct 30, 2008 9:45 AM
in response to: haihovu
|
|
|
Substance works fine in my test applet (code below). I don't do anything in the class constructor, but override the applet lifecycle methods (like init()) to do the work, and also call invokeAndWait().
import java.awt.FlowLayout;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class TestApplet extends JApplet {
public void init() {
super.init();
Runnable r = new Runnable() {
public void run() {
setLookAndFeel("org.jvnet.substance.skin.SubstanceCremeCoffeeLookAndFeel");
createGUI();
}
};
try {
SwingUtilities.invokeAndWait(r);
} catch (Exception e) {
e.printStackTrace();
}
}
public void setLookAndFeel(String laf) {
try {
UIManager.setLookAndFeel(laf);
} catch (Exception e) {
e.printStackTrace();
}
}
public void createGUI() {
getContentPane().setLayout(new FlowLayout());
getContentPane().add(new JLabel("test label"));
getContentPane().add(new JTextField(15));
getContentPane().add(new JCheckBox("checkbox"));
getContentPane().add(new JRadioButton("radiobutton"));
getContentPane().add(new JButton("button"));
}
}
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Oct 30, 2008 10:02 AM
in response to: macintyrei
|
|
|
This only occurs in later Substance releases, e.g. 5.0, and only when the applet is reloaded, when you reload the web page, or when you open up another instance of the applet in another browser tab or window.
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Oct 30, 2008 10:08 AM
in response to: haihovu
|
|
|
I see what you mean. It works ok the first time, but subsequent reloads give the stacktrace you detailed earlier.
The only workaround I can think of would be to use java6u10 and force each applet to run in a separate jvm - although that may not be desirable for you.
<PARAM name="separate_jvm" value="true">
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Oct 30, 2008 9:17 AM
in response to: haihovu
|
|
|
Why can't you use SwingUtilities.invokeLater()?
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Oct 30, 2008 9:59 AM
in response to: cowwoc
|
|
|
Did both, invokeLater, invoekAndWait, put in my own wait, use sleep in stead of wait, ... no go.
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Oct 30, 2008 10:06 AM
in response to: haihovu
|
|
|
What stack-trace did you get when you used invokeLater()?
|
|
|
|
|
|
|
|
Re: JApplet instantiation outside of EDT
Posted:
Oct 30, 2008 10:52 AM
in response to: cowwoc
|
|
|
Below is a trace (behaviour is slightly different each time but the below is the most common):
java.lang.InterruptedException at java.lang.Object.wait(Native Method) at java.lang.Thread.join(Thread.java:1143) at java.lang.Thread.join(Thread.java:1196) at sun.applet.AppletPanel.run(AppletPanel.java:404) at java.lang.Thread.run(Thread.java:619) java.lang.InterruptedException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:485) at java.awt.EventQueue.invokeAndWait(EventQueue.java:992) at javax.swing.SwingUtilities.invokeAndWait(SwingUtilities.java:1323) at FusionLogIn.createRootPane(FusionLogIn.java:70) at javax.swing.JApplet.<init>(JApplet.java:134) at FusionLogIn.<init>(FusionLogIn.java:62) <<<----- My constructor at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at java.lang.Class.newInstance0(Class.java:355) at java.lang.Class.newInstance(Class.java:308) at sun.applet.AppletPanel.createApplet(AppletPanel.java:786) at sun.plugin.AppletViewer.createApplet(AppletViewer.java:2108) at sun.applet.AppletPanel.runLoader(AppletPanel.java:715) at sun.applet.AppletPanel.run(AppletPanel.java:369) at java.lang.Thread.run(Thread.java:619)
And here is my kludge:
/*
|
|
|
|
|