Is there a better way to handle close exceptions in a java try-with-resources close [duplicate]

With try-with-resources, we are guaranteed the resources will be closed, but if there is also a catch on the try, that catch will get either of the exceptions from the try block or the close() of the resources, (or both, with resources suppressed). We may want to very different things if the main try block succeeds and the resource close() fails. However, there’s not a good way to differentiate those cases in the catch. I’ve found a workaround (simplified here):

public class TryExample  implements Closeable {
    public static void main(final String[] args) {
        System.out.println("----- START -------");
        System.out.println("Results: ====================== " + readString());
        System.out.println("----- END -------");
    }

    static String readString() {
        String result = null;
        try (TryExample example = new TryExample()){
            result = example.read();
            return result;
        }
        catch(IOException e) {
            if (result != null) {
                System.err.println("Must have gotten an exception closing: " + e.getMessage());
                return result;
            }
            else {
                System.err.println("Must have gotten an exception reading: " + e.getMessage());
                return null;
            }
        }
    }
    
    public String read() throws IOException {
        //return "SOME READ RESULT";
        throw new IOException("EXCEPTION: ------- Some read exception");
    }
    public void close() throws IOException  {
        //throw new IOException("EXCEPTION: ------- Some close exception");
    }
    
}

Uncomment the return/throws for different cases.

Basically, it just uses the result to differentiate between an exception in the try block vs an exception in the resource close. (The solution could be generalized by wrapping the result so a null value could be a valid return value.)

This feels very clunky, but I’ve not found a cleaner solution. Is there a better way to do this? It seems that having catch handle both for the try block and for the resource close() is problematic, especially given that Closable implementations are typically going to have methods used within the try block that also potentially throw IOException.

So, is there a more straightforward way to express this now that try-with-resources has been around for a while? (Currently using Java 21.)

Thank you in advance.

UPDATE: This question was closed and indicated that it was a duplicate. However, the link provided:
Catch errors during object construction from try-with-resources separately from body references a question for the construction of a resource, not the close() of that resource. Both the title of my question and that of the provided title explicitly state their respective use: “close exceptions in a java try-with-resources close” vs “Catch errors during object construction”.

2

We may want to very different things if the main try block succeeds and the resource close() fails.

You’ve drawn that conclusion too hastily. It is, almost always, incorrect.

What meaningful difference is there?

I am writing data

If the distinction you are looking for is to differentiate between a write call causing an exception and a close() call, that is wrong. There is no meaningful distinction in semantics. It is incorrect to conclude that the data you ‘sent’ (via write) has actually ‘arrived’ (e.g. has actually appeared on disk). output resources buffer. Almost all of them do. Hence, write calls can succeed (because you’re just moving bits into a different part of memory somewhere), even if they are never going to actually get there: If write(someBytes) returns without error that does NOT mean the bytes have fully made it to the other side. In case you doubt this, simply refer to BufferedOutputStream. Its one and only job is literally to convert the majority of write() calls into pure memory blitting operations!

Hence, there are no good reasons to attempt to differentiate, and, indeed, the 2 methods (close() and write()) share virtually 100% overlap causes for exceptions and the messages that convey them. write() can fail due to disk full. close() can fail to disk full. If close() throws, you must assume that some preceding write() would have failed with that exact exception if only the buffer sizes were a little smaller. Hence, essentially by definition of the exception behaviour of close v. flush, caring about whether close() threw it, or write() threw it, is necessarily a bug.

We can recreate this easily:

var fos = new FileOutputStream("/mount/usb-stick/test.txt");
var out = new BufferedOutputStream(fos);
System.out.println("Yank the stick out now...");
Thread.sleep(10000);
out.write(1); // write one byte.
System.out.println("No exception? How did we get here??");
out.close(); // HERE, exception occurs

I am reading

This one is a lot more nuanced. The general theory is that if all your read() ops succeed, you have reached the end of the file by way of receiving -1 from your last read() call, then – so what. if the close() call fails, that’s immaterial and should therefore be handled differently (generally, by ignoring it completely).

But this isn’t a useful distinction. Because this never happens. There are 2 exceedingly exotic scenarios that don’t happen that you’re trying to cater to:

  • read() was lying to you; it returned -1, yes, but the underlying resource, whatever it might have been, is just wonkily set up. The read call doesn’t realize an error has in fact occurred, and instead returns -1, but close() (which, usually, is far less optimized; you call read() a lot more than close, after all!) does some extra legwork and determines properly that reading has, in fact, failed. The same principle applies – you should definitely not ignore that exception, nor deal with it differently.

  • close()‘s exception is lying to you and read() was not: For whatever reason, closing really is failing, but you have fully read the entire resource. This.. doesn’t happen. Or at least, it is extremely rare.

Hence, you might find that first case (read() lies!) so rare that you wash your hands of it and, if it ever occurs, will simply blame the implementors of the underlying resource for messing up their read() impl. However, that second case is even more rare.

See also this 2012 bug report about removing closeQuietly from guava – which explains also from the point of view of the guava team why they have, indeed, removed that method from guava entirely (in case your primary intent of ‘I want to handle exceptions in close() differently’ boiled down to ‘… I want to ignore them’).

7

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật