java.nio.channels.MembershipKey API

Alan Bateman Alan.Bateman at Sun.COM
Sat Nov 29 02:50:08 PST 2008


Thanks for being persistent on it. I'll think more about it. It may be 
that the right thing is that the drop method should not throw 
IOException. Off-hand, I cannot think of any reason why it can fail 
(except a bug). This is unlike close which might  need to fail when the 
object is a destination and buffered data could not be flushed.

A few comments inlined.

David M. Lloyd wrote:
> :
> FileLock and SelectionKey are, apart from other issues, already set in 
> stone as they are part of the JDK.  I don't think these two classes 
> have any bearing on MembershipKey as a new class.  
I mention these classes because we want consistency in the package. Each 
of these objects are obtained from channels and define methods that are 
named opposite to the action that obtained them.

> Consider this simple case:
>
> Jane User realizes that she frequently has to write code that looks 
> like this:
>
> SomeResource r = ...create...;
> try {
>     ...do stuff..
> } finally {
>     try {
>         r.close();
>     } catch (IOException e) {
>         log.error("Failed to close " + r, e);
>     }
> }
>
> Realizing that the finally block is boilerplate, she introduces a 
> static method on a util class:
>
> public static void safeClose(Closeable c) {
>     try {
>         c.close();
>     } catch (IOException e) {
>         log.error("Failed to close " + c, e);
>     }
> }
>
> Much typing and annoyance is saved.  
Yep, and there are many like Jane that have done exactly that. The 
Inputs#closeUnchecked method maybe useful for some of those cases (for 
input sources anyway, not output destinations where there may be unsent 
data).

> Everything is well and good until she runs across this new case:
>
> public void addMembership(DatagramChannel ch, InetAddress group, 
> NetworkInterface intf) throws IOException {
>     boolean ok = false;
>     MembershipKey key = ch.join(group, intf);
>     try {
>         ...send & receive some messages, and run some app logic, any 
> of which might fail...
>         ok = true;
>     } finally {
>         // rats.  if only I could use safeClose(), this whole thing 
> would be one simple, readable line
>         if (! ok) {
>             try {
>                 key.drop();
>             } catch (IOException e) {
>                 log.error("Failed to close " + key, e);
>             }
>         }
>     }
> }
This is certainly a valid annoyance although I would not expect 
membership to be as transient as this example might suggest. We've had 
many bug reports and sample applications using the legacy 
MulticastSocket over the years and most of the time the application 
joins the group at startup and doesn't ever leave. However, point taken.

>
> :
> Minor, but annoying.  This kind of thing happens far too much in the 
> JDK. Jane User already has the same method defined for selectors, 
> ZipFiles, Sockets, and ServerSockets, not to mention JDBC resources, 
> JDK logging handlers, MIDI stuff, etc.  Why perpetuate it to one more 
> class?  Just because it ends in *Key?  The usage pattern is the same.
There are indeed cases that were missed when java.io.Closeable was 
added. Jessie retrofitted Socket and ServerSocket some time ago for 
jdk7. We need to do Selector and ZipFile. I'm not sure about the others 
- for example, in java.sql there are close methods that throw 
SQLException and cannot be changed; in the MIDI package the close 
methods don't throw IOException so they can be changed either.

Thanks again for pushing on this one.

-Alan.





More information about the nio-dev mailing list