A: To uncover my hidden assumptions!
Let me tell you a story about SharePoint, Alfresco, design choices, and downloading files.
My Java-based application uses SharePoint 2010 to store files. CMIS is the obvious tool for my app to talk to SP 2010, and in fact, CMIS and SP2010 work just fine together, as you may have gathered from my colleague Tim Lisko’s last few articles.
So it came time for me to write the download feature, thus allowing users to download the files stored in SP2010 from my application. Chemistry makes it very easy to retrieve a file object by ID:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Override
public InputStream getFileContentStream(Session session, String objectId)
{
try
{
Document file = (Document) session.getObject(objectId);
ContentStream csFile = file.getContentStream();
InputStream retval = csFile.getStream();
return retval;
}
catch (CmisBaseException cbe)
{
throw new AcmRepositoryException("Could not get file contents",
cbe);
}
} |
So I said to myself: OK, I’ll just construct a URL including the CMIS object ID, then I’ll pass that object ID straight through to my Java method.
All you guys that have used CMIS against both Alfresco and SharePoint (hi Colin!) know what’s coming next.
SP2010′s object ID looks like this: 42-512. So my URL’s looked like this:
http://<host>/<context>/docs/download/2316/42-512
No problems here! A nice valid URL, and my download code worked great!
So yesterday, I had an idea (actually, my boss had the idea). Let’s stand up the app against Alfresco!
Alfresco’s object IDs turn out to look like this:
workspace://SpacesStore/ecd60ff9-adbb-45fb-824d-9bc93aa61b0f
Which turned my download URL into this grim-looking thing:
http://<host>/<context>/docs/download/2316/workspace://SpacesStore/ecd60ff9-adbb-45fb-824d-9bc93aa61b0f
I’ll leave what happened when I clicked that link to your imagination (hint: it wasn’t pretty!).
Since I wanted to be up and running on Alfresco pretty quickly, I applied a short-term fix: I replace the colons and slashes in the object ID with strings that should not be part of any real object ID, and my download controller reverses the process. Now my URLs look like this:
http://<host>/<context>/docs/download/2316/workspace-c!–s!–s!-SpacesStore-s!-ecd60ff9-adbb-45fb-824d-9bc93aa61b0f
The good: the download code works again. The bad: I shouldn’t have to encode and decode my own download URL this way! The ugly: as you can see, the aesthetics of the above URL leave a lot to be desired.
The long-term fix (by “long-term” I mean “by Monday”) is to not place the object ID in the URL in the first place, and use an opaque sequence-driven numeric database ID instead. Then all my URLs will look like this, no matter what repository is in use at the moment:
http://<host>/<context>/docs/download/2316/42
Why didn’t I do this in the first place? Well, I certainly should have. For the most part I would never use a natural key such as the CMIS object ID in this situation. I’m pretty sure I was trying to avoid a database lookup. In the end I needed to do a database lookup anyway, but it never occurred to me to rethink my earlier design choices.