Using external Libraries in Jython

One big limitation of the Jython environment of ICD and Maximo is that the base installation only provides the jython.jar file in version 2.5.2 without any libraries installed. Exactly these libraries can help enormous to write powerful scripts. Some useful examples are httplib and urllib for web access or smtplib for mail functions to just mention some of them. A full reference of included libraries in standard Jython can be found here.

What many users will now know is that the jython.jar file installed in Maximo/ICD does, compared to the original version of this file, include all standard libraries from the Lib directory. That’s quit cool, because we can easily use these libraries in our own scripts without copying any files to the servers. The only thing to know is the exact path of the jython.jar file on the server. This is basically in:


So on my Windows demo server for example it can be find under:

C:\Program Files\IBM\WebSphere\AppServer\profiles\ctgAppSrv01\installedApps\ctgCell01\MAXIMO.ear\lib\jython.jar

The clue to use these libraries is to add the new library path in your script. To do so you need the following code:

# Extend the sys Path
import sys
foundJython = False
jythonLibPath = "C:\\Program Files\\IBM\\WebSphere\\AppServer\\profiles\\ctgAppSrv01\\installedApps\\ctgCell01\\MAXIMO.ear\\lib\\jython.jar\\Lib"
for path in sys.path:
    if (path.find(jythonLibPath) != -1) :
        foundJython = True
if (foundJython == False):
import re
mystring = "Hello World!"
test = re.match(r'(.*)World!', mystring)

hello =

print hello

Lines 1-9 are used to extend the sys-path. In the following lines I demonstrate the usage of the external library module re.

If you would like to use additional libraries, which are not included in the standard Jython package you need to copy the library source files to a new directory on the Maximo server and then include this directory in a similar manner like show above.

One improvement of the scenario show above is to use a property for the Jython path (for details see here). Change line 4 to the following code after you have created a Maximo property custom.jython.lib:

from psdi.server import MXServer
configData = MXServer.getMXServer().getConfig();
jythonLibPath = configData.getProperty("custom.jython.lib");

Read Maximo system properties in a Jython script

It is a good practise to store all properties like usernames, passwords, Url’s, etc in the Maximo System Properties. User defined properties can be defined in addition to all the tons of existing system properties. You will find the properties application under

System Configuration –> Plattform Configuration –> System Properties

To define a new property just click “New Row” in the Global Properties section:


The usage of these properties in a Jython script is quit easy. To read and print the new “custom.username” property the following script can be used:

from psdi.server import MXServer
configData = MXServer.getMXServer().getConfig();
maxProperty = configData.getProperty("custom.username");
print maxProperty


When tested in the Maximo Script editor the script should print out the username “bigadmin”. If you get a no output at StdOut or “None” you should verify if you made a live refresh of the property data.

Selecting specific Mbo’s using Relationships and Where Clauses

A very common scenario is that you would like to get an instance of a MboSet with not all records included, but only a subset. Spoken in SQL you would like to apply a where clause to limit the number of records you get as a result in a MboSet. In this article I will show you different ways on how you can achieve this.

  1. Usage of relationships

A very common pattern is to just use relationships when you initialize your MboSet. I have shown such a pattern in this article. You can easily define the where clause directly in the relationship and you will only get the records based on the where clause.

  1. Adding a Where-Clause to an existing MboSet

It is quit handy to add a Where-Clause to an existing MboSet. The following code example will show this scenario:

woset = session.getMboSet('WORKORDER')
woset.setWhere("WONUM = '2009'")
wo = woset.moveFirst()
if wo is not None:
    print "Workorder ",wo.getString("WONUM")

At the beginning you initialize a MboSet returning all Workorder’s in the system. In line 2 you append a Where-Clause to the result set. When you have used a relationship with an existing where clauses in it the new where clause will be appended. The woset.reset() method call in line 3 is required to “execute” the where clause and update the result set in woset. The rest of the script just shows the first record.

  1. Building a temporary relationship

