Wolfgang Baltes wolfgang.baltes at
Mon Jan 10 13:48:24 PST 2011

On 2011-01-10 10:36, Alan Bateman wrote:
> Wolfgang Baltes wrote:
>> :
>> 1: WatchEvent.context(): it would be nice to get a complete path, not 
>> just a relative path. I can always build the relative path from a 
>> complete path, but the other way around forces me to store the parent 
>> path and do some extra work. /Complete path/ could be the 
>> concatenation of original or real (as in toRealPath) parent path that 
>> was used to obtain the WatchKey, and the name of the directory or 
>> file which caused the event. The original parent would probably be 
>> better because it maintains the information that was put into the 
>> system and one can always convert it to the real path.
> One of the things that has come up a few times is that WatchKey 
> doesn't define a method to get the original Watchable. We'd need to 
> set some expectations around that as there are implementations where 
> the watch is on the inode and isn't tied to the original path but that 
> aside, it would mean that you can resolve the file name against the 
> original watch and that would give you the path that you want (and 
> avoid needing to maintain the mapping yourself).
This would be fine with me.
>> 2: WatchService class: provide a isClosed() method. This is 
>> convenient when multiple threads need to share this knowledge. It is 
>> simpler than having to catch the ClosedWatchServiceException in one 
>> thread and then to propagate it to other threads. All other methods 
>> that throw this exception have some side-effect.
>> 3: Path class:
>> 3.1: It would be nice to have a getExtension() method.
>> 3.2: Same for getNameWithoutExtension() method.
>> 4: Path or Paths class: provide a static method that returns an empty 
>> Path array. See Item 43 in Joshua Bloch, Effective Java, Second 
>> Edition, page 201. I use this systematically, and am frustrated that 
>> I have to redefine empty arrays again and again, instead of having 
>> them in the base library.
> I can't think of anywhere in the API where we return null instead of 
> an empty array or empty collection, but there are a couple of methods 
> (getRoot, getName and getParent specifically) that return null when 
> the path doesn't have the component - is that what you are asking about?
My comments in item 4 were not specific to the NIO2 API, but are more 
general. For example, if somebody writes some code where he would return 
an empty array, then he has to define this array. If you write a 
collection of packages, you end up defining this array again and again 
(unless you have some "core" package). The idea here is to offer this 
feature in the base library, so that others don't have to create it. It 
may not be used in the NIO2 library itself. Of the NIO2 classes I have 
worked with, Path is the only one where this is likely to be of some 
help. The other class would be WatchKey, but this is more likely to be 
used in collections, for which there are already "empty" versions.

However, related to item 5 below, instead of returning null from getRoot 
and getParent, one could return the EMPTY_PATH path (= Path with zero 
elements; but not root), which could then be used in a normal execution 
path, when null would require special code. But then, I am not sure this 
is even possible with the current implementation as the root component 
"/" already has some characteristics of an empty path (zero length and 
null name) and this may already be exploited by your code, and it does 
not have a neutral behavior in most methods.

>> 5: It would be nice to have some predefined Path instances, such as 
>> the "." path (= current path), and possibly a "null" path. The first 
>> acts as an identity element (as in mathematical groups), because its 
>> effect is neutral to all relevant Path operations. The second is for 
>> use in Path collections which do not accept null. I understand that 
>> this is a little bit tricky if you want this instance to have special 
>> behavior in regard to some methods.
>> Another comment is relative to the documentation: almost all NIO 
>> methods throw IOException. That's a pretty large group of exceptions, 
>> many of which can probably appear at any time, but only a few of 
>> which have particular meaning in a specific context. For example, the 
>> watch events appear much faster than the file system finishes writing 
>> a file. The documentation says nothing about which exception I should 
>> expect if I try to access the file to soon (FileSystemException). I 
>> think that providing this type of information would help a lot of people.
> The API defines several specific exceptions for specific classes where 
> it may be useful to handle/recover. These are marked as "optional" and 
> you'll see them in the throws list of several methods (the reason they 
> are "optional" is that it's not always possible for implementations to 
> distinguish specific errors from other errors).
> For this specific case, I guess you are looking for additional wording 
> to make it clear that when you receive an event to indicate that a 
> directory entry has been modified that there is no guarantee that 
> whatever was changing the file has completed - is that right?
Yes! For example, the Javadoc for the WatchService says that "When an 
event is reported to indicate that a file in a watched directory has 
been modified then there is no guarantee that the program (or programs) 
that have modified the file have completed." However, there is no hint 
what to look for as an indicator to assure/wait for completion. When I 
started to work with the WatchService, I had to figure out which I/O 
exceptions were specific to this case, and then ended up catching 
FileSystemException as shown in this example where I try to retrieve a 
path's attributes:

             BasicFileAttributes attrs = null;
             for (;;) {
                 try {
                     attrs = Attributes.readBasicFileAttributes(path, 
                     return attrs;
                 catch (final FileSystemException fse) {
                     if (path.notExists()) {
                         throw fse;

I chose to catch FileSystemException (instead of IOException) because it 
seems to be broad enough to catch the cause for non-completion and then 
try to recover unless the path nonExists(), but not too broad to cause 
endless loops. All other possible exceptions are propagated to the 
calling code which can then decide whether there is a possibility to 
recover at a higher level.

In summary, the above mentioned Javadoc could/should alert the 
programmer to expect FileSystemException (and maybe others) to indicate 

And yes, I have noticed that some classes use very specific exceptions 
to indicate specific error conditions.
> -Alan
-------------- next part --------------
An HTML attachment was scrubbed...

More information about the nio-dev mailing list