MBOs in Automation Scripts: Working with MboSet Collections
Let’s start with defining some terms. The three biggest terms to define are MboSet, Mbo, and MboValueData. First, the acronym MBO stands for Maximo Business Object. This represents a generic record of data within Maximo. An MBO could be a Work Order, an Asset, an Item, or any of the other hundreds of record types in Maximo. If we think of a spreadsheet of data, an MboSet would be a tab with columns and many rows of data. The data can be sorted or filtered in many ways. Again, this data could represent any record type in Maximo. An Mbo would be a single row of data represented within an MboSet. Finally, an MboValueData record would be a single cell in the spreadsheet that represents a column of data for a single row. These terms are used in generic fashion because they have behaviors that can apply to any set of records in Maximo. For example, a set of Work Orders, Assets, Items, etc. can all be filtered, sorted, saved, and looped over in the same fashion. In fact, all record types follow a wide set of general behavior patterns. If you understand these patterns, you’re going to write much better automation scripts in Maximo. This article will focus on the MboSet collection. There are three ways to get a handle on an MboSet:
- Use the getThisMboSet() method on an Mbo. Most automation scripts will create an implicit variable at runtime of the script called
mbo. This represents the record on which the script is operating. To get a handle back to the list that the current record is part of you can use some code that looks like this:
This is analogous to going back to the List tab in Maximo. mbo
mboSet = mbo.getThisMboSet()
- Use the getMboSet() method on an Mbo. You can either get an MboSet of data related to the current record, as in a one-to-many relationship, or you can get an MboSet of unrelated data to the current record.
mboSet = mbo.getMboSet("ASSET")
mboSet = mbo.getMboSet("$WOAPPR", "WORKORDER", "status = 'APPR' and siteid = 'BEDFORD'")
- Use the MXServer.getMXServer.getMboSet() method. If you have an existing Mbo in your code, it’s recommended that you use one of the first two options above. However, there are some automation script launch points that won’t contain the implicit
mbovariable (such as Cron Task scripts, some of the Integration scripts, etc.). If that’s the case, then this is your option. You’ll need a
userInfovariable defined to make this connection as a given user.
mboSet = MXServer.getMXServer().getMboSet("WORKORDER", userInfo)
returns a collection of WO objects (which represent approved work orders for the BEDFORD site). So far, the set has zero members, but after the following code executes:
woSet = mbo.getMboSet("$WOAPPR", "WORKORDER", "status = 'APPR' and siteid = 'BEDFORD'")
the set contains all approved work orders in the BEDFORD site (or, more precisely, WO objects representing all approved work orders in the BEDFORD site). The methods moveNext() and moveLast() produce similar results (see below). Note that the method also returns a remote reference to the object that has become the current member of the collection, in this case the first one. This holds true for the other methods that traverse collections as well (moveNext(), movePrev(), and moveLast()). A set has a current member pointer that is maintained on the server. The current index of that pointer may be retrieved with the following:
wo = woSet.moveFirst()
The method returns -1 if there is no current member. Note that the first object in the collection is stored in the zeroth position. The action of
woPos = woSet.getCurrentPosition()
moveFirst()sets the current member pointer to the first position. The
moveNext()method produces the identical result: the pointer is advanced one position. In the case of
moveLast(), the pointer is set to the last position and all records in the collection are retrieved. This can be very expensive in performance terms and is generally not recommended. If the current object itself is required, call the following:
The method returns null if there is no current member. The
wo = woSet.getMbo()
getMbo()method can also return the object at an arbitrary position in the set; in this case the desired position is passed as an integer argument. The following code returns the first object in the collection.
The current member pointer is important, as there are many methods in the MboSet class which operate on the current object in the set. Examples of these are
wo = woSet.getMbo(0)
getString(). To change the current member pointer, use methods such as
add(). The contents of the collection can be restricted by using the
setWhere()method. For example:
This restricts the set to having only members whose work order numbers begin with the character “1”. This method must be called when the set is newly initialized, i.e. before any members have been placed in the set. If the set already has members, call the method:
woSet.setWhere("wonum like '1%'")
This clears the current contents of the collection and generates a query to the database. Any modifications or additions made to the set are lost if they are not saved before
reset()is called. The
reset()methods can be called in either order. When the
setWhere()method is used, it must be passed a valid SQL where clause for the database platform the server is connected to. Here’s an example of looping over an MboSet:
For a complete description of all methods available, refer to the MboSet JavaDocs on the IBM Asset Management Developer Center. Our next article will focus on reading single attributes from the current record in an MboSet.
woSet = mbo.getThisMboSet() wo = woSet.moveFirst() while wo: #Do some things with the work order wo = woSet.moveNext()
While automations themselves were developed to mitigate repetitive and time consuming tasks, ironically...
A3J Group is happy to announce the latest MxMobile releases below. The releases will be available on...
Maximo has a neat feature where you can set any value in the global property, and it will default to...
Walter I need your help. I cannot get my automation script to look at the current record. I have a custom object connected via relationship to the COMPANIES object, and want to fire the script on saving the Companies record. The script should insert a record into the new object. If you would like me to post the script please let me know. Thanks for any help.
We haven’t covered this yet in this series, but the basics are:
relatedSet = mbo.getMboSet("RELATEDCOMPANYSET")
newMbo = relatedSet.add()
newMbo.setValue("OTHERATTRIBUTE", "OTHER VALUE")
Hope this helps.
Alex, sorry I called you Walter earlier. In my haste I made a mistake. The record is created at the child level and has to look up to the COMPANIES record as the parent. The problem is that even after creating a relationship, the child doesn’t know the parent’s primary key. Thanks for your help.
No worries! I’ve been called worse… 🙂
Again, something that hasn’t been covered yet but would be useful in your case is the
getOwner()method on an Mbo. You can effectively traverse up the tree of related Mbo’s using that method. In your case, it might look like:
parentMbo = mbo.getOwner()
Thanks Alex, I’ll give it a go.
Alex, you are 100% correct. It worked first time. My problem is that I printed out the parentMbo (prior to fetching the COMPANY field) and it was some sort of index number, not the primary key, and it confused me. Thanks so much for your help. If you ever have a BIRT question, let me know. I’m better at BIRT than automation scripts.
It worked, Alex. Thanks so much!! If you ever have a question on BIRT, let me know. I can help you there…
I need a script that shows an error message if an asset number that already exists in the asset table is entered.
I don’t know how to make the comparison of the asset that is entered with the entire table of assets. can you support me
Typically Maximo will throw an error immediately when a user attempts to manually enter an asset number that already exists in the database. However, if you want to test this manually, something like this should work:
from psdi.mbo import SqlFormat
whereClause = SqlFormat(mbo, "assetnum = :1 and siteid = :2")
whereClause.setObject(1, "ASSET", "ASSETNUM", mbo.getString("ASSETNUM"))
whereClause.setObject(2, "ASSET", "SITEID", mbo.getString("SITEID"))
assetSet = mbo.getMboSet("$CHECKASSET", "ASSET", whereClause.format())
if not assetSet.isEmpty():
I need a script that check if current user is related with specific security group like MAXADMIN, system flag a checkbox on a field like isMaxadminGroup.
I don’t know how to make the script. can you support me.
thanks four your solution first. next i need your support that i want to know how to get the new record id generated after
newMbo = relatedSet.add() command run. i am new to maximo environment.
Thank you, Alex. I need your help.
I’m trying to get a list of the selected items in an autoscript on a button on the main tab.
I call mbo.getThisMboSet(), and it returns a set with only one item. First of the all selected items.
I check mboSet.getQbeWhere() and it returns itemid = ‘1092’
Why it returns the limited mboset and not the full from the List tab?
Can you guys help me with the automation script that validate the location before creating the asset in assettable. Right now we are manually providing the location in the jsonmapping. I am looking for an script when assetcron is running, while creating an asset it should validate if the location exists or not, if exists take that location as reference while creating the asset in asset table. Any help would be appreciated.
I need a “Attribute Launch Point” script to compare date value from Parent table with existing multiple records of date values in the child table.
Been trying the following script to do so, but it returns sql -104 error code,
from psdi.server import MXServer
from psdi.mbo import Mbo
from java.util import Calendar
from java.util import Date
from java.text import SimpleDateFormat
if(offstartdate <= datetime):
errorkey = ' Start Date is less than Current Date'
errorgroup = 'system'
offbooking.setWhere("STARTDATE is not None")
while(first is not None):
if(startdate <= offstartdate <= enddate):
errorkey = ' Start Date is between previously booked dates'
errorgroup = 'system'
there is a way to obtain the name of the jvm where the script is running?
The name of the JVM should be available in the mxe.name System Property. I believe this can be inspected via the
MXServer.getMXServer().getConfig("mxe.name")call. I haven’t tried this before, so the syntax may not be exactly that. Hope this helps.
Hello Alex, in the first paragraph you state the following:
An MBO could be a Work Order, an Asset, an Item, or any of the other hundreds of record types in Maximo.
Is there a list of record types available? I would like to see all the different record types (all the hundreds that you mention). Thanks in advance.
Bob – thanks for the reply. The full list of record types is available in the Database Configuration application in Maximo. Each object in that application is a Maximo Business Object (MBO).
I have the below code, however it breaks when setWhere() is closed obviously because no data exists in the DB for that query.
Is there a way by which I can avoid the code breaking here?
lSupSet = MXServer.getMXServer().getMboSet(“GSUPPORT”,MXServer.getMXServer().getSystemUserInfo())
lSupSet.setWhere(“PMI='” + str(pmi) + “‘ order by GSUPPORTID DESC”)
I am calling this from User exit after External Exit on an enterprise service response.
Thanks in advance.
For what it’s worth, there are similar functions for Formulas and MBR too:
SETQBE(): set qbe to a mboset variable (varname, attrname, qbeexp)
SETWHERE(): set where clause to a mboset using a condition (varname, condname)