Not speaking to CUE specifically, the most critical objective I try to emphasize to everyone developing automation scripts is you want Maximo to manage the transaction. You mention that you have an automation script, but it is not clear what your launch point is. So, I'll talk through a few different common scenarios.
1) Something that runs in context of an attribute/object event, such as WORKORDER before save. In this scenario, you will have an implicit variable (mbo) that will correspond to your work order. All sets should be opened using this MBO (or children of this MBO) and should NOT be explicitly saved. Maximo will save these child sets automatically for you.
These sets can be opened using relationship names, such as mySet=mbo.getMboSet("RELATIONSHIPNAME"). Or they can be opened dynamically, such as mySet=mbo.getMboSet("UNIQUEDYNAMICNAME","OBJECTNAME","WHERECLAUSE"). Where the UNIQUEDYNAMICNAME is anything you want it to be but should be a unique reference like $EMXNEWDESTCONTROL. The object name would correspond to the Maximo object like PLUSDESTCONTROL. And WHERECLAUSE is the sql that links your record to that table, including something like 1=2 if you intend to add a new record.
In this scenario, these will automatically be part of one transaction so they will all be committed or rolled back together. This is the best-case scenario to ensure you do not get partial commits.
2) A cron task automation script. In this scenario, you will need to open a set using either service.getMboSet() or MXServer's getMboSet() method. For example:
woSet=service.getMboSet("WORKORDER",runAsUserInfo)
woSet.setWhere("wonum='ABC123' and siteid='BEDFORD')
woMbo=woSet.getMbo(0)
if woMbo:
But similar to before, you still want to open all the other sets as children of the WO. IE woMbo.getMboSet()... rather than opening new sets using service.getMboSet() because these would each establish their own transaction.
Unlike before, you will need to explicitly save yourself in a cron task automation script. But it is critical that you only save once at the very end. IE you should have:
woSet.save()
And no other saves in this script. By opening the other sets as children of this set, this save of the WO set will automatically save all children sets.
Something I have been seeing a lot of lately that I struggle to understand is AFTER SAVE & AFTER COMMIT launch point scripts. These have some very narrow legitimate use cases which is why these events exist. But if you are manipulating records at this stage (IE modifying the work order, modifying the asset, etc.), I almost guarantee you have the wrong launch point. I have seen examples where customers commit a WO & then modify the WO after it has been committed. In addition to the partial commit issue, this is extremely poor from a performance perspective and can lead to infinite loops.
To sort of highlight why this is bad, let's use WO again as an example. In the before save scenario, we have a WO MBO fully in memory and can change any values we need to. Maximo has not tried to write anything to the database at this point so anything we change when Maximo executes the save will result in a single:
update workorder set field1='ABC', field2='ZXY' where workorderid=1001 and rowstamp=ROWSTAMP;
In the after save or after commit, we need to establish a new set and transaction. For example, we would need to do:
woSet=service.getMboSet("WORKORDER",mbo.getUserInfo())
woSet.setWhere("wonum='ABC123' and siteid='BEDFORD')
woMbo=woSet.getMbo(0)
A couple of things are going to happen here. We need to execute a new query to get our record and go through the MBO initialization logic again (firing any java classes, automation scripts, SQL queries, any java classes/automation scripts on related child MBOs, etc.). This is extremely poor from a performance perspective because we went from using a record already in memory to needing to establish a new record in memory. Then we need to modify the record and save it.
This causes all the before save, after save, and after commit logic to run again. If your before save automation script takes 5 seconds for example, you have 5 seconds the first time, however long the after save/after commit script takes, 5 seconds for the before save the second time, however long the after save/after commit script takes, etc. And if you're not careful, this will cause an infinite loop.
And because this will be part of its own transaction by default, you can get some of the data committed the first time while having the second transaction fail and get rolled back. This is why it's critical that we're not modifying the records at the after save/after commit events.
------------------------------
Steven Shull
Naviam
------------------------------
Original Message:
Sent: 06-11-2025 13:36
From: Theo Pozzy
Subject: Automation script best practices for dealing with failures creating child objects in a hierarchy
I am working on a Maximo automation script that creates multiple related objects, including: PLUSDESTCONTROL, PLUSDESTVERSION, PLUSDSTATION, PLUSDSTNPARAM, PLUSDSTNDETAIL and WORKORDER. There are situations where there might be errors creating the child records in the hierarchy. What are the best practices for dealing with errors and not leaving partial record structures? Is there any kind of transaction boundary that can automatically back out records that are created in the case of an error? Or do I need to add logic to the script to track all the records that are created and deleting them in the script?
#Customizations
#MaximoApplicationSuite
------------------------------
Theo Pozzy
OneGas
------------------------------