Log Level in Automation Script

What logging level do you use to log messages from automation scripts? Well, your first answer would be the highest level of logging – debug. I used to do the same but in the past couple of months, I have moved from writing logs at debug level to writing them at info level.

If you have not already noticed, in the last year or so, automation script logging has changed in Maximo. Earlier, you could just specify a logger in the code, set that logger to debug in the logging application, refresh the cache and that would start logging your messages in the SystemOut.log. But that doesn’t work anymore. Now you need to set the logging level at the automation script record level for it to log messages from the automation script in the SystemOut.log. And if you set the log level on the automation script record header to DEBUG (because that is what your log statements in the code are using), Maximo starts printing a whole lot of OOB debug information out in the logs. This just makes debugging an issue much more difficult as you need to search for your debug statements in a big pile of debug logs. If it’s a big script or a script that runs on a schedule you are trying to debug, it’s just a nightmare to read the logs.

So, to be able to debug issues without having to unnecessarily scroll through a large pile of logs, I moved to using the info logger level in my automation script code. That way if I set the log level on the automation script record header to INFO and it only prints my log statements and not the OOB debug statement.

Happy days!!

What do you think about this approach? Let me know in the comments.

When using MXServer for fetching MboSet

There are two ways of fetching a MboSet in java code, either using a relationship or through MXserver. There are different benefits for using either of these and different scenarios may need one of these ways to be used. For now, we are going to talk about MboSet fetched from MXServer.

When fetching a MboSet from MXServer, there are a few things that one needs to be careful about. Poor knowledge of these may result in performance issues, poor memory management and undesirable outcomes.

There are six simple rules to keep in mind when fetching MboSet from MXserver. These rules are as follows –

  1. Always use setWhere() and reset() on the set fetched from MXServer. The where clause that you give in the setWhere will reduce the no. of MBOs fetched in the set. The reset will get the data from the database using the where clause. If the setWhere is not used, the entire set is fetched from the database which means the entire table is fetched into the memory.
MboSetRemote assetSet = MXServer.getMXServer().getMboSet("ASSET", getUserInfo());
assetSet.setWhere("LOCATION = 'BEDFORD'");
assetSet.reset();
  1. If the set is being fetched just to add new MBOs and not for traversing then use 1=0 as where clause in the setWhere. This will fetch an empty set.
assetSet.setWhere("1=0");
assetSet.reset();
  1. If the set is being fetched just for traversing and not for any addition or updates set DISCARDABLE flag as true on the MboSet. Discardable MboSets are not cached in memory, they can only be traversed in forward direction and cannot be saved.
assetSet.setFlag(DISCARDABLE, true);
  1. If MboSet is fetched for readonly purpose, set NOSAVE flag as true. This way the MboSet won’t be added to the MXTransaction which would shortens the looping time of the transaction.
assetSet.setFlag(NOSAVE, true);
  1. If an add or update transaction is being performed on an MboSet, do not forget to call save(). Contrary to popular belief that save shouldn’t be called explicitly in java code, MboSet fetched from MXServer must be saved before the set is closed otherwise the changes would be lost. MboSets fetched from relationship do not require a save to be called explicitly because their save is called when their parent is saved. Hence the belief.
  1. Always call clear() and close() on the MboSet fetched from MXServer once it is certain that it is not required anymore. This releases the memory and the database resources. If the set is not closed, it will remain in memory till it is collected by the garbage collector which could be a long time.
assetSet.clear();
assetSet.close(); 

clear and close shouldn’t be called on an MBOSet fetched from a relationship. This will give undesirable results.

So keep in mind these simple rules next time when you are fetching a set from MXServer.

In my next post I will try to explain you the difference between clear(), cleanup() & close(). Stay tuned.. 🙂

isNew() vs toBeAdded() Methods in MBO

Often this question is asked that what is the difference between isNew() and toBeAdded() methods of the Mbo. Before I explain the difference let me tell you what these methods are –

  • isNew() – Returns whether the mbo is new or not. true, if the mbo is new (i.e. created by calling add() or insert() methods), otherwise false.
  • toBeAdded() – Returns whether the Mbo is to be added to storage
  • toBeDeleted() – Returns whether the Mbo is to be deleted from storage
  • toBeSaved() – Returns whether the object need to be saved to persistent storage. This will also check child objects.

All these method are in the psdi.mbo.Mbo class and have a return type as Boolean.

The difference is explained using the scenarios in the below table

Scenario isNew()  toBeAdded() toBeDeleted() toBeSaved()
New Mbo Added True True False True
New Mbo Added, deleted before saving the Mbo True False True False
Existing Mbo updated False False False True
Existing Mbo deleted False False True False

All about Count Method

Although it is discouraged to use the count method of mboSet as it hits the database to get the count but at times it can be very useful. There is an overloaded method count(int countConstant) that can be used to get the count of mbos that are in different state in the mboset.

Here is the explanation of the parameter –

countConstant – one of the constants from psdi.mbo.MboConstants. The list below shows each constant and describes the count returned for each.

  • COUNT_DATABASE — The count from the database.
  • COUNT_ADDITIONS — The count of newly added Mbos that have not yet been saved.
  • COUNT_DELETED — The count of Mbos marked for deletion that have not yet been saved.
  • COUNT_EXISTING — The sum of the count from the database (COUNT_DATABASE) plus newly added Mbos that have not yet been saved (COUNT_ADDITIONS).
  • COUNT_AFTERSAVE — The number of Mbos that is anticipated to be in this MboSet after saving. Equals the sum of the count from the database (COUNT_DATABASE) plus newly added Mbos that have not yet been saved (COUNT_ADDITIONS) minus Mbos marked for deletion that have not yet been saved (COUNT_DELETED).

The count() method without the parameter is Same as count(COUNT_EXISTING).