Why is my HTML JTextPane beeping at me?

I'm sure I've had this problem before, and when I found the work-around, I was sure I'd got that far before, too. So here, for ease of web search, is why your HTML JTextPane sometimes beeps when you call setText, and what you can do about it.

If you look at the Swing source, you won't find any calls to Toolkit.beep, but you will find calls to its more socially acceptable cousin, LookAndFeel.provideErrorFeedback. The genius of that method is that, since the only parameter it accepts is a Component, you can't really provide any "feedback" fundamentally different from a beep. A visual bell, maybe, but a beep by any other name would still stink as error feedback. Why not just give the user a short electric shock?

Looking at the calls, some of them are less unreasonable than others. Trying to paste into a non-editable text component, for example, is a situation where you can probably guess what you've done wrong. You press a key and the computer beeps immediately and as a direct result of your key press. Hopefully the non-editable component is rendered in such a way that you can recognize your mistake and carry on.

Other calls, though, are not at all reasonable. Other calls are the moral equivalent of try { ... } catch (Exception ex) { /* do nothing. */ }, but just a little bit more annoying. In fact, there are places where the code does just "do nothing". Yet other places do something significantly more useful to the developer (and, eventually and transitively, to the end-user): they call printStackTrace.

I won't labor the point of libraries hiding failure. We all know it's wrong, and we can all name a variety of different solutions, any of which would be better than this.

What's the failure in this case? The problem is that down in the bowels of the HTML parsing code, a ChangedCharSetException is being thrown. It's a checked exception, which leads to the usual checked exception problem of it being handled by the wrong layer in the code, in an attempt to clean up the interface that the use of a checked exception messed up in the first place. The problem of detecting the character encoding in use is mentioned in the JavaDoc. You might wonder, though, why this would ever happen in real life: setText takes a String, so isn't the problem solved (or too late to solve) by that point? You might well wonder that. But whatever, if Swing's HTML-parsing code comes across an http-equiv META tag that tries to set the character encoding, you're in trouble. Microsoft Outlook/Exchange (I'm never sure who's guilty in that unholy alliance) always seems to explicitly specify some parochial Windows encoding, as do plenty of other common programs that generate HTML.

Luckily, there's an undocumented "IgnoreCharsetDirective" property you can set on your text component's Document to disable this. I don't know why it isn't documented, because if you need to deal with real-world HTML, you're almost certain to run into this problem. I also don't know why it doesn't default to true. Or why this isn't worth a printStackTrace rather than just a beep.

By the way, please don't use Boolean's constructor, like the people from the 1990s do in Sun bug 4233012 ("not a bug", apparently; just undocumented behavior that's been catching people out for eight whole years). Use this instead:

textComponent.getDocument().putProperty("IgnoreCharsetDirective", Boolean.TRUE);

I wonder how many people have fought this? I wonder how many people have given up on Swing's HTML rendering because of this? Too many, I'm sure. What a waste to put so much effort into really pretty good HTML rendering and then make it not work out of the box, and not even document how to make it work.

This isn't how the world ends. But if we all end up stuck with C#, not having focused on "making easy things easy" will be one of the bigger mistakes we look back and reflect on, too late.