Friday, 3 April 2020

Exploring MBR Language scripting and REST APIs using JSON Format with examples


Maximo as a product is always emerging and evolving in the space of enterprise asset management and the recent versions of Maximo, like 7.6.1, is by far the most impressive version available in the market. It delivers and caters to client and industry driven needs. Availability of Maximo SaaS versions on cloud has exposed the developer community to a more demanding and fastest growing segment where in he/she is expected to explore out of his/her comfort zone of relying into Java Customization or Automation Scripting for that purpose.  Because Maximo SaaS public/standard version is all changing the game plan for a developer. In this changing paradigm, a developer is supposed to understand that MBR is the only scripting language supported available in IBM Maximo EAM SaaS. Also, integration is supported mostly through REST APIs in the Maximo Public SaaS variant. Through this blog I want to throw some light on the same subjects with a few practical examples.

Maximo Business Rules Scripting Language

The latest versions of Maximo on cloud necessitate a Maximo developer to be familiar with MBR. This scripting language provides cloud-safe way to extend application business logic and is evolving gradually. The Maximo Business Rules scripts are text files that are made up of expressions. These expressions contain operators, functions and variables. Supported launch points that can be associated with MBR scripts are for Maximo business objects, attributes, conditions and actions. These MBR scripts cannot access Maximo framework’s Java classes directly. MBR scripts allow you to create functions pre-fixing the function name with a “:”. You can write library scripts for reusable code and these library scripts can be invoked by any other script. You can add comments by pre-fixing with a “#”. But there are certain rules around these. You cannot call a function or a library script recursively from your script. You cannot define more than one expression in the same line. No expression can span multiple lines. You cannot add inline comments. MBR Scripts restrict looping capability to delimited strings known as tokens and to MBOs that are related to the MBO that owns the current artifact. Keeping all these in mind you have to write a script using MBR language. And, you should also be aware that MBR scripting cannot be used to support Integration in Maximo SaaS variants, at least not yet.

There is a list of mathematical and Boolean operators, and the common mathematical, String manipulation, Aggregation, Date Manipulation functions are available in MBR language. Control flow functions like if(), break, continue, foreachmbo() are available for use. Date manipulation functions like now(), date(), duration(), datetime() are for your use. There are two very important functions to manipulate the variables in the scripts, as getVar(var_name) to retrieve the value of a variable, and setvar(var_name, expr) to set the value of a variable. There are a number of Maximo business specific functions as invokescript(), newmbo(), setValue(), error(), tobeadded(), tobeupdated(), scriptvar(), invokeworkflow(), setvarresult(), setrequired(), etc. are also available. There are dollar notations to access the MBO attributes in the MBR script. You can use a notation like Relation1$Relation2$Relation3$...$RelationN$attr to traverse several relationships to reach the MBO that contains the desired attribute value. A complete list for all of these can be referred to in the pdf file available from the below URL.

Let us jump into a few examples to understand how easily you can adapt to this new language. For the very first example, let us throw an error to the user when user selects the required date less than the current system date in Create Requisition application. We will create the error message in the Database Configurations application with message group as “ErrMsgGrp”, key as “ErrMsgKey”, display method as MSGBOX and the value of the error message as say, “Please select a date greater than the current date.” So far so good. Next, we proceed to create an automation script with Attribute launch point on object MR and attribute REQUIREDDATE with event as Validate. We are still in our familiar conform zone. We select the script language as MBR and the desired log level. Then we write the source code, and you will be very happy to write a single line that will suffice our requirement. Refer the image below for the source code.




You can see for yourself, it is such a simple If statement; i.e., If(<condition expression>, <expression if true>, <expression if false>). Now() is a date function that returns the current system date and time.

For our next example, let us explore how to make use of use variables and how to access a MBO attribute value from a related object from the current MBO record. In Purchase Orders application, on adding a line record, if the user selects an item number and the selected item is of type KIT, a field, say ‘X’, need to become read only else, another field, ‘Y’, needs to become required. For this requirement, we will create an automation script with attribute launch point on object POLINE and attribute ITEMNUM. Please refer the image below for its source code. 






You can see the dollar notation used here to fetch the value of ISKIT attribute from ITEM object using the relationship name “ITEM” which exists between parent object POLINE to child object ITEM. We are setting this value to a new variable “var_kititem” created for this script. You can see the If statement. If this variable “var_kititem” is true, attribute X is set as read only else attribute Y is made required. You can add the comment line starting with hash.

