Thursday 17 September 2015

MBO Date Formats

Sometimes we need to filter the MboSet records based on dates.
  • By using MXFormat.dateToSQLString(Date d) you can get the date format as "yyyy-MM-dd".

For example:
MboSetRemote mboSetRemote = getMboSet("ASSET");
mboSetRemote.setWhere(MXFormat.dateToSQLString(getDate("STATUSDATE")));

Here MXFormat.dateToSQLString will return date as string and format is '2015-09-17' (with single quotes).

  • If your database is using different date format, then update it in system properties mxe.db.format.date and use SQLFormat.getDateFunction(Date d)

For example:
MboSetRemote mboSetRemote = getMboSet("ASSET");
mboSetRemote.setWhere(SQLFormat.getDateFunction(getDate("STATUSDATE"));

Here SQLFormat.getDateFunction will return date as string in two ways:

1. If mxe.db.format.date is not null/blank then it will return string with given date format in this property.
for example: If mxe.db.format.date is dd-MM-yyyy, then return string will be '17-09-2015' (with single quotes)
2. If mxe.db.format.date is null/blank, then it will return same as MXFormat.dateToSQLString method, i.e. '2015-09-17' (with single quotes).

Hope it helps :)

Wednesday 9 September 2015

BMXAA6002E - You cannot save object JOBPLAN : Job Plan=TESTJP1 Organization=ORG1 Site=SITE1 Revision=0 because of the data security restrictions. If you save the object, it becomes read-only and hidden

Error: BMXAA6002E - You cannot save object JOBPLAN : Job Plan=TESTJP1 Organization=ORG1 Site=SITE1 Revision=0 because of the data security restrictions. If you save the object, it becomes read-only and hidden

Environment: Maximo 7.6.0.1

Steps to reproduce above error:

1. Create a job plan and save it with DRAFT status.
2. Create a condition expression "status <> 'DRAFT'".
3. Create a global data restriction --> Object restriction --> Object JOBPLAN , app JOBPLAN , READONLY and add condition created in step 2.
4. Create a new user and associate a security group which has access job plan application (not maxadmin group).
5. Login with new user and go to job plans application.
6. Change status of job plan created in step 1 to ACTIVE and save the record.
7. Above error will occur.

Note: These steps will reproduce error in Maximo 7.6.0.1. In Maximo 7.1, job plans are editable even status is ACTIVE. So above steps will not reproduce errors in Maximo 7.1.

Cause: Out of box Job plan mbo is flagged to readonly when status is ACTIVE or INACTIVE. In our case, condition again trying to flag it readonly for the same mbo, hence this error occurs.

Solution: No need to put condition for Job plan to make it READONLY when status is ACTIVE or INACTIVE.

These are just my findings, if anyone have different approach, please provide your inputs in comments.

Friday 4 September 2015

Maximo restore database error in SQL Server

System.Data.SqlClient.SqlError: RESTORE cannot process database '<DbName>' because it is in use by this session. It is recommended that the master database be used when performing this operation.

While restoring database, faced above issue.

Even though all services stopped, still restore database given error that “Database is in use by this session”

Solution:

Connect to Sql server management studio:

Expand Security à Login à Right click on “maximoà Click Properties

 Default database:” value = <your database name>. Change it to “master”.

Friday 24 July 2015

Automation Script - Retrieve List

Sample code - Retrieve list event of attribute launch point in automation script:

In my example, I want to display only PR companies starting with "SK".

1. Created a table domain, TEST_COMP_SK
2. Create a attribute launch point and select option "Retrieve List".

Launch point name: TEST_PRVENDOR
Object: PR
Attribute: VENDOR

Script Name: TEST_RETRIEVELIST
Script Language: jython

Source Code:

domainid = "TEST_COMP_SK"
listWhere = "COMPANY LIKE 'SK%'"
listOrder = "COMPANY"

Save the script.

THATS IT :)

Now you can test in PR application - Company lookup - It will display companies starting with SK and order by company name ascending.

Below information will give the list of implicit variables in Retrieve List event:

