A few days ago, I had a really clever idea.
At least, it seemed like that at the time. In this post I’ll write about something that didn’t quite pan out as I’d hoped.
Some things I like to do with IBM MQ is to integrate it with other pieces of technology, expose some useful but little-known capability, or extend it in some way – wherever possible without actually changing the base product. Making extensions available mean that customers can try out additional function without necessarily needing to upgrade to a future version of the product. While the Continuous Delivery mechanism can mean a much shorter wait than before, it still requires someone to move to that level before the capability is usable.
Sometimes making one of these tools available can be a useful prototype to prove an initial concept works, even if it’s not as well-integrated as it might be. And that can then lead to a “real” implementation later. For example, the first version of MQ’s API Exits were made possible without changing any of the product code, but by playing games with the AIX runtime library linkages. Not pretty, but good enough to explore what the exit interface should look like. I was able to get feedback from a few people outside of MQ development based on real-life experiences before we locked down the API. And a couple of things in the MS0P SupportPac have since turned up in the real MQ Explorer code.
But sometimes these ideas just don’t work out.
One of the non-Explorer pieces of MS0P is an implementation of MQ’s pluggable Authorisation Service that simply writes to a log file. The idea behind writing that module was that it could a) give a worked example of how someone could write a “real” authorisation module that might replace MQ’s built-in OAM with a lot of explanations in the comments and b) by logging all the calls made to the OAM, you could see when auth checks were being made. My “clever idea” involved taking that skeleton code and (essentially) making it do some real work with MQ resources like queues and messages. Assuming it worked, it could go towards meeting a number of customer-raised RFEs.
While it was quick to get some build and test scripts written that would allow experimentation, once I started to work on code it became obvious that it would not be as simple as I’d hoped. For a start, the Authorisation Service interface does not pass through an hConn. Not really surprising, as part of the OAM’s job is to check whether the caller is allowed to create an hConn, but irritating. Worse is the fact that I couldn’t simply call MQCONN – given where we are in the calling stack at the time, and the environment where the code is running, regular MQI calls are simply not possible. And while I was able to think of a way around that, the whole thing started to get messier and messier, and more restricted. For example, the next iteration of my code would only work on Unix systems (not Windows). And then various synchronisation issues raised their heads. And then some other things around I/O and buffer sizes showed up. And then there were environment setups that had to be considered …
While I guess I might have been able to work round all of these with sufficient work, in the end it became obvious that I would not be able to create an easily-understandable piece of Open Source code that could be picked up and reused. I would probably have to reinvent a whole bunch of services that code within the queue manager can assume are already provided in its Common Services layer – serialisation and cross-process resource sharing for example.
So I’ve given up on that project for now. At least as far as providing something that would work in existing versions of MQ.
Is there a moral or lesson at the end of this story?
Perhaps one lesson is that sometimes things cannot be made to work, and you should cut your losses quickly. I didn’t spend too much time on trying out this stuff, so it wasn’t a lot of sunk time. Perhaps one day.
Another lesson is that even trying and failing can get you somewhere. I now know much more about what I would change (or get someone else to change!) inside the queue manager. The function I was trying to implement is definitely useful, but now I know a lot more about the environment in which it has to run. And I have already got information about what I want the output of that function to look like. And it really ought to be “easy” to implement in the guts of the queue manager. (Though of course it’s never that easy, especially when you include essentials like testing and documentation)
So while I couldn’t get things to work the way I wanted, perhaps it wasn’t a complete waste.