This is one of my favorite patterns which can help you make life much easier. When you develop your script you will not always have the perfect relationship for navigation defined in the system. So you can either define a new relationship in database configuration or you can do this step directly from your Jython script. You define a new relationship just to be used temporarily in your script with no impact to the rest of the system.

The syntax based on the JavaDoc is:

public MboSetRemote getMboSet(java.lang.String name,
                              java.lang.String objectName,
                              java.lang.String relationship)
                    throws MXException, java.rmi.RemoteException

A real example statement to get all worklog entries for a specific workorder could look like this:

worklogset = wo.getMboSet("$TEMPREL1", "WORKLOG", "RECORDKEY='2009'")

$TEMPREL1 – An unique identifier for the relationship. It needs to be unique and for this reason it is good practice to start the name with a dollar sign.

WORKLOG – The database object which should be queried using any provided where clause.

RECORDKEY=’2009’ – The where clause to be applied to reset the MboSet of interest.

Adding Mbo records to a MboSet

In this blog I will show you in detail how to add new Mbo records to a MboSet.

The easy pattern

To do so we will directly start with a simple code example:

woset = session.getMboSet('WORKORDER')
wo = woset.add()
if wo is not None:
    wo.setValue("DESCRIPTION","New Testworkorder")
    wo.setValue("WOPRIORITY", 10)
    # Only save if necessary (e.g. Script executed via RMI)

This is the simplest form of adding a record. At the beginning we need to have a MboSet object stored to the woset variable.
By using the add method woset.add() a new record will be added to an existing MboSet. The record is added at the beginning of the MboSet. If you would like to add the new record to the end of the existing set you can use the woset.addAtEnd() method.

Very important is line 3 to check if we really have created a new object instance. Without that check our wo.setValue(..) method calls would result in Null Pointer exceptions. The wo.setValue method is quite easy to use to set the individual fields in the MboSet. The good thing at this method is that it does not differentiate between datatypes.

The method call is a bit special and need some explanation. Depending on the way you run your script you should or should not save the MboSet at the end:

  • In general no saving on object & attribute launchpoints
  • In general no saving in workflow actions
  • In general save in RMI Scripting, in direct invocation or when you act on a dialog button.

But as you can imagine there is no rule without exceptions and you eventually have to trial and error to find the correct usage.

Add Mbo records to multiple MboSet’s using transactions

In the previous example we just added a single record to a single Mbo. What if we wan’t to a add an additional Worklog entry to the new Workorder. What about transaction processing. We only want to create the Workorder together with the worklog entry or fail both. The following script shows such an example:

woset = session.getMboSet('WORKORDER')
wo = woset.add()
if wo is not None:
    wo.setValue("DESCRIPTION","New Testworkorder 3")
    wo.setValue("WOPRIORITY", 10)
    worklogset = wo.getMboSet("WORKLOGAPPT")
    worklog = worklogset.add()
    if worklog is not None:
        worklog.setValue("DESCRIPTION", "WLOG Descr.")
        print "Workorder " + wo.getString("WONUM")  + " created !"

This example is quite similar to the first one. The difference is that we navigate from our newly created workorder Mbo to a Worklog MboSet via a predefined relationship. Using a relationship at this point automatically holds together the two MboSets via a transaction. There is nothing else via have to do to create this kind of dependency! Cool, isn’t it?

The next line to mention is the statement. You could ask: “Why do we do not save the Workorder object?” My answer is: “Save the object you want! Since both MboSet objects are linked by a relationship it doesn’t matter which object you save. The result is the same!”

Jython Introduction

Jython is an implementation of the Python programming language designed to run on the Java Virtual Machine (JVM) and can be used for Maximo / ICD scripting development. The syntax of Jython is based on Python but Java libraries can be included and used in Jython. This is a major benefit when we use Jython for Maximo / ICD Development because on the one hand side you will find a lot of documentation especially for the Python language on the other hand side you can include all Java libraries used in Maximo / ICD. One of the most commonly used libraries is the businessobjects.jar file, which contains most of the business logic included in the product.