1. domainid - Specifies the domain that is used to provide the list of values that are shown for the attribute launch point.
2. listWhere - Establishes which set of result data is displayed and which filter is set before the results are shown. Set the listWhere variable to a WHERE clause that uses the related MBO.
3. listOrder - Set to any ORDER BY attribute names that are used to order the results of the retrieve list event.
4. relationObject - Applies to the related MBO that is searched from the current MBO.
5. relationWhere - Establishes the criteria that is used to perform the retrieve list event. Set to a WHERE clause that queries the related MBO.
6. srcKeys - Applies to the set of attribute names from the current MBO that is used to lookup a related record in another related or target MBO. For example, the set of attribute names from the current MBO might be used to look up that FAILURECODES field from the ASSET business object.
7. targetKeys - Applies to the set of attribute names in the target MBO that is looked up from the current MBO on which the attribute launch point is defined.
8. listErrorGroup - Identifies the group ID of the message that the user sees when the retrieve list event fails.
9. listErrorKey - Identifies the key ID of the message that the user sees when the retrieve list event fails.

Source: http://www-01.ibm.com/support/knowledgecenter/SSLKT6_7.6.0/com.ibm.mbs.doc/autoscript/r_variables_automation_scripts.html?lang=en



 

Monday 15 June 2015

Error: The mbo value info for atttribute AUTHALLGLS for object grpreassignauth could not be retrieved

One of my friend faced this issue. This error is little bit tricky, because there is no attribute called "AUTHALLGLS" exist in GRPREASSIGNAUTH table. But still maximo throws this error. And also error logs will not provide any detailed information. This error can find in system out log as a warning.

This error can occur while creating new security group or assigning security group to user.

Cause: Few security groups has granted access to create users.

Solution: Except for MAXADMIN security group, need to remove granted access to create users for other security groups.

I am providing this in my blog, just in case, if anyone faces this issue and not to waste their time to solve it.

 

Tuesday 9 June 2015

Continous queue stopped processing records into queue.

While importing records into Maximo using continuous queue, after certain amount of errors (in my case, after every 10 errors) in message reprocessing application, continuous queue stopped working.

To solve this issue, I followed below steps:

1. Enable MDB bean for cqin err:

Take a backup of "ejb-jar.xml" from "<Drive>:\IBM\SMP\maximo\applications\maximo\mboejb\ejbmodule\META-INF"
Open the file from "ejb-jar.xml" in notepad++, search for "MEA MDB for error queue". Uncomment it.

BEFORE CHANGE:

<!-- MEA MDB for error queue
    <container-transaction>
     <method>
        <ejb-name>JMSContQueueProcessor-2</ejb-name>
        <method-name>*</method-name>
     </method>
   
     <trans-attribute>Required</trans-attribute>
   
    </container-transaction>
-->

AFTER CHANGE:

<!-- MEA MDB for error queue-->
    <container-transaction>
     <method>
        <ejb-name>JMSContQueueProcessor-2</ejb-name>
        <method-name>*</method-name>
     </method>
   
     <trans-attribute>Required</trans-attribute>
   
    </container-transaction>

Take a backup of "ibm-ejb-jar-bnd.xmi" from "<Drive>:\IBM\SMP\maximo\applications\maximo\mboejb\ejbmodule\META-INF"
Open the file from "ibm-ejb-jar-bnd.xmi" in notepad++, search for "MEA MDB for error queue". Uncomment it.

BEFORE CHANGE:
<!-- MEA MDB for error queue
  <ejbBindings xmi:type="ejbbnd:MessageDrivenBeanBinding" xmi:id="MessageDrivenBeanBinding_1" activationSpecJndiName="intjmsacterr">
    <enterpriseBean xmi:type="ejb:MessageDriven" href="META-INF/ejb-jar.xml#MessageDriven_JMSContQueueProcessor_2"/>
  </ejbBindings>
-->
AFTER CHANGE:
<!-- MEA MDB for error queue-->
  <ejbBindings xmi:type="ejbbnd:MessageDrivenBeanBinding" xmi:id="MessageDrivenBeanBinding_1" activationSpecJndiName="intjmsacterr">
    <enterpriseBean xmi:type="ejb:MessageDriven" href="META-INF/ejb-jar.xml#MessageDriven_JMSContQueueProcessor_2"/>
  </ejbBindings>

