The Code Jedi

Using OData from Objective-C - Fixing the odatagen NSRangeException bug

Lately, I've been working on getting a small sample project up and running on the iOS platform, and using an OData endpoint for external data access. Fortunately, the OData site is an incredibly useful resource for a vast array of information, from both the publisher and consumer perspective. There is even an office Microsoft OData helper project for Objective-C which lives over on Codeplex.

Part of this toolkit is an incredibly indispensible tool, which in its simplest form, can generate your entity classes (.h and .m files) from the OData Metadata. So in theory, if you wanted to generate the entities for the Netflix catalog API, all you need to do is call it as such:
./odatagen /uri=http://odata.netflix.com/Catalog/ /out=~/Projects/MyNetflixApp

Unfortunately, the utility does have a few issues, one being critical. Some times, when executing it, you would get a bunch of text noise on the screen, the last bit of which was slightly alarming, when it partly reads:

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSPathStore2 substringToIndex:]: Range or index out of bounds'
*** Call stack at first throw: <snip>

Some searching online did turn up that this was the issue (work item #10949) and workaround, but a workaround isn't a permanent solution. For the record, the problem is as such. It is necessary that the executable exist in a folder, which is a descendant folder to one called "build", since it looks for stylesheets in the parent folder of said "build" folder. So your structure would have to end up being something along these lines: "~/utilities/build/odatagen", rather than simply living in the "utilities" directory, where the XSL files would exist. And for even odder reason, the utility would only work once, when I managed to get it going magically, until it stopped working completely, until I re-extracted the source package. Something is definitely amuck!

After some digging through the code, and a few false starts, I finally resolved the issue, and tidied up the code a little bit through some refactoring, so that the XSL files and the executable can both live in the same directory, which can be referenced in the path environment variable. Another issue which was hampering my debugging was that the entire downloaded metadata contents and HTTP headers would be printed to the screen during execution! Seriously (work item #11015)! This was the source of all the noise that I encountered at every execution!

As far as needing to re-extract the package every time the application ran successfully, a very simple yet very high impact issue was at play. A required stylesheet ("objc_filename.xsl" for those interested) was being deleted from the drive after it was being used. Why? I honestly couldn't say, but I do have a theory. Every other stylesheet used (5 in all) also had a delete operation associated with it, but all of the others were commented out. Perhaps the original intent (and what I was planning on doing at some point as well), was to embed the stylesheets within the application, so that only 1 file needs to move around. At execution time, the stylesheets could be temporarily written to the disk to be used (or permanently if they don’t exist in the current folder), and then harmlessly deleted at any time.

And so, if you have been trying to use the provided Objective-C client for OData, and have also run into these issues, I hope this has been of help to you. Feel free to download my proposed patch to issues #10149 and 11015, I think it will help!

Cheers!