In Maximo and ICD up to release 7.6, there is a relatively old version 2.5.2 of Jython in use. If you develop your scripts you should keep this in mind as there is already Jython 2.7 available today which has some new features included.

In this blog, I will not provide a dedicated introduction into the Jython language since there is some very good stuff available on the internet. I will give you some links at this point:

  1. Official Jython Homepage – with references and tutorials
  2. The Definitive Guide to Jython – Very good book!
  3. Intro to Jython, Part 1: Java programming made easier – IBM Developer Works article
  4. The Jython Wiki

Navigate to different MboSet using Relationships

In this blog I will show you a way to navigate from a given Mbo to a different, related MboSet. The easiest way to perform such a navigation is to use a predefined relationship as it is defined in the database configuration of a table. For our example lets assume we are starting from the WORKORDER MboSet. We would like to print out all workorder activities for the first workorder we read.

The following script can be technical combined with the RMI introduction to get a quick result since it requires a valid session object.

woset = session.getMboSet('WORKORDER')
wo = woset.moveFirst();

if wo is not None:
    print "Workorder ",wo.getString("WONUM")    

    workActSet = wo.getMboSet("WOACTIVITY")
    workAct = workActSet.moveFirst()

    while (workAct != None):
        print "Workorder activity: ", workAct.getString("DESCRIPTION")
        workAct = workActSet.moveNext()

Some of the important commands in this example are:

  • if wo is not None: Very important! Check if we have found a workorder Mbo. If you do not do this check the next access like wo.getString(..) could lead to a null pointer exception.
  • worklogset = wo.getMboSet(“WORKLOGAPPT“) gets a reference to a different MboSet based on the current MBO in wo and the existing relationship “WORKLOGAPPT“
  • while (workAct != None) the loop construct to loop on all workorder actions. Have a look here to loop on MboSet’s.

Setting up Eclipse for Maximo / ICD Jython development


When you start developing Jython scripts in context of Maximo & ICD the first question is where to edit the scripts. The provided editor in the Web-interface of the product can only be seen as a “Paste-In” area, since it absolutely lacks any needed development features. Better alternatives at this point can be the usage of more professional editors like UltraEdit or Notepad++. If you only want to develop a small set of short Jython scripts this can be a starting point for you. If you plan to do a bit more development I would highly encourage the usage of a professional development environment. In this article I would like to show you how you can set up the Eclipse platform to perfectly act as a Maximo & ICD development environment. I will guarantee you that the benefits of this platform over time are major, even if it is a bit work to setup at the beginning.

Required Software

So before we start let’s figure out, which software is needed for the installation:

  • Eclipse Luna (Download) (64 Bit)
  • Java JRE or SDK V1.7 or V1.8 (64 Bit) *** please see notices below
  • Jython Interpreter V2.5.2 (Download) – Even it is quit old – this is the used Version in the product.

Notices on Java:
For the development of Jython scripts the used JRE or SDK is really important. For Maximo/SCCD 7.5.x (TPAE 7.5) you need at least a JRE Level of Version 1.6 for Maximo 7.6 (TPAE 7.6) you need at least a JRE Level Version 1.7. I personally always try to use the IBM Java in the version 1.7 and set the JRE Compliance level to 1.6 if needed. I will show you later on how to set this – don’t care for the moment.

The download of the IBM Java is a bit tricky to find. The base download page is can be found here. For Windows you need to download the complete “IBM Development Package for Eclipse”, extract it and take out the JRE directory. You should use Version 5.0 64-bit which includes Java 7.1 (1.7).

Installing the Prerequisites

The installation of the software is described in this section.

  1. Eclipse installation

For Eclipse no special installation is required. It basically only needs to be extracted to a folder of your choose. On the first start you can select the folder where you would like to store your eclipse workspace (data-directory).

  1. Java JRE (optional – you may use your system JRE)