Rebuild and Redeploy maximo.

2. Login into Maximo:

Go to --> System Configuration--> Platform Configuration --> Select "Crontask setup" --> Search for "JMSQSEQCONSUMER" and open it.

Create a crontask instance of "CQINERR", Schedule "30s,*,*,*,*,*,*,*,*,*", Runas user "MAXADMIN".
 In parameters, Enter below values:
MESSAGEPROCESSOR = psdi.iface.jms.QueueToMaximoProcessor
QUEUENAME = psdi.iface.jms.QueueToMaximoProcessor
ERRORQUEUE = 0
TARGETENABLED = 0

Activate the instance and save the crontask.

3. Change destination of errors in websphere:
Login into websphere.
In Left panel --> Expand "Service Integration" --> Click on "Buses" --> Right panel click on "intjmsbus"-->Under "Destination Resources" click on "Destinations" -->Click on CQINBD -->Under "Exception Destination" select "Specify"--> Enter the value CQINERRBD --> Click "Apply" --> Save it into master --> Click ok --> Save it into Master.
Note: No need to restart server.

Testing:

Import 100 error records into any application and search in message processing that all 100 records exists in it. Earlier it was only 10 error records in my case, now it shows all 100 records.
In websphere, you can notice that all error records are moved into cqinerrbd destination.

I hope this article may help to some one who are new to maximo websphere process. As I suggest always, first try in development environments and also above mentioned parameters may differ based on environments.




 

BMXAA0667E - The value of the changed attribute could not be assigned.

Error: BMXAA0667E - The value of the changed attribute could not be assigned.


 I faced this error, when trying to update length of one field in INVENTORY table. The field which I am trying to update length is a same as object and same as attribute in INVVENDOR table. So I started investigating INVVENDOR table, then I found below cause.

In my environment, problem is, INVVENDOR has a audit table A_INVVENDOR, but audit enabled is unchecked.
While investigating, found that, audit table A_INVVENDOR details available in MAXATTRIBUTECFG and MAXATTRIBUTE tables, but A_INVVENDOR table itself not exist.

Note: Before doing below changes, make sure you have backup of database. And better try in your development environment first.

Steps:

1. In database configuration, INVVENDOR table, make sure audit is disabled and audit table field is blank. In my case, audit enabled is false, but audit table field has value A_INVVENDOR. To remove, audit table field (it is read only), first check the check box of audit enabled, it makes audit table field editable. Now remove value of audit table field and uncheck audit enabled field. Save the record.

2. Apply configuration changes. It will remove A_INVVENDOR meta data available in MAXATTRIBUTECFG and MAXATTRIBUTE tables.

3. Now, change the length of the required field in INVENTORY table and save the record. Error will not occur.

 

Tuesday 2 June 2015

Maximo attachments - doclinks

Step 1:
Create folder doclinks in your drive. And also create subfolders under doclinks --> "attachments", "images" and "diagrams".
Names of the folders are case sensitive.

Step 2:

1. Take a backup fo httpd.conf file from path <drive>\IBM\HTTPServer\conf
2. Open httpd.conf file from path <drive>\IBM\HTTPServer\conf
3. Find ‘DocumentRoot’ and change DocumentRoot "D:\doclinks"
4. Save and close the file.


Step 3:
Go to System properties application:
1. mxe.doclink.doctypes.defpath = D:\doclinks
2. mxe.doclink.path01 = D<PATH>\doclinks = http://<servername or IP>
3. mxe.doclink.doctypes.topLevelPaths = D:\doclinks
4. Rebuild and restart the server.


Step 4:
Login into Maximo.
Go to any application --> From select action menu click on "Manage folders"
Attachments = D:\doclinks\attachments
Images = D:\doclinks\images
Diagrams = D:\doclinks\diagrams



Step 5: Testing
Go to PR application --> Click new row and attach a document
Save it. Then click view attachments and click on the attached file. File will be opened.

