Another stupid mistake has taken a lot of my time last week. I developed a small library to provide function(s) to move attachments from rich text fields to separate db (nsf or some other). This function was supposed to be part of bigger process, so saving of document being processed was meant to happen in other code. That is why I had not tested what
doc.save() would do. My tests were just checking destination db for created records containing moved files. Other part of process was developed by colleague of mine, he tested his part expecting my function to return true or false. And the function was returning true or false. But when his code started to call real implementation of my function, our server crashed with nice and reassuring
PANIC: LookupHandle: handle out of range.
At first I was thinking "all tests are green" therefore mistake is not in my code. Stupid, right? But hey, calling just my function did not crash the server.
But the same was true for his part of code.
So we started to track down the exact place where error was by turning on debug logging and adding some more log calls, checking server console and even reading those stack trace logs and heap dumps and I have to tell you these are not easy to read and understand. After a while we were sure trouble is caused by
doc.save() call that occurred at the final step of the whole process. And that it crashed the server only if my function was called before.
Ok, that was time to admit I am the one to be blamed. So I started to review code in my library trying to find something that could cause such big trouble to server. I recycled every object, checked all variables for null before accessing them even when I was assigning some hardcoded value to them on the line above...you know the usual desperate stuff you do when you have no idea where the bug is. I would even try black magic, if I know it :-)
I was of course searching internet for help but my problem seemed to be completely new. How I hate when this happens!
Long story short: I was accessing data in fields of type MIME_PART, just reading from them via
doc.getMIMEEntity(fieldName). Then I was looping through mimeEntity via
getNextEntity looking for attachments and copying them to the destination db. And then I was calling
doc.removeItem(fieldName) to remove already processed fields in the document. But I forgot to call
doc.closeMIMEEntities(false, fieldName) before calling
doc.removeItem. And following
doc.save() call crashed the server.
There is code example in documentation. There is no
doc.closeMIMEEntities() call. But there is also no
doc.save() there and no
Moral of the story? Do not read just part of documentation you think is relevant. Read also related info. There is in fact a need of
doc.closeMIMEEntities() call mentioned here.
And even if you think you have fulfilled the contract (API we have agreed on) and your code is fine, it in fact could not be true. Writing tests and test driven development in general is extremely helping but even this great approach can not save you from your mistakes. Because it is usually you writing the tests.