Depending on the Java Version you have to either run a setup program or just copy some files. The installed Java does not have to be the system Java! This is important to know if you use different software on your computer which requires a certain version of Java.

If you use the “IBM Development Package for Eclipse” just extract the “ibm_sdk71” subfolder to a folder on your local harddisk for later usage.

  1. Jython 2.5.2 Installation

Jython Installation is quit straight forward using the setup program. During installation you are asked for the Java Home directory where you should be careful to select the one provided by the Java JRE Installation.


Configuration of the Java Environment (optional)

At this point we need to set up the correct Java Environment Eclipse should use.

  1. In Eclipse go to “Window –> Preferences”.
  2. In the left navigation pane go to “Java –> Installed JRE’s”. In the window on the right you should see the currently installed JRE selected. If you have installed an additional JRE and want to make this the default JRE select the Add button on the right.
  3. Select “Standard VM” and “Next…”
  4. The next screen requires the definition of the new JRE. If you select the correct installation directory for your JRE home the rest of the Fields should be filled in automatically:
  5. After selecting “Finish” a new SDK is available. The SDK which is checked and bold is the default SDK.

At the end the right Java compiler must be selected:

  • Maximo 6: Java 1.4
  • Maximo 7: Java 1.5
  • Maximo 7.5.x: Java 1.6
  • Maximo 7.6: Java 1.7

Set it in Eclipse preferences: Windows –> Preferences –> Java –> Compiler  –> Compile compliance level.


Installing the maximo.ear

The maximo.ear contains most of the Java method’s to operate on all kinds of Mbo’s and MboSet’s within TPAE. One of the best features of using Eclipse in comparison to a simple text editor is, that we can include the businessobjects JAR file from your Maximo/ICD installation and that we have some syntax checking and input features for these classes. I will show you in a later post how we can utilize these features to make our life easier.