Hope this topic will be helpful!! :)

Tuesday 26 May 2015

Automation Script - get current date and time.

In automation script, there is no implicit variable available to get current date and time. I followed below procedure, to get current date and time to set date time field.

from java.util import Calendar

#Create a instance for Calendar
cal = Calendar.setInstance();

#Get Current date and time by using cal.getTime()
currentDateTime = cal.getTime();

#AS I AM APPLYING THIS SCRIPT TO WORKTYPE OF WORKORDER, ALREADY DECLARED VARIABLES FOR WORKTYPE as worktype AND TARGSTARTDATE as tsd

if worktype="CM":
 tsd = currentDateTime


Hope it helps to someone who are new to set date time in automation script.

 

Friday 22 May 2015

Route stops data loading

While loading route stops, make sure below fields are exist in your file:

ASSETLOCORGID
ASSETLOCSITEID
ROUTESTOPID (This field is to provide sequence number of route stop for a respective route)

If those fields are not exist and trying to load route stops with locations, error will appear "XXXXX is not a valid location".

ROUTESTOPID will help to avoid routestop duplicates.
For example:
ROUTE,ASSETNUM,LOCATION,JPNUM,STOPSEQUENCE,SITEID,ROUTESTOPID
1001,,LOC1,,10,SITE1,1
1001,,LOC2,,20,SITE1,2
1002,LOC21,,10,SITE1,1
1002,LOC22,,10,SITE1,2
1002,LOC23,,10,SITE1,3
1002,LOC24,,10,SITE1,4

if you don't provide ROUTESTOPID, when doing routes data loading second time, it will add duplicate records.
Below format will create duplicate records in route stops:
ROUTE,ASSETNUM,LOCATION,JPNUM,STOPSEQUENCE,SITEID
1001,,LOC1,,10,SITE1
1001,,LOC2,,20,SITE1
1002,LOC21,,10,SITE1
1002,LOC22,,10,SITE1
1002,LOC23,,10,SITE1
1002,LOC24,,10,SITE1 

PM Records data loading

While data loading PM records, make sure USEFREQUENCY = 1 for frequency based PMs.

Otherwise, problem is, even though you saved the record, it will ask again to save the pm record. PM Work orders will not generate.

Monday 18 May 2015

Actions in Maximo Integration Framework

Add – Add records
AddChange – Add or update existing records
Change – Update existing records
Delete – Delete records
Replace – Substitute existing records
null – Add records or replace records depending on whether the primary record exists in the database.
  • If the primary record does NOT exist in the database, the system performs an Add action
  • If the primary record DOES exist in the database, the system performs a Replace action.

Friday 8 May 2015

Maximo training videos

IBM Maximo Education Assistant:

http://www-01.ibm.com/support/knowledgecenter/#!/tivoli_iea/com.ibm.iea.mam/mam/7.6/content_list.html 

Tuesday 5 May 2015

Increase list of display applications in "My Recent Applications"

System properties has a property called "webclient.maxRecentApps".

Default value is 8.
Increase/decrease the value and save the record. Click on the 'Live Refresh' and click Ok.

The property will now be updated.

If you want to disable this option. Set value to 0 and save the record. Click on the 'Live Refresh' and click Ok.

Automation Script - get difference between dates

If you want to get a difference between two dates in Maximo automation scripts, I tried below process:

For example:
In Work Order, you want to find a days between Target Start Date and Target Finish Date.

Target Start Date is "01/Apr/2015"
Target Finish Date is "25/Apr/2015"
Difference from Target Start Date and Target Finish Date is 25

Lets see how to write automation script:

Object: WORKORDER

Varibles declared as:

tsd = Target Start Date
tfd = Target Finish Date
dayselapsed = CUSTOM_DAYSELAPSED (Custom attribute to set days - integer)

Script as follows:

#************** AUTO SCRIPT START ***************
#Define a function to get date difference
#************** FUNCTION START ***************
def getDateDiff(timeDiff):

#Seconds in Millis
 milliseconds = 1000

#Minutes in Millis
 milliminutes = milliseconds * 60

