Maximo

Maximo

Come for answers, stay for best practices. All we're missing is you.

 View Only
  • 1.  The rules about when to close an MboSet are a bit confusing.

    Posted Tue January 06, 2026 07:43 AM

    The rules about when to close an MboSet are a bit confusing.
    sources I've read agrees that you should definitely close the MboSet obtained from:

    • MXServer.getMXServer().getMboSet(...)

    • service.getMboSet("MBOSET", MXServer.getMXServer().getSystemUserInfo())

    However, you should not close your current MboSet obtained from mbo.getThisMboSet().

    Where it gets confusing is when using mbo.getMboSet("Relationship"). Some blogs suggest closing the MboSet retrieved this way, while I was under the impression that it should not be closed, because Maximo closes it automatically along with the main Mbo.

    Additionally, what about mbo.getMboSet("$tempRelation", "MboSet", "Query")?

    I've also read that you should not use moveNext() with mbo.getMboSet("Relationship"). Is that true?


    #Maximo #Maximo #MaximoEAM #IBMMaximo #IBMMaximoAssetManagement



    ------------------------------
    osama attia
    ------------------------------


  • 2.  RE: The rules about when to close an MboSet are a bit confusing.

    Posted Wed January 07, 2026 04:17 AM
    Edited by Andrzej Więcław Wed January 07, 2026 04:27 AM

    Hi Osama,

    in most of the cases the rule is actually simple and can be phrased this way:
    You should always close and cleanup MboSet (ref. e.g. Closing MboSets) which hasn't been opened via any of the psd.mbo.Mbo#getMboSet(...) calls, otherwise you need to close the set.

    Why did I say in most of the cases? Because it's all about sharing an instance of MXTransaction which is happening automatically whenever you call any of the overridden psd.mbo.Mbo#getMboSet(...)methods.
    Technically you can still open new MboSet using psdi.server.MXServer#getMboSet(...) or psdi.server.AppService#getMboSet(...) and do the following: 

    newMboSet.setMXTransaction(otherMboSet.getMXTransaction());

    In such case, if otherMboSet is managed by Maximo (UI, escalation, etc.) then you should skip closing the MboSet explicitly and  in general - calling MboSet lifecycle methods (e.g. MboSet#save()).

    Regarding psdi.mbo.Mbo#getThisMboSet() usage. The key here is to realize that you are NOT opening new MboSet but only acquiring a reference to already existing one, hence all the rules described above apply.

    Regarding usage of psdi.mbo.Mbo#moveNext()(and others psdi.mbo.Mbo#moveNext(), psdi.mbo.Mbo#movePrev(), psdi.mbo.Mbo#moveLast(), psdi.mbo.Mbo#moveTo()) in combination with any of psd.mbo.Mbo#getMboSet(...) - in general there is no such rule but I would say it's a good "just in case" practice, just to avoid glitches e.g. with the UI. Namely all these methods are changing current MBO index reference. Depending on your customization logic injection point it may interfere/affect other logic which may depend on the MBO index (like UI). 

    ------------------------------
    If this post helps, please consider accepting it as a solution to help other members find it more quickly.

    Andrzej Więcław
    Maximo Technical SME
    ZNAPZ B.V. (part of Naviam)
    Wrocław, Poland
    ------------------------------



  • 3.  RE: The rules about when to close an MboSet are a bit confusing.

    Posted 14 days ago

    @Andrzej Więcław Thanks and sorry for the late replay this was helpfull



    ------------------------------
    osama attia
    ------------------------------



  • 4.  RE: The rules about when to close an MboSet are a bit confusing.
    Best Answer

    Posted Wed January 07, 2026 09:04 AM

    Andrzej provided an awesome answer as always, but I wanted to expand a bit further.

    Your question around using an existing relationship (IE getMboSet("RELATIONSHIP")) or you build it dynamically (IE getMboSet("$tempRelation", "MboSet", "Query")) is there is no difference between the two other than the obvious (one exists in database configuration, and the other is built dynamically in code). These should be treated as equivalent. If you need the same data set in multiple places (automation scripts, UI dialogs, object structure relationships, etc.) you should create it as a relationship in Database Configuration. If you have a completely unique relationship that is only used to fulfill the one automation script, you can avoid creating it in database configuration. Just ensure that your $tempRelation name is extremely unique because if something else uses that name you'll get unexpected behaviors. There was a bug in core Maximo recently where two different things (even across different child objects) used the same $tempRelation name which led to undesirable results. 

    Whenever possible, you should get sets as child objects. You want the transaction management (save and or rollback if an error occurs) to be automatic with the main object. You also want it to get cleaned up when the originating MBO is cleaned up by the framework. There are ways as Andrezej called out to set the transaction to be consistent but it's adding a lot of extra code to set the transaction, save the set, cleanup, etc. that isn't necessary. And if you fail to do it, the risk of data being in a corrupt state is highly possible.

    I see customers/consultants mess this up all the time. This is one of the reasons I loathe after save automation scripts because I see customers try to modify the record that has already been saved (and written to the database, though not yet committed), which requires opening a separate set and going through the save process again. It's horribly inefficient and can lead to data in a corrupt state. 

    Regarding close on the sets that are opened using MXServer (service.getMboSet is calling the same thing, just simplifies the logic), you want to cleanup() the set. Most people don't know this but calling close on the set is for the database connection. When people complain about database connection leaks, close() is one of the solutions that can help avoid it. It should only be called after you've fetched everything you've needed from the database. There are other practices such as not using isEmpty(), which fetches the first MBO without traversing the entire set, can help avoid the connection leaks as well.

    But what's even better is cleanup(). When you are truly done processing a set, cleanup() is preferred. This is what the automation script warning framework will try to confirm exists in your code for a reason. Cleanup helps the framework release the data from memory and also closes the set. While you can call close() and cleanup(), it's not necessary to do both. Calling cleanup() will call reset() which calls resetThis() which calls the close() on the set. 

    And again, you should neither call close nor cleanup if you are not opening these sets using MXServer.  

    Regarding the moveNext and such, the concerns there are really around the UI as he mentions. It changes the current index of the set. You'll see a lot of examples I have personally posted where I've done this because it's easier for people to understand. But you can traverse in other ways like MboSetEnumeration. Or if you're in an operation where users select the values they want to process (IE a multiselect dialog) you can call set.getSelection().iterator() to iterate only the records that have been selected.



    ------------------------------
    Steven Shull
    Principal Maximo Solutions Engineer
    Naviam
    Cincinnati OH
    ------------------------------



  • 5.  RE: The rules about when to close an MboSet are a bit confusing.

    Posted 14 days ago

    @Steven Shull Thanks and sorry for the late replay this was helpfull



    ------------------------------
    osama attia
    ------------------------------