The best way to make the JAR file available is to create an own project in Eclipse for the referenced Java libraries.

  • Select “File –> New –> Java Project” in the Eclipse Workbench with the name “MaximoLibs”.
  • Copy [SMPDIR]\maximo\deployment\default\maximo.ear from your admin workstation into the new project.
  • Extract the following files from the maximo.ear file:
    • jar
    • war and extract the content to a directory named maximouiweb
    • lib/*.jar files to a directory lib
  • Refresh the project tree in Eclipse (F5). Your project should now looks like follow:

Installing the PyDev Plug-In in Eclipse

After the initial start of Eclipse and the selection of a workspace directory you find yourself in the Welcome screen, which should be closed using the “Workbench” symbol in the upper right corner.

To install PyDev select the Menu “Help à Install new Software…”

  1. Enter the text into the Work with text box.
  2. Select only the PyDev checkbox
  3. Press the Next Button…
  4. You get the Installation Details displayed where you also can press “Next”
  5. Accept the License and press “Finish”. The installation starts.
  6. At the end of the installation you are asked to restart Eclipse. Please answer with “Yes”.

Configuring PyDev in Eclipse

To configure PyDev perform the following steps:

  1. After Restart, click Window and then click Preferences.
  2. Find the entry “Jython Interpreter” as shown in the picture and select “New…”
  1. Enter “Jython 2.5.2” as the Interpreter Name and find the jython.jar file from your previous Jython installation. Select “OK”.
  2. The configuration starts. Select OK in the dialog which appears.

At the End your Jython Interpreter Configuration should look similar to this one:


Create a new PyDev project

Now create a new PyDev project where you can store you Jython sources.

  • Select: File –> New –> Project
  • Select the wizard PyDev Project and select Next
  • Enter a project Name and select the correct Project Type Jython and the Grammar Version 2.5 with your defined Interpreter.
  • Press Finish.

You get a question if the associated PyDev perspective should be opened. Select Yes.

Congratulations you have your first Python/Jython project. There is still one little piece missing…

Referencing the Maximo Java libraries

In a previous step we have extracted the Maximo related Java libraries. To use them in our Jython project we need to reference them.

  • Right click to your new project in the PyDev Package Explorer window and select properties.
  • In the property window select the option “PyDev – PYTHONPATH”
  • Select the tab “External Libraries”.
  • Using the “Add zip/jar/egg” button you can add all required libraries from the referenced project. At least the businessobjects.jar file should be added, but all other jar files could be added in addition. At the end your configuration looks like this:

Creating your first Jython Script

To create the first Jython script right click on your newly created project and select New –> File in the Popup Menu. Select a filename of your choose with the extension “.py” and click on Finish.

You are asked for the Default Eclipse preferences for PyDev. Just click ok.

You are now ready to create your first Jython script, but this is a story for another post.

Output fields from a Mbo with different data types

TPAE supports nearly twenty different data types for it’s fields which can be used during database configuration. Commonly used types are ALN, DATE, INT, UPPER, YORN just to mention some of them. A full list of available datatypes can be found on the support webpage.

When we read records using a script we have to be very carefully to always use the correct command which is related to the data type of the field. Some important commands are:

  • wo.getString(“<FIELD>”) – returns a String value
  • wo.getInt(“<FIELD>”) – returns a Integer value
  • wo.getLong(“<FIELD>”) – returns a BigInteger value
  • wo.getDouble(“<FIELD>” – returns a Double/Decimal value (better than getFloat()).
  • wo.getDate(“<FIELD>”) – returns a Date value
  • wo.getBoolean(“<FIELD>”) – returns Boolean Value from a YORN Field (True / False)
Attention: It is a common mistake to use the getString method to read numeric values which will work without errors. The issue you will fall into is that numbers are represented  with thousands separators so a number 1000 is represented as a string “1.000”.

In context of the workorder MboSet a code sample could be the following one, which reads different fields with different data types:

 woset = session.getMboSet('WORKORDER')
    wo = woset.moveFirst()

    while (wo != None):
        # Read out values
        print "Workorder ",wo.getString("WONUM")
        print "Priority ",wo.getInt("WOPRIORITY")
        print "StartDate ", wo.getDate("TARGSTARTDATE")
        print "WorkorderID ", wo.getLong("WORKORDERID")
        # get next Workorder
        wo = woset.moveNext()

Loop MboSet and output Mbo content

A very common programming pattern is to loop on a MboSet and read information from the included Mbo’s. This example can be technical combined with the RMI introduction to get a quick result since it requires a valid session object.

In this example I would like to show how to loop on all existing workorders in the system. Later on we will see how to select specific records from a MboSet, but for now let’s start with all workorders in the system. The following pattern can be used to achieve that objective and print out the workorder numbers:

woset = session.getMboSet('WORKORDER')

for i in range(0,woset.count()):

    # get one Workorder Mbo
    wo = woset.getMbo(i)

    # Read out a value
    print "Workorder ",wo.getString("WONUM")

Some of the important commands in this example are:

  • woset = session.getMboSet(‘WORKORDER’) – method to get a MboSet and stores this in the variable woset – in that case based on the session object
  • woset.count() – returns the number of records in woset
  • woset.getMbo(i) – gets the Mbo with index i
  • wo.getString(“WONUM”) – returns the string from DB Field WONUM from the Workorder Object

As always in programming there are often different ways to achieve the same goal and so I would like to introduce a different way on how it is possible to loop on a MboSet:

woset = session.getMboSet('WORKORDER')
wo = woset.moveFirst()

while (wo):
    # Read out a value
    print "Workorder ",wo.getString("WONUM")

    # get one Workorder
    wo = woset.moveNext()

In that case we use the methods of the MboSet object to navigate around using some simple commands:

  • wo = woset.moveFirst() – gets the first record from the woset
  • woset.moveNext() – moves the pointer to the next record in woset
  • while (wo != None) – loops as long as wo has a valid record (not at the end)
1 2 3 4