#Hours in Millis
 millihours = milliminutes * 60

#Days in Millis
 millidays = millihours * 24

#Get days diff
daysDiff = timeDiff / millidays

#Get hours diff
hoursDiff = timeDiff/millihours

#Get minutes diff
minDiff = timeDiff / milliminutes


#Return days difference
if(daysDiff != 0):
 return int(daysDiff)

#Return hours difference
if(hoursDiff != 0):
 return int(hoursDiff)

#Return minutes difference
if(minDiff != 0):
 return int(minDiff )

#************** FUNCTION END ***************

#Time difference between two dates
timeDiff = tsd.getTime() - tfd.getTime()
daysDiffernce = getDateDiff(timeDiff)
dayselapsed = daysDifference

#************** AUTO SCRIPT END ***************

For few developers, if above script confuses you, below script without comments, to return days difference:

#************** AUTO SCRIPT START ***************
#Define a function to get date difference
#************** FUNCTION START ***************

def getDateDiff(timeDiff):
 milliseconds = 1000
 milliminutes = milliseconds * 60
 millihours = milliminutes * 60
 millidays = millihours * 24

daysDiff = timeDiff / millidays
hoursDiff = timeDiff/millihours
minDiff = timeDiff / milliminutes

if(daysDiff != 0):
 return int(daysDiff)

#************** FUNCTION END ***************

timeDiff = tsd.getTime() - tfd.getTime()
daysDiffernce = getDateDiff(timeDiff)
dayselapsed = daysDifference

#************** AUTO SCRIPT END ***************

 

Automation script integer variables

When I started writing a auto script to copy one INTEGER value into another INTEGER value, I feel that it is very easy to do. Offcourse it is easy, except you are able to solve the below error:

java.lang.ClassCastException: java.math.BigInteger incompatible with java.lang.String

I will explain you in detail, when you will face this error

For example, in work order I would like to set wopriority and assetlocpriority based on work type.

Created a attribute launch point script.

Variables declared as follows:

object is WORKORDER

wp = WOPRIORITY
alp = ASSETLOCPRIORITY
worktype = WORKTYPE

Script as follows:
#Script is for if work type is CM, then copy assetlocpriority to wopriority

if worktype == "CM":
 wp = alp

# Here you will get a error that
"java.lang.ClassCastException: java.math.BigInteger incompatible with java.lang.String"

This is because auto script considering these wp and alp as longs. I am not sure why it is like that and why it is throwing an error.
Hence I tried to print it.

print wp
#output is 2L
print alp
#output is 4L

From above output, I felt that, error is because of "L". Hence I tried to change to output without "L" like 2 and 4

So I did casting with integer like int(alp), it is printing output as "2" (without "L")

Corrected Script as follows:
#Script is for if work type is CM, then copy assetlocpriority to wopriority

if worktype == "CM":
 wp = int(alp)

Now it is working fine. No error.

 

Automation Script dates

To add DAYS to date:

For example, in Work Order we have target start date and target finish date:

now we will get the Target Start Date and Target Finish Date as variables tsd" and "tfd respectively.

In automation script, if we want to add two days to "Target Start Date" and copy it into "Target Finish Date"

# First import Calendar
from java.util import Calendar

#Create a Calendar instance
cal = Calendar.getInstance()

#Set calendar date as Target Start Date. Variable is defined in automation script as "tsd"
cal.setTime(tsd);
# ADD TWO DAYS TO TARGET START DATE
cal.add(cal.DATE,2)

#SUBSTRACT TWO DAYS TO TARGET START DATE
cal.add(cal.DATE,-2)

#ADD TWO WEEKS TO TARGET START DATE
cal.add(cal.DATE, 2*7)

#SUBSTRACT TWO WEEKS TO TARGET START DATE
cal.add(cal.DATE, -2*7)

#ADD 4 MONTHS TO TARGET START DATE
cal.add(cal.MONTH,4)

#SUBSTRACT 4 MONTHS TO TARGET START DATE
cal.add(cal.MONTH,-4)

#ADD 5 YEARS TO TARGET START DATE
cal.add(cal.YEAR,5)

