DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Coding
  3. Java
  4. Try-Catch-Resource and the Exception.getSuppressed() Method

Try-Catch-Resource and the Exception.getSuppressed() Method

Eyal Lupu user avatar by
Eyal Lupu
·
Mar. 18, 13 · Interview
Like (0)
Save
Tweet
Share
8.22K Views

Join the DZone community and get the full member experience.

Join For Free

Java 7 is out there for such a long time now so this post is even not fashionably late but still there is one aspect of the try-with-resource construct which, in my opinion, is sometimes overlooked: In this post I would like to point out some behavioral change related to exception suppression which might affect code migrating from older Java versions.




Old Code

Let's assume the following pre-Java 7 code, for the example I assume a dummy OutputStream ('SampleStream') which throws IOWriteException when write() is invoked and IOCloseException when close() is invoked (both are faked exceptions derive from IOException). For the sake of the example both exceptions are always thrown - regardless of the state of the application/stream. Which exception would be thrown by the method below?

public void testTraditionalTryCatchWithExceptionOnFinally() throws IOException {
  OutputStream os = null;
  try {
    os = new SampleStream(); 
    os.write(0); // Throws IOWriteException 
  } finally {
    if (os != null) {
      os.close(); // Throws IOCloseException
  }
}

The invocation of os.write() throws IOWriteException which passed the control to the finally block. The os variable is not null so the os.close() method is invoked resulting in the IOCloseException. At that point the method execution ends throwing an instance of IOCloseException. A caller similar to the one below will print 'Failed to closed stream'.

try {
 testTraditionalTryCatchWithExceptionOnFinally();
} catch (IOWriteException e) {
 System.out.println("Failed to write to stream");
} catch (IOCloseException e) {
 System.out.println("Failed to close stream");
} catch (IOException e) {
 System.out.println("Error working with the stream");
}

Migrating to Try-catch-resource

The method above using a try with resource block would be written as

public void testJava7TryCatchWithExceptionOnFinally() throws IOException {
 try (OutputStream os = new SampleStream(true)) {
  os.write(0); // Throws IOWriteException
 }
}

Indeed more elegant and a very easy conversion of the code - however there is an important nuance from the caller point of view: the try-catch-resource version of the method throws IOWriteException rather than IOCloseException. Obviously the caller illustrated few paragraphs above will change its behavior when using the migrated version of the method. So what had seemed to be a naive internal method change becomes now a contract change.



What can be done: document and getSuppressed()

First thing is to be aware of that change - and to consider if this internal change in the method does worth it. If it is decided to do the change we should track down all usages of the modified method and to see if any changes need to be done. However in real life this is not always easy: in large projects or if the modified method is a part of a library provided to other projects (so there is no visibility  on who is using it) we should also include an explicit notification of that behavior change in the library documentation/release notes. Once the change is communicated with other developers they can use the getSuppressed() method to drill down into the different use cases. The try-catch-resource block does expose the suppressed exception using the new (since Java 1.7) getSuppressed() method. This method returns all of the suppressed exceptions by the try-catch-resource block (notice that it returns ALL of the suppressed exceptions if more than one occurred). A caller might use the following structure to reconcile with existing behavior

try { 
  testJava7TryCatchWithExceptionOnFinally(); // This is the method illustrated above
} catch (IOException e) {   
  Throwable[] suppressed = e.getSuppressed();
    for (Throwable t : suppressed) {
    // Check T's type and decide on action to be taken
  }
}

Not the most elegant solution I could think about - but still one of those things Java developers must be aware of.

And one last thing

Just another example on the importance of good unit test coverage which can promptly identify that kind of  'hidden changes'.

[some sample code for try-with-resource is at https://github.com/eyal-lupu/eyallupu-blog/tree/master/Java-SE/src/test/java/com/eyalllupu/blog/java7/trywithresource]
unit test Blocks Java (programming language) dev POST (HTTP) Library Execution (computing) Visibility (geometry) Drill

Published at DZone with permission of Eyal Lupu, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • How To Choose the Right Streaming Database
  • Testing Level Dynamics: Achieving Confidence From Testing
  • Microservices Testing
  • Using Swagger for Creating a PingFederate Admin API Java Wrapper

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: