For some reason the other day I was thinking “Whatever happened to that renegade members feature?” So I did some digging.
Renegade members, by the way, refers to this concept where instead of a data record being rejected, you can map it to some other member. Other names for this feature might have been “shovel members”, but renegade members sounds cooler. That said, it’s a feature with a cool name but an apparently terrible publicist.
Renegade members were blogged about as early as a few years ago, such as on Cameron’s blog (during the 2013 OpenWorld), in Russian (apparently), and even over at Rittman Mead’s blog (before Mark spent his days trying to get tea kettles to work with the internet, but I digress).
But there’s a a curious lack of information on renegade members since then. There is, however, just enough information on the internet to piece this together. There’s a little documentation about renegade members over on the official documentation. Just as important (for my purposes), there are two methods relating to renegade members that are in the Essbase JAPI Javadoc.
Typically when something is in the JAPI, there is a fair chance that functionality is in EAS as well. And since the renegade member is related to the dimension object (
IEssDimension) I went hunting around in EAS for any sort of menu/right-click setting or anything that would let me select the renegade member. It may exist, but I couldn’t find it anywhere. So right now my assumption is that it doesn’t have a GUI to manage it (at least in EAS). Further, there doesn’t seem to be any MaxL syntax to update the renegade member. So that leaves us with literally these two JAPI methods to update things.
A Few Hours Later in Java Land
Not to be deterred by a lack of GUI or commonly accepted form of administering an application, I whipped up a quick and dirty Java app to try and update the renegade members for a given dimension. You won’t be able to compile it and run it out of the box (it relies on some private libraries I’ve developed that aren’t public), but you can check out the code such as it is over on a GitHub project (imaginatively titled Hyperion Renegade Setter) I created.
Basically, it takes a given Essbase connection and a dimension/member, then tries to update that dimension’s renegade member. It also allows for clearing the renegade member. These APIs are little bit touchy but I think I have the sequencing right. Of course, there is absolutely no warranty expressed or implied, so caveat emptor.
Here’s an example of setting the renegade member for the Products dimension:
And an example of clearing it:
Please note that the code here is simulating running on the command-line. I haven’t gone so far as to compile this for the command line and actually run it there, but if you’re dying to do so and don’t want to mess with adapting the source code online, send me an email and I can make available.
Also, sidenote: renegade members are only available on ASO databases, not BSO (nor hybrid, one assumes). So for these examples I’m working on a copy of ASOSamp/Sample instead of the classic Sample/Basic database.
Let’s assume the code works for now. I want to do some testing to make sure that the data loads are working as expected. So here’s an example of a “good” data file (that we expect to load with success):
And here’s some bad data:
I botched the screenshot a little bit rest assured that I tweaked one of the member names so as to cause a bad load. Lastly, let’s look at an example of good and bad data in one file:
Note that there is a bad product named “BAD PRODUCT”. With test files in hand, let’s load the “good” file with a simple load rule:
Another fun fact: renegade members don’t work when doing free form data loads (i.e., data loads without a load rule), so keep that in mind too. As expected, loading the good at a results in a status of Success. So far so good. How about some bad data:
We get a Warning. Also to be expected. Let’s run the renegade setter program and set the renegade member to a new member we create in the Products dimension, called “Stuff”:
You can see in the latter half of the console output that the member for Products is indeed set to Stuff. Now, before checking out this renegadey goodness, let’s take a look at the database statistics to ensure that the load of the good/bad file truly resulted in just one record (instead of two) loading:
Also, before trying the data load with a renegade member set, let’s turn on
RENEGADELOG, which is mentioned in the documentation that exists:
Turning this option on tells Essbase (or more specifically, the ASO database in question) to log the results of a renegade load. You don’t have to turn this on but it might be useful.
Alright, so we have the renegade member set, we’re doing a data load with a load rule, we’re using an ASO database, and renegade logging is on. Let’s load our data file with the one good and one “bad” record now:
Success! Also note the extra line in the results (“Renegade member’s [sic] were used in Data load, please see the renegade log”). Any, as any good Essbase developer should think: trust but verify. Let’s see how much data is in the cube now:
We now have two input cells. Nice. For completeness, let’s go hunt down that renegade data load file inside of the log folder for our cube:
Here’s the file only:
Renegade members are one of those nice incremental feature ideas that can go into a product. Not revolutionary, but evolutionary. At first blush, it’s a bit curious that this feature only exists in the ASO database type and not BSO (and by extension, hybrid). This makes sense, though. The technical implementation of this feature is highly related to each database technology (more specifically, each database technology’s loading mechanism, be it BSO or ASO) – and we clearly know that BSO and ASO data loads are somewhat different beasts from each other if for no other reason than the fact that ASO cubes have all of this extra functionality around load buffers and whatnot.
So one can imagine that if nothing else, Oracle needed a place to start with in terms of renegade members, and ASO probably makes the most sense. This is for a few reasons. Firstly, renegade members make the most sense in a world where you want to just shovel a bunch of data into a cube and have it add up. ASO is as good of technology as any for this since it doesn’t have dense/sparse considerations, loads fast, and can handle huge gobs of data.
We live in a world where now where there are numerous instances where we are going to be using cubes that are themselves ad hoc, rather than bespoke and incredibly curated (as many/most cubes currently are). So renegade members fits right into this paradigm.
I imagine that there are many dimensions that you wouldn’t want to have renegade members turned on though. They seem like they’d be of curious or even negative value for dimensions like Scenario, Version, Years, and Time, since it’s rare that these dimensions aggregate up. This is going to be more useful for a dimension that aggregates up and you can live with a little fuzziness in the particulars, so long as the top of the house total is correct.
I’ll be curious to see if more enhancements come to the renegade member feature (such as MaxL/GUI support) or if it just remains in the JAPI only (where it is ostensibly leveraged by OBIEE and perhaps the forthcoming EssbaseCS GUI). One imagines that perhaps in the tectonic shift from all things Exalytics to all things Cloud in the last couple of years that renegade members got put on that back burner, as it were.
Even in it’s current, perhaps somewhat less than polished form, I think it has some relevant use cases that would fit nicely for various organizations. A common automation paradigm is to load data to a cube, check for a reject record file, then email it to the admin team. Sometimes the automation is considered to have failed if there are rejected records. So this technique can help reduce the number of cases where automation might fail.
As an interesting aside, several years ago I developed a program (and I know others have as well) that basically takes a rejected records file and remaps the rejects to some known member. This is actually really simple to develop – at least, it’s really simple most of the time. Sometimes there are multiple incorrect members for a single piece of data, and things get a little trickier from there. One of the solutions I developed even checked the account type from the GL and mapped it to a different member (think debit/credit) depending on what type of account it was. Of course, despite my seeming penchant for overengineering automation and one-off Essbase utilities, I actually like things to be as stock as possible. So even in cases where I had developed some specialized automation to help with mapping bad members, I think you could still make a good case for leveraging the built-in renegade member functionality rather than a separate utility.
So, hopefully you found this useful in case like me, you found yourself wondering one day, “Whatever happened to renegade members?”