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