#SUBSTRACT 5 YEARS TO TARGET START DATE
cal.add(cal.YEAR,-5)
#SET NEW DATE WITH INCREMENT/DECREMENT FROM CALENDAR TO TARGET FINSIH DATE
tfd = cal.getTime();



 

Maximo automation script mboset iteration

To iterate mboset records using automation script:

Usually we do below coding in java using Maximo API:

In the below example, taking PR as MboSet:

MboSetRemote prSet = MXServer.getMXServer().getMboSet("PR",MXServer.getMXServer().getSystemUserInfo());
prSet.setWhere("prnum = '"+<PRNUM>+"' and siteid = '"+<SITEID>+"'");
prSet.reset();

MboRemote pr = null;
int i = 0;

if(!prSet.isEmpty()){
  while((pr=prSet.getMbo(i)) != null){
      pr.setValue("description","TEST PR");
      i++;

     }
  prSet.save();
}

Now we will do above logic in Automation Script:



from psdi.server import MXServer

mxServer = MXServer.getMXServer()

prSet = mxServer.getMboSet("PR",mxServer.getUserInfo())
prSet.setWhere("prnum = '"+<PRNUM>+"' and siteid = '"+<SITEID>+"'")
prSet.reset()

prRemote= prSet.moveFirst()
while prRemote:
 prRemote= prSet.moveNext()

prSet.save()

Monday 20 April 2015

Throw warning in Maximo Automation Script

To throw warning in automation script:

warning = MXApplicationException(msggroup, msgkey, msgparams);
mbo.getThisMboSet().addWarning(warning);



 

Throw error in Maximo Automation script

In Maximo, all messages like errors, warnings and info are available in maxmessages table with msgkey and msggroup.

To throw an error in autoscript:

errorgroup=<msggroup>
errorkey=<msgkey>

In case of parameters:
errorgroup=<msggroup>
errorkey=<msgkey>
params=[<param1>,<param2>...etc]

For example I have created an error message in maximo using database administration --> Messages

msggroup = TESTGRP
msgkey = TESTKEY
msgvalue = "This is a test message"

in automation script, it is easy to display error message by using below code:

errorgroup=TESTGRP
errorkey=TESTKEY

in case of params:

For ex: my message value has : msgvalue = "This is a test message by {0}"

errorgroup=TESTGRP
errorkey=TESTKEY
params=[user]


 

Maximo Automation Script - Create Action Launch Point

It is simple to create a action launch point.

In my case, I have created a sigoption in Purchase Order application.

1. Sigoption name is : CREATEPOEXT - by using app designer

In sigoption --> Advanced Signature Options --> select the radio button "This is an action that must be invoked by user in the UI"

Give the position in your select action menu in app designer.

Grant access to this sigoption in your security group applications.

2. Automation script

Go to System Configuration --> Platform Configuration --> Automation Script application
From list tab --> Select "Create" --> click on "Script with Action Launch Point"

Enter Launpoint name same as your sigoption created for your application:
Launpoint : CREATEPOEXT
Active: Yes
Object: PO
Action: CREATEPOEXT
Note: Action name will auto generate same as launch point name.
Click next and enter your variables and automation script. Save the record. That's it.

3. Main point is, you don't have to create a Action separately in Actions applications.
for ex: Action "CREATEPOEXT" automatically created in Action applications.

Action will be created like below, in our case:

Action: CREATEPOEXT
Object: PO
Type: Custom Class
Value: com.ibm.tivoli.maximo.script.ScriptAction
Note: Above value is common class for all action launch point related actions.
Parameter: CREATEPOEXT,CREATEPOEXT,CREATEPOEXT
In parameter, you noticed that there are three values. Let me explain what are they
1. Script name
2. Launch point name
3. Action name
in my case all names are "CREATEPOEXT"

So by any chance, if you miss any of those values in your "parameter" field of action, then it will throw error at the point of automation script execution.

 

Maximo SOAPUI error javax.xml.ws.WebServiceException

SOAPUI error while sending payload to below url (in cluster environment) http://localhost:9080/meaweb/services/MXASSET Error : <f...