Search code examples
javaiotimeouttimeoutexceptionlockfile

What is the best exception type to use for an I/O timeout?


I've written a Java class that implements a "lock file" to prevent a period job from running more than once concurrently. It's based upon java.nio.channels.FileChannel.tryLock and works quite well.

My class allows client code to supply a timeout value indicating how long it's willing to wait for the lock file to become available, and if a timeout occurs, I'm throwing an IOException. This also works quite well.

But I'm wondering if there is a better exception type to be using, since IOException is fairly generic. Client code catching an IOException wouldn't be able to know if the problem was due to e.g. the timeout itself or some other issue with the filesystem, etc. (unless that other issue throws a subclass of IOException of course).

Briefly leafing through the Java API, I see some candidates but I don't really like any of them for various reasons:

  1. java.util.concurrent.TimeoutException (this isn't really a "concurrent" usage)
  2. java.nio.channels.FileLockInterruptionException (docs indicate a very specific reason for this exception; doesn't match my case)
  3. java.nio.channels.InterruptedByTimeoutException (similar reasons to above)

Any suggestions?

I'd prefer something that is available back to Java 7 if possible.

EDIT

Obviously, a custom exception class is possible, but I was wondering if there was something in the standard API that would be appropriate.


Solution

  • I think that java.util.concurrent.TimeoutException is appropriate. The javadoc says:

    "Exception thrown when a blocking operation times out. Blocking operations for which a timeout is specified need a means to indicate that the timeout has occurred."

    Your method that is calling trylock is a blocking operation in the sense that is envisaged by the authors.

    You say: "this isn't really a "concurrent" usage" ... but that depends on your perspective. You are using a Lock API, and that interface is declared within the java.util.concurrent package tree. And presumably you are designing your API so that it can easily be used in a concurrent application. (And if not ... why not?)


    IMO, the only good argument for using IOException or an existing or custom subclass of IOException would be if the client operation is modeled as an I/O operation. For instance, if the API uses I/O exceptions to signal other things.

    Another argument against using IOException is that it is too general. It says the the caller of your API method(s) "you need to be prepared for any IOException". That includes all sorts of exceptions that your current implementation won't throw, but a future one might.


    The other alternative is to declare your own custom exception class that is not a subclass of IOException. On the face of it, that appears better than an I/O exception.


    As for the "implementation detail" issue, the class is designed and documented to use an on-disk file as a locking mechanism. So while it definitely is an implementation detail, it's the definition of the implementation, interface, etc. so I think IOException is at least not inappropriate.

    I would argue that it is a bad idea to specify an API like that. Suppose that you decide later on that another kind of locking might be more appropriate. If you have specified the locking details in the interface, you can't change them. Or at least, not without "rewriting the contract" in a way that could break an existing client of the API.