Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 284265 - [JFace] DialogSettings.save() silently ignores IOException
Summary: [JFace] DialogSettings.save() silently ignores IOException
Status: VERIFIED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.4.2   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.6 M4   Edit
Assignee: Susan McCourt CLA
QA Contact: Susan McCourt CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-07-22 09:35 EDT by Marc R. Hoffmann CLA
Modified: 2009-12-08 14:19 EST (History)
4 users (show)

See Also:


Attachments
DialogSettingsTest.java (806 bytes, text/plain)
2009-07-22 09:37 EDT, Marc R. Hoffmann CLA
no flags Details
patch.txt (7.35 KB, patch)
2009-10-12 09:27 EDT, Marc R. Hoffmann CLA
susan: iplog+
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Marc R. Hoffmann CLA 2009-07-22 09:35:16 EDT
Build ID: M20090211-1700 (Problem still in HEAD)

STEPS TO REPRODUCE

Call DialogSettings.save() on a Writer that produced a IOException or with a file which causes trouble during output (e.g. full drive).

EXPECTED

The original exception thrown by the underlying output should be propagated to the caller -- as "save() throws IOException" suggests.

ACTUAL

The IOException is silently ignored.

ANALYSIS

The internal DialogSettings.XMLWriter is based in a java.io.PrintWriter, which catches all IOExceptions.
Comment 1 Marc R. Hoffmann CLA 2009-07-22 09:37:08 EDT
Created attachment 142267 [details]
DialogSettingsTest.java

Added a test case to reproduce the problem.
Comment 2 Marc R. Hoffmann CLA 2009-10-12 09:27:04 EDT
Created attachment 149360 [details]
patch.txt

This patch fixes the issue. The XMLWriter is now based on a BufferedWriter instead of a PrintWriter.
Comment 3 Susan McCourt CLA 2009-10-21 17:48:27 EDT
First of all, thanks for the test case and patch.  Much appreciated!  It makes fixing and verifying the bug much simpler.

Except in this case there's an API breakage technicality.

The problem I have is that this patch introduces a throws IOException clause into the public API for DialogSettings.  
	public void save(Writer writer) 
becomes
	public void save(Writer writer) throws IOException

I realize that the interface definition for IDialogSettings defines the throws clause, but today it's possible to write code like this:

	DialogSettings settings = new DialogSettings("test");
	settings.save(myWriter);

The patch means this code would no longer compile and clients would have to add the try/catch.  If DialogSettings were an internal implementation class, this kind of change would be ok, but the implementation class is public, too.  I noticed this because I wanted to run the old dialog settings against the new test case to verify the breakage, but I got an "unreachable catch block" error in the code, thus realizing I could compile code without the catch block in the old case, but not in the new case.

To further complicate things, I checked the CVS history to see how long the implementation had existed without the throws clause.  Turns out (sigh) that DialogSettings.save(Writer) has thrown an IOException since Eclipse was released, but this throws clause was removed early in 3.5 development to fix a compiler warning.

So technically speaking, we relaxed the API in 3.5 (possibly causing downstream clients new compile warnings for unreachable catch blocks), and this patch would restore it to the 3.4 (and prior) method signature, forcing callers to catch the exception.

Since we seem to have changed it casually in 3.5 (there is no bug number on the commit), perhaps we can casually change it back for 3.6.  but I'd like to understand better the actual use case (what kind of writer were you using, etc.) to justify the change.

The SDK uses the save(String fileName) method which is propagating the expected exceptions.

cc'ing Boris for comment.  Am I being too paranoid?
Comment 4 Marc R. Hoffmann CLA 2009-10-22 04:13:25 EDT
The Use Case comes from a major RCP deployment at the Swiss Railroad (SBB), where it tooks me some time to debug the reason, why dialog settings are sometimes not persisted. It's more or less a typical enterprise setup.

1) The workspace is on the user's home share (no write access elsewhere).
2) The users home share is a network share with quota.
3) The quota limit is reached.

In this situation it is possible opening a FileOutputStream, but not writing to it. On the share a file with 0 bytes is created.

AFAIK the network shares in our scenario are backed with Netapp appliances.
Comment 5 Susan McCourt CLA 2009-10-22 20:11:01 EDT
Moving to M4 as this is my last day to work on new stuff for M3.
I consulted http://wiki.eclipse.org/Evolving_Java-based_APIs_2 for the rules of engagement here.

It indicates that adding or removing checked exceptions from API methods is considered "Breaking" but the footnote says 

(1) Adding and deleting checked exceptions declared as thrown by an API method does not break binary compatibility; however, it breaks contract compatibility (and source code compatibility). 

But the bottom line is that we *already did this* in 3.5 by removing the throws clause and the correct behavior is to throw the exceptions and restore the clause.

Boris, can you confirm if it's OK to break source compatibility from 3.5 to 3.6 if the breakage from 3.4 to 3.5 was unintentional/accidental?
Comment 6 Boris Bokowski CLA 2009-10-25 07:28:14 EDT
Right, the change would be binary compatible but not source compatible.

Specifically, clients moving from 3.4 to 3.5 will have to get rid of a try..catch if they recompile. And then, if they move from 3.5 to 3.6, they will have to add the try..catch again (if they recompile). Clients moving from 3.4 to 3.6 won't have to do anything.

What a mess! 

Is there a way for clients to use IDialogSettings (and not DialogSettings) if they want to avoid the fallout? If yes, I would be leaning towards allowing the source incompatibility as you suggest, Susan, with an entry in the porting guide that gives recommendations for what to do.
Comment 7 Susan McCourt CLA 2009-10-25 11:32:32 EDT
(In reply to comment #6)
> Is there a way for clients to use IDialogSettings (and not DialogSettings) if
> they want to avoid the fallout? If yes, I would be leaning towards allowing the
> source incompatibility as you suggest, Susan, with an entry in the porting
> guide that gives recommendations for what to do.

Fortunately the mainstream use cases (AbstractUIPlugin, Wizard, Dialog,  etc.) that use dialog settings use IDialogSettings   (I imagine that's why the source incompatibility snuck in during 3.5 without anyone noticing.)  AbstractUIPlugin manages the creation, loading, and saving.  

The issue is simply that the concrete implementation is available as API, so it's possible for clients to run into this.  

I'll fix during M4.
Comment 8 Susan McCourt CLA 2009-12-02 17:33:52 EST
Fixed in HEAD >20091202.
I also added a section to the "incompatibilities" document explaining the source incompatibility.  Thanks again, Marc.
Comment 9 Susan McCourt CLA 2009-12-02 17:34:49 EST
Comment on attachment 149360 [details]
patch.txt

This patch contains the fix and test.
Comment 10 Susan McCourt CLA 2009-12-08 14:19:10 EST
verified on WinXP, Build id: I20091208-0100
- checked source
- checked incompatibilities guide
- automated test case has been passing (and passed in I20091207-1800, results not available on this build yet)