[JAVA-605] NullPointerException on DBCursor.hasNext() when cursor is closed Created: 18/Jul/12 Updated: 19/Oct/16 Resolved: 30/Jan/14 |
|
| Status: | Closed |
| Project: | Java Driver |
| Component/s: | API |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | Sushil Thampy | Assignee: | Jeffrey Yemin |
| Resolution: | Done | Votes: | 1 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
Linux Ubuntu 11.04, mongod 2.0.5 |
||
| Issue Links: |
|
||||||||
| Description |
|
When iterating over a DBCursor using standard hasNext()/next() logic, hasNext() can raise a NullPointerException when the underlying server-side cursor has been closed. This happens in my code because I wrap the DBCursor in another Iterator that provides "batching": Iterates over the DBCursor generating a list of objects instead of a single object. I has been able to trace the issue to the following code fragments in DBApiLayer:
Please the documentation tells the hasNext() method can throw a MongoException and there are some issues that deal with this API issue. |
| Comments |
| Comment by Jeffrey Yemin [ 30/Jan/14 ] |
|
Fixed in scope of |
| Comment by Jeffrey Yemin [ 24/Jan/14 ] |
|
lllegalStateException is the more correct exception to throw here. InterruptedException has a pretty specific meaning that does not seem to apply here. |
| Comment by raulvk [ 08/Jul/13 ] |
|
I suggested borrowing InterruptedException due to the multi-threading aspect of this problem. This NPE only happens when the DBCursor is closed from another thread while it's blocked waiting for results. From a logical standpoint, I equate this situation to an interruption of Thread.sleep(), which throws an InterruptedException. I would argue against a generic MongoException, because that can mean anything and could potentially trigger client logic to regenerate the cursor. Especially in this context given that, AFAIR, MongoDB reserves its right to close a tailable cursor server-side. So more likely than not, nicely programmed clients would have implemented regeneration logic. Perhaps a MongoException.CursorClosedException would work, if you'd rather not use a standard JDK exception? |
| Comment by Jeffrey Yemin [ 08/Jul/13 ] |
|
I agree about the NPE, but what's the precedent for InterruptedException? Calling Socket.close(), for example, doesn't result in pending reads throwing InterruptedException. You just get a generic SocketException. Similarly, I would argue for a generic MongoException in this case. |
| Comment by raulvk [ 07/Jul/13 ] |
|
I'm a committer in the Apache Camel project, and I've come across this NPE when upgrading from 2.9.1 to 2.11.2. I see this exception from the Java driver when stopping a Camel route that was consuming from a MongoDB tailable cursor (camel-mongodb component) and was blocked at DBCursor#hasNext. IMHO, a NPE is a sign that the developer forgot to handle a situation gracefully (!). Furthermore, this NPE is not part of the contract of the DBCursor#hasNext method. Can 10gen improve the driver to detect this case and throw a standard InterruptedException instead? The latter is self-explanatory and accurate for this case. It's extremely inelegant for us to have to catch a NPE |
| Comment by Jeffrey Yemin [ 27/Aug/12 ] |
|
It does seem to be the case that if you call DBCursor.hasNext() after calling DBCursor.close(), it will throw an NPE. But I don't quite see why this is a problem in practice, except that maybe it should throw a different exception type. |