Expand all | Collapse all

Launch point variables

  • 1.  Launch point variables

    Posted Thu July 29, 2021 06:23 AM
    Edited by User1971 Fri July 30, 2021 09:08 AM

    My organization has adapted the automation script from this tech note: Prevent Work Order With Open PO From Closing With Automation Script

    The script makes use of launch point variables:


    if openpo is not None and len(openpo) > 0: errorgroup = 'cgworkorder' errorkey = 'cgopenpoexists' if openpr is not None and len(openpr) > 0: errorgroup = 'cgworkorder' errorkey = 'cgopenpoexists'


    That script seems quite simple, which is great. If I had to guess, the script would be more complicated if launch point variables weren't used.
    With that said, I've noticed that people don't usually use launch point variables when writing autoscripts from scratch.

    Is there a reason why people don't normally use launch point variables, even though they might simplify things? (To my mind, simplicity and readability should be top priorities when configuring Maximo.)

  • 2.  RE: Launch point variables

    Posted Thu July 29, 2021 11:04 AM
    Why not just remove everyone's security rights so they can't close work orders, and then run an escalation to do it?

    Much simpler.  The users would be responsible for getting the work order to COMP or equivalent.  The escalation would take it from there.

  • 3.  RE: Launch point variables

    Posted Thu July 29, 2021 11:40 AM
    Personally I'm not a fan of Launch Point variables since you have to go back and forth between two different tabs to get the full picture of what the script is doing. It may simplify the script, but that's just because it's obfuscating some of the logic into the variable.

    Tim Ferrill
    Solutions Consultant
    Intelligent Technology Solutions

  • 4.  RE: Launch point variables

    Posted Fri July 30, 2021 08:36 AM
    Most importantly, this is a matter of preference. I think it's apparent that's the case, but wanted to be clear that there is no right/wrong answer here.

    Variables can simplify things and are appropriate in some scenarios but often I've found it makes scripts more difficult to follow and troubleshoot. One of the main purposes of variables when it was introduced (in 7.5 when the framework itself was introduced) was to support utilizing a single script with multiple launch points. For example, let's say you needed to multiply linecost*quantity*markup percent for 10 different objects. Utilizing variables, you could refer to these attributes in an abstract way and utilize one script, even if it's sometimes called quantity, sometimes called orderqty, etc. But with the ability to invoke other automation scripts (even specific functions in another script in 7.6.1.X), that need goes away entirely IMO because you can abstract that logic into its own script and call it from the other scripts.

    Variables have to return an attribute (or property/literal value). There are scenarios where you only care "do I have a record/value" and it might save some time. But let's say this logic you needed the PONUM & SITEID from the PO record. You currently only have the PONUM, so you would need to create another variable with the same relationships and filters for SITEID and then match them up. But if you just had the PO object, you could get any attributes you needed. 

    From a performance perspective, this is also a really bad implementation. It has to get all PRLINEs and for each PRLINE, attempt to get a PR (with an additional filter applied to the relationship). That means if you had 100 PRLINEs it would try to get 100 PRs, meaning a minimum of 200 queries that has to execute (plus all the initializing logic of those objects). It would then build all the PRs into a list to return to you. What I would do instead is write a where clause that gets me PRs that are open that reference my WORKORDER. This would avoid initializing 100 PRLINEs and I could avoid initializing the PR too if I didn't need anything from it. For example, I'd write this like below. NOTE: I did this from hand in this editor and didn't test it, so if I have the wrong attribute referenced or wrong case on something I apologize if someone tries to utilize this script verbatim. 

    openPRSet=mbo.getMboSet("$EMXOPENPR","PR","historyflag=0 and exists(SELECT 1 FROM prline WHERE prline.prnum=pr.prnum and prline.siteid=pr.siteid and prline.refwo=:wonum and prline.siteid=:siteid)")
    if not openPRSet.notExist():

    The notExist is preferred over isEmpty() as isEmpty() has been known to cause database connection leaks. This will simply execute a query and say yes records would be returned or not based on this criteria. I went from potentially 200+ queries to 1. This requires knowledge of Maximo to write, but this type of optimization just isn't possible with variables. 

    That also ignores the annoyance of maintaining variables. If you have 4 attribute launch points on the same script for example, you need to manage the variables on all four launch points. That can lead to potential issues where one of the launch points might be misconfigured with the wrong attribute/property/maxvar/value and it's unlikely it gets caught for a while until you're trying to troubleshoot why it doesn't quite work in some cases. 

    You also can't delete variables (at least you couldn't before, haven't tested recently) while you have launch points. That means if you no longer need variable X, it's still in the variable list and must be set unless you remove all launch points to delete that one variable. That makes it difficult to know if the variable is intentionally missing from a script or not. On something that doesn't change often, that might not be a significant issue, but having to recreate launch points just to remove unnecessary variables is a non-starter for me.

    Steven Shull

  • 5.  RE: Launch point variables

    Posted Wed August 04, 2021 01:56 PM
    I recommend against using ATTRIBUTE bound variables for two primary reasons.

    One reason is that Maximo generates and sets a bunch of other variables, based on the original name and suffixed with _readonly and _required and etc, during setup and then read them and leaves them for garbage collection on teardown. To cover the different attribute names scenario that @Steven Shull refers to, I would rather pass the attribute name as a LITERAL bound variable that I can reference in mbo.get*() or mbo.setValue() calls and skip the performance hit of setting up and tearing down all those extra variables that I won't reference.

    The other reason is that I've seen bindings like the one shown, where you have a relationship chain doing the setting, give ugly errors (e.g. "script foo failed to execute launch point bar due to a NullPointerException") to users if a relationship in the chain doesn't find data. And because the error happens before any of my script executes, I can't catch it and throw something nicer for the user to see.

    As far as closing WOs goes, I agree with @Shannon Rotz. It's pretty normal, as far as I've seen, to not let anyone Close WOs but instead to have an Escalation that Closes WOs ​with no open transactions (POs, etc) 90 days after they Complete.

    Jason Uppenborn
    Sr. Technical Maximo Consultant
    Ontracks Consulting