Let us also explore how to loop through a MBO set in MBR scripts. Let’s assume we have to update the actual cost of all issue transactions of active inventory records of all capitalized items that have happened between last Monday and Friday. Any issue of an inventory record in Maximo is written into MATUSETRANS object. Let us consider that we create a relationship from MATUSETRANS object to INVENTORY object with the name as “CAPITEMISSUES” and where clause as “siteid=:siteid and location=:storeloc and itemnum=:itemnum and itemsetid=:itemsetid and issuetype='ISSUE' and exists(select 1 from ITEM where itemnum=:itemnum and itemsetid=:itemsetid and CAPITALIZED) and (transdate betweek trunc(sysdate)-5and trunc(sysdate)-1)”. Then we proceed to create an automation script “CALCULATECOST” with Action launch point in Object MATUSETRANS. We will then create an escalation on MATUSETRANS object to call this action “CALCULATECOST” every Saturday. The source code that is written using MBR language is as shown in the image below.

We have used foreachmbo() control function here and we are calling a function “capitemcost” for each record fetched from the relationship name “CAPITEMISSUES”. The function starts with its definition with the “:” and it finds the LASTCOST attribute value from the related INVCOST MBO record. This is fetched using the dollar notation for related MBO sets, CAPITEMISSUES being the relationship from MATUSETRANS to INVENTORY object and INVCOST being the relationship from INVENTORY to INVCOST. The LASTCOST attribute’s value we are setting in a variable “v_costvalue”. You can see that with the setvar function we have used a Boolean value TRUE. This is to make this variable global so that this can be used by outside the function “capitemcost”. ACTUALCOST attribute of the MATUSETRANS record by multiplying Quantity value to the value of the variable “v_costvalue”.

Maximo REST APIs using JSON format 

The multi-tenant or public variant of Maximo SaaS, IBM Maximo EAM SaaS, provides integration support mostly through REST APIs. It allows inbound integrations, outbound events and data export by enabling a secure sharing of data between Maximo and external applications. In this variant of Maximo SaaS, you are not allowed to create or modify any Object Structure. You do not have support for integration scripting. There is no support for XML messages and web services. Only JSON and CSV formats are supported.

All these necessitate a developer to understand how to use REST APIs with JSON formats. The REST (Representational State Transfer) application programming interface (API) provides a way of querying and updating the Maximo application data by external applications. The REST API is part of the Maximo Integration Framework and can be used for CRUD (Create, Read, Update, Delete) functions on the data using either XML or JSON (JavaScript Object Notation) representation formats. In Maximo SaaS Public, however, JSON is only supported with REST API. REST is based on the concept of resources and hence, Maximo REST API exposes two types of resources, Maximo Business Objects (mbo) and Integration Object Structures (os). You can see two system properties for JSON format in Maximo which shows that Maximo REST API uses serializer classes, “mxe.rest.serializer.mbo.json” and “mxe.rest.serializer.os.json”.

Using REST API is actually very simple. First of all, you should know what is the URL of Maximo REST services. It is usually http://[HOSTNAME:PORT]/maxrest/rest. Say, we want to retrieve the list of all person records whose last name starts with “LAN”, using the integration object structure MXPERSON. We will simply use the URL as below. 
And, Maximo will perform a wildcard search so all person records that starts with the string LAN in the last name field will be returned. When you are using a REST API call with HTTP GET request like above, you may get an authentication error as “User name and password combination are not valid.” In such a case, the REST API call is expecting userid and password arguments with the HTTP GET request. So, we may use the below URL if we are using native authentication.
http://[HOSTNAME:PORT]/maxrest/rest/os/mxperson/?_lid=wilson&_lpwd=wilson&LASTNAME=LAN%.


Let us take another example to retrieve all the PO records sorted in descending order of total cost value. You will use the below URL to do so.

Moving on from READ to CREATE or UPDATE functionality of CRUD, let us make some REST API calls with the HTTP POST request. Say, I want to change the description of an asset 1001 of BEDFORD site to New asset description.  Here we are using an argument _action to specify a Change and ‘%20’ is used to encode spaces.

Next I want to change the status of all internal PO records of BEDFORD. Here the parameters with tilde prefix, status and memo, specify that these parameters belong to a web method.
http://[HOSTNAME:PORT]/maxrest/rest/mbo/po/?_lid=wilson&_lpwd=wilson&siteid=BEDFORD&internal=1&~status=APPR&~memo=Status%20change%20from%20REST%API

Let us create a new location ‘XYZ’ in BEDFORD site of storeroom type in OPERATING status. Note the use of argument _action with AddChange.
http://[HOSTNAME:PORT]/maxrest/rest/mbo/location/?_lid=wilson&_lpwd=wilson&_action=AddChange& location=XYZ&siteid=BEDFORD&type=STOREROOM&status=OPERATING&description=My%20location%20description


References