Sunday, September 29, 2024

Maximo BIRT for Parent-Child Records with Costs

Maximo BIRT Sub report to View a Parent-Child Relationship and Costs

These type of reports are required to view parent - child records with their costs displaying individually for parent and child in separate sections. Users may need to know consolidated costs of the list of records for a period of time.

Let us create a sample report for Parent-child records - Work Order with its Actual Materials records

Create a new report of "Tivoli Maximo Subreport Template"


The parent and child data set are linked using a Data Set parameter. 
subDataSet defines a parameter "wonum" with Direction as Input.


 This parameter will take value from parent data set to subDataSet binding. row["wonum"] will get the value from parent layout in the design.



subDataSet query will get the value using the BIRT setQueryParameterValue method against ? place holders inside the sql query.


In report layout design we are displaying costs values of "WO Total Cost" and "Actual Material Line Cost".

WO total cost is displayed for each WOs and a consolidated WO total cost at footer section. 

Actual Material Line Cost is displayed for all WO Material lines below the sub section and a consolidated one for all WOs at footer. 

A couple of report global variables are created to calculate the consolidated sum for all WOs for the specific date range given in the report input parameter. 

Initialization of these report global variables are made in mainDataSet onCreate Script method. 



On data element of WO total cost & Material line cost fields, we add their values to global variable for displaying them at footer section using onCreate Script method. 



To display the consolidated value of all WOs, we using the onRender method of data element totwocost in footer section.



Report Output displays the WO Total Cost & Material Actual Cost at WO level and consolidated one at footer section.



Report design file woactualssubreport.rptdesign

Saturday, August 31, 2024

Maximo JSON Mapping

What is JSON Mapping ?
  • JSON Mapping is an application in Integration Module
  • A Mapper plugin  com.ibm.tivoli.maximo.fdmbo.JSONMapperExit used as Processing Class (or External Exit) in Publish Channel or Enterprise Service
Why it is used ?
        Used to convert messages of Maximo XML to JSON (Outbound) and JSON to Maximo XML (Inbound).

Applications support JSON
  • JMS Queues
  • Message Tracking & Message Reprocessing
  • Enterprise Services
  • Publish Channel
  • JSON Mapping Application
JMS Queues
  •        JMS Queues support JSON messages from Integration components like Enterprise Service or Publish Channel.
  •         Inbound JSON data is supported into JMS Queues using http/https end point or a direct update to JMS
  •        Not Supported - JSON data using Interface tables, Web Services or from a file upload
  •      Same JMS queue can be used for XML/JSON payload without any configuration
  •   Message driven Bean (MDB) and JMS Cron task psdi.iface.jms.JMSQueueCronTask will support the use of Selectors against queues with JSON data
  •      View Queue and Delete Queue that allows viewing or deleting of data in the queues will support messages in a JSON format
  •       JSON messages work for kafka topic because it  takes payload of base64 encoded compressed xml/json messages


Message Tracking  
        Message Tracking will save the payload in JSON format for Enterprise Services and Publish Channels where JSON Map is implemented.
        The Search and External Message IDs are supported using format -  $.header.attributeID   header is JSON object & attributeID is tag name with case sensitive

Sample JSON payload & its external message ID $.header.transactionId (case sensitive)

{
  "header": {   
    "reportedAsOfDateTime": "2024-04-24T00:00:00+05:30",
    "recordTotal": 1,  
    "transactionDateTime": "2024-04-29T03:30:00+05:30",
    "transactionId": "4a262629c1134b1eafed7b81dd50a6b",
  },  
  "data": {
    "assets": [
      {                     
        "assetId": 10000056,
        "assetLocationId": 10000062,      
        "assetCriticalityCode": 1,
        "assetStatusCode": "OPERATING",
        "assetStatusDate": "2022-06-06",
      }
    ]
  }
}


Message Reprocessing
        Message Reprocessing application supports both JSON and XML. Error Messages from Enterprise Services and Publish Channel with JSON Map can be viewed in the application as JSON. 
 
Enterprise Service
JSON Mapping for Enterprise Services can be used in a couple of scenarios: Asynchronous where ES is invoked with an inbound JSON message persisted to an inbound JMS queue or Synchronous http/https Call without JMS queue as an outbound response.

Enterprise Service using JSON Mapping need to have Processing Class (External Exit)  com.ibm.tivoli.maximo.fdmbo.JSONMapperExit or a Java class extending this class. This processing class is needed for both request and response side.

