JDK-6502558 : AbstractDocument fires event not on Event Dispatch Thread
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 6
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2006-12-08
  • Updated: 2011-04-28
Description
All Swing listeners must be notified on Event Dispatch Thread
please see http://java.sun.com/products/jfc/tsc/articles/threads/threads3.html

"Swing components will generally not comply with the single-thread rule unless all their events are sent and received on the event-dispatch thread. For example, property-change events should be sent on the event-dispatch thread, and model-change events should be received on the event-dispatch thread."

But following example shows that document listener notifications clearly break this rule
(don't forget to set proxy settings properly)

Current behaviour:
DocumentListener notifications are sent from the wrong thread

Expected behaviour:
DocumentListener notifications must be sent from Event Dispatch Thread only


import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import javax.swing.text.html.HTMLEditorKit;
import java.awt.*;
import java.io.IOException;
import java.net.URL;
import java.util.Properties;

/** @author JohnM */

public class EditorPaneEDTViolation extends JFrame{
    static JEditorPane msgArea;

    public EditorPaneEDTViolation() {
        setTitle("EDT Violations R Us");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        msgArea = new JEditorPane();
        JPanel p = new JPanel();
        p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
        p.add(msgArea);
        add(p, BorderLayout.CENTER);

        setBounds(100, 100, 800, 600);
    }

    public static void main(String[] args) {

        Properties systemproperties = System.getProperties();
        systemproperties.put("proxyHost",
                             "yourcache");// http proxy server
        systemproperties.put("proxyPort",
                             "80");              // http port #
        systemproperties.put("proxySet","true");

        System.setProperties(systemproperties);

        EventQueue.invokeLater(new Runnable(){
            public void run(){
                final EditorPaneEDTViolation epv = new EditorPaneEDTViolation();
                epv.setVisible(true);
                try {
                    msgArea.setEditorKit(new HTMLEditorKit() {
                        public Document createDefaultDocument() {
                            Document doc = super.createDefaultDocument();
                            doc.addDocumentListener(new DocumentListener() {
                                public void insertUpdate(DocumentEvent e) {
                                    if (!SwingUtilities.isEventDispatchThread()) {
                                        System.out.println("Error !!!");
                                    }
                                }

                                public void removeUpdate(DocumentEvent e) {
                                    if (!SwingUtilities.isEventDispatchThread()) {
                                        System.out.println("Error !!!");
                                    }
                                }

                                public void changedUpdate(DocumentEvent e) {
                                    if (!SwingUtilities.isEventDispatchThread()) {
                                        System.out.println("Error !!!");
                                    }
                                }
                            });
                            return doc;
                        }
                    });
                    msgArea.setPage(new URL("http://www.google.com"));

                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }
}

Comments
EVALUATION The current design is to send the notification on the same thread the document was modified I suggest to modify the document on EDT
13-12-2006

EVALUATION The test case correctly works with Swing from EDT, so it is really surprising that the listener is notified from another thread
11-12-2006