The mime type of content-type header parameter should be "application/json".

Publish Channel
JSON Mapping for Publish Channel to convert outbound XML message into JSON is used in scenarios: Data is pushed out by an Event/Data Export or triggered from an incoming message of an enterprise service (customization in java/scripting for Event Filter class is used to enable response to incoming message).

A JSON message placed in outbound queue can be processed by End points: HTTP/JMS/XML file. The XML file end point will create a file in JSON format.

JSON Mapping Application
JSON Mapping application is used for creation and configuration of a JSON Map used for Integration messages.
This application has fields for 
Mapping: This field need to be entered as per the Maximo naming convention for different Integration points. 
  • ExternalSytemName.EnterpriseServiceName.IN
  • ExternalSytemName.EnterpriseServiceName.RESPONSE (Outbound)
  • ExternalSytemName.PublishChannelName.OUT  
Object Structure: Object Structure of type INTEGRATION to map the JSON data
Direction: Inbound or Outbound Processing
End Point: Existing HTTP End point for JSON payload
URL: URL will be used to retrieve the sample JSON data for configuration. 

End point or URL should be able to access the sample JSON payload and populate the data in JSON document section. We are also allowed to manually enter the JSON data. It is recommended to have the content in simple editor like notepad before pasting in JSON document section as directly putting the content from browser will have junk character and cause problems on the mapping configuration. 

JSON Mapping Properties
Once we have pasted the content of the JSON data, we can proceed on the JSON object and its attribute mapping in the Properties tab of JSON Mapping application.

The JSON Mapping can be performed for Inbound and Outbound messages. 

Inbound JSON Message to Maximo XML mapping:
Please refer the steps documented in the reference link.

Maximo XML Message to Outbound JSON mapping:
We read the Interface specification document to know the expected JSON outbound message expected by external system. 

for example, we paste the sample message in JSON document section. 
{
  "header": {   
    "reportedAsOfDateTime": "2024-04-24T00:00:00+05:30",
    "recordTotal": 1,  
    "transactionDateTime": "2024-04-29T03:30:00+05:30",
    "transactionId": "4a262629c1134b1eafed7b81dd50a6b",
  },  
  "data": {
    "assets": [
      {                     
        "assetId": 10056,
        "assetLocationId": "POWERHOUSE",      
        "assetCriticalityCode": 1,
        "assetStatusCode": "OPERATING",
        "assetStatusDate": "2024-08-08"
      },
  {                     
        "assetId": 10058,
        "assetLocationId": "GARAGE",      
        "assetCriticalityCode": 1,
        "assetStatusCode": "DISPOSED",
"assetStatusDate": "2024-08-08",
        "disposalDate": "2024-06-06",
      }   
    ]
  }
}

Some rules to consider: 
assetStatusDate - date format should be yyyy-MM-dd
disposalDate - this field should be present only if assetStatusCode is DISPOSED or REPAIRED
assetLocationId - this value should be within an array even though we have single value in Maximo

Object Structure for this sample message is configured without any alias conflict:

JSON Mapping is defined for Outbound Asset data 

In the Properties tab, we set the JSON Object Mapping first. 






JSON Properties for Object Attributes: 
Process Order 1 and 3 are for header section only.

Simple Maximo XML field to JSON tag mapping

Formatting for Date field mapping


Conditional Values: Disposed Date field should be set only for statuses [DISPOSED & REPAIR]

We can have multiple conditions for the mapping of one field.


Valid Condition Syntax must align with JavaScript Notation. 
attr$STATUS=="DISPOSED" || attr$STATUS=="REPAIR"
attr$STATUS=="DISPOSED" && attr$STATUS=="REPAIR"


Concatenation of values in Source Attribute 


Limitations
  • Maximo accepts Array for JSON Objects level, but not at JSON Attribute level. So if the external system needs a JSON value within an Array, we need to convert it in User Exit class. for example, "location":["30045", "56789" , "67890"] It is considered as a single value and can't be pared in Maximo.   
  • JSON Map is not supported for Invocation Channel
References: 

Tuesday, July 30, 2024

Maximo Loggers and Appenders

What is Logging ?
  • Logging is required for investigating issues in Live system. 
  • Without logging, it's very difficult to identify the source of the problem for resolution
Maximo Logging
  • Maximo Uses Log4j. Log4j is an open source independent logging framework developed by Apache. It's not part of standard Java API.
  • Log4j provides the ability to selectively enable or disable logging requests based on Maximo logger.
  • Log4j allows logging requests to print to multiple destinations (or Maximo Appenders). 
Logging properties in Maximo
  • Logging properties are available inside Maximo application (System Configuration --> Platform Configuration --> Logging) and stored in the database.
  • There are 3 components on properties: Loggers, Log Appenders and Layout
What are Maximo Loggers ? 
  • Loggers are the component of Maximo that prepare log statements
  • It follows hierarchical naming rules with dot notation

How Log statements are handled ? 

         Log statements are either written to User Interface consoles or sent as output to log files.

What is Maximo Root Logger ? 
  • Root Loggers are at top application functional level or main subtopic of loggers.
  • A logger is said to be an parent of another logger if its name followed by a dot is a prefix of the child logger name.
  • Without root (or main) logger, no logging will work in Maximo.

What is a child logger ? 
  • Parents are root loggers and child loggers are the loggers that inherit the log message level of the root logger. 
  • They contain the name of the root logger in their names.
Can we deactivate loggers ? 
  • Root Loggers can't be deactivated, but child loggers can be deactivated.
  • System Users determine the size that is required for Appenders. 
What is an Appender ? 
  • An Appender is a log file or location created by Maximo where log information is written.
  • Each enabled logging request for a given logger will be forwarded to all the linked Appenders as well as the Appenders higher in the hierarchy.
  • Appenders are used to forward log messages to different destinations such as files, databases, console, cloud etc.,
  • Log4j appenders exist for the Console, files, GUI components, remote socket servers, JMS, NT Event Loggers, and remote UNIX Syslog daemons. 
  • Maximo uses only file type Appenders.  
Maximo has 3 predefined Appenders:
  • Console - Writes log information to Console or std.out (SystemOut.log file)
  • RollingWrites log information to specified file name and rolls to a new file when size is reached
  • Daily RollingWrites log information to specified file name and rolls to a new file by EOD
MX File Appender is Maximo's extension of Log4J Appenders: 
psdi.util.logging.MXDailyFileAppender.MXFileAppender psdi.util.logging.MXDailyFileAppender.MXDailyFileAppender

Log Appender Layout
  • Layout is used to format the log output written to a file.
  • A layout is associated with a Log4J appender
    • log4j.appender.Console.layout=psdi.util.logging.MaxPatternLayout
    • log4j.appender.Console.layout.ConversionPattern=%d{dd MMM yyyy HH:mm:ss:SSS} [%-2p] [%s] [%q] %m %n %C{1} %M{1} %L %t
    


      • %d - date format given inside brackets{ } 22 JUL 2024 16:40:57:636
      • %-2p - log level [INFO] priority of logging event, left justified to a width of 2 characters
      • %s - Maximo Server Name  [MXServer-UI1]
      • %q - Log correlation entries in format [CID-TYPE-NUMBER]. TYPE is CRON or UI. To enable this property, we need to activate a couple of system properties: mxe.logging.CorrelationEnabled=true Crontask & REST correlation will be enabled. A child property mxe.webclient.logging.CorrelationEnabled=false for enabling UI request Correlation. Logger pattern [%q] and System property both need to be enabled to display correlation log ID. Each Correlation type has its own set of properties and they are printed at end of correlation log. UI request correlation prints out app name, UI session id, UI event identifier, client IP, elapse time etc. Crontask action correlation prints out Crontask name, instance name and elapse time.
      • %m - Maximo message BMXAA6719I
      • %n - System independent new line separator
      • %C - fully qualified class name of the caller issuing the logging request psdi.app.actionscfg.CustomClass %C{1} - CustomClass
      • %L - line number of the code  psdi.app.actionscfg.CustomClass 272
      • %M - method name of the Class issuing the logging request
      • %t - thread name that generated the logging event
      • %F - File name 
      •      


How do Loggers and Appenders interact ? 
  • A Logger can have either one or multiple Appenders. 
  • An Appender can have output from either one or multiple loggers. 
Log Message Levels
  • Every loggers needs a log level There are 5 log message levels in Maximo: FATAL < ERROR < WARN < INFO < DEBUG
  • If a given logger is not assigned a level, then it inherits one from its closest ancestor with an assigned level
Logger in Automation Script
from psdi.util.logging import MXLoggerFactory  
logger = MXLoggerFactory.getLogger("maximo.script")

logger.debug ("Debug level log messages")
logger.info ("Info level log messages")
logger.warn ("Warn level log messages")
logger.error ("Error level log messages")
logger.fatal ("Fatal level log messages")
Impacts
  • Enabling UI correlation causes a delay because of light weight filter for UI events.
  • Enabling %C caller class name, %M method name, %L caller class line number and %F file location are extremely slow and should only be activated on critical investigation or performance is not an issue.
References:

Sunday, June 30, 2024

Automation Script as a Cron task

Automation Script can be used to create crontask without any Java customization file.
 
It's widely used option to avoid outage using Java Code for Cron task.

Cron task definition for an automation script has a Class file value and 2 parameters.
 
Class file value should be set to com.ibm.tivoli.maximo.script.ScriptCrontask

Cron task instance parameters: 
SCRIPTNAME - Name of the automation script without launch point
SCRIPTARG - Arguments to pass values to the Script
{"siteid": "BEDFORD","status": "'WAPPR','APPR','WMATL'"}


Automation Script - C_ASCRONTASK 
Script Name should be set as SCRIPTNAME parameter in Cron task
if arg is not None:
   args = service.tojsonobject(arg)
   
   assetSite = args.get('siteid')
   assetValidStatus = args.get('status')
   
   #service implicit variable is used to getMboSet since 7.6.1.2 . MXServer is not needed
   #runAsUserInfo is the userInfo of Cron task Instance
   assetSet = service.getMboSet("ASSET", runAsUserInfo)
   assetSet.setWhere("siteid='" + assetSite + "' and status in (" + assetValidStatus + ")" )
   assetSet.reset()
   
   assetMbo = assetSet.moveFirst()
   while (assetMbo): 
        # more logic 
	assetMbo = assetSet.moveNext()
   assetSet.save()
   assetSet.close()



Friday, May 31, 2024

Comparison of Maximo 7.6.x vs MAS 8.x for MAS Upgrade

As IBM planned to discontinue the regular base support for Maximo 7.6.1.x version on Sep'2025, clients are analyzing the impact on their existing Infrastructure and Systems. It's useful to know the basic difference between the versions for preparing for MAS Upgrade.

           Items
   Maximo 7.6.1.x
                MAS 8.x
Application Server
Websphere
WAS Liberty
Database
Normal JDBC configuration connected via client VPN
Hosted from IBM Cloud
Connection possible via SSL certification only
Server Folder/Logs
Server File path can be accessed using WinScp or putty tool and download the log file
Connection with accesskey & secretkey for Cloud Object Storage (like AWS Bucket).
Mobile Solutions
Maximo Anywhere and Work Centers

SSO not available in OOB Maximo Anywhere
Maximo Anywhere & Work Centers will be deprecated from 8.9 version.
 
SSO supported in Maximo Mobile Out of Box. 

Adoption to Maximo Mobile with MAS demands some effort for clients.
Hyper scalers
Can be hosted from Cloud Servers like EC2
Available in Amazon and Azure Marketplace with instructions.

Clients need resource with skillset of managing the infrastructure
Inspections Form and Conducting Inspections
Work Centers
Maximo Mobile
UI theme
          N/A
Old Maximo theme can’t be retained
Users
Users & Person applications
Users & person application with MAS Administration application.

MAXUSERSYNC will create users from MAXUSER table to Administration application
Self Service Portal (SSP)
SSP devops portal can be used for running configdb, restart servers, running sql etc.,
If we use IBM Cloud, then IBM SRE team will perform the activity by a case from client. 

If we use Azure/AWS Cloud, we can perform such actions on our own.
Messaging engine
JMS and Kafka providers are supported.

JMS queues are hosted in same Application server
JMS and Kafka providers are supported

JMS queues are hosted from a different server using a new bundle standalonejms to isolate the functionality.

A set of OOB kafka cron tasks to be enabled for MAS
UI Difference
           N/A
-> Save button is at right hand side in all application and it’s not easy to use

-> Buttons around the tables are different after Upgrade
MongoDB
           N/A
Used for data dictionary (like install.properties information and user management)
Production Database
Read access is given by default
Read access is given only if you buy a secondary database                                      
Customization
  Java files with proper folder structure.          Build EAR and deploy into Application Server.
Development is same, but deployment process is different. 

We need to create a zip file and upload to MAS.                                      
Reports
Barcode in BIRT Reports needs customization

Oracle Compatible SQLs (such as rownum, connect by prior) are allowed in DB2
Barcodes are supported in OOB BIRT Configuration


Oracle Compatible SQLs are disabled in DB2. We need to use an alternative sql in DB relationships and reports. Replacing "connect by prior" vs "with clause"                                 

References: