July 19, 2013

Custom Java Action Class Example

This entry is part of the Maximo Java Development series.

In a previous post I have described how create a custom action class using Java.

Here is a full example that can help to understand how to navigate objects and set values.

package cust.psdi.app.workorder;

import java.rmi.RemoteException;

import psdi.common.action.ActionCustomClass;
import psdi.mbo.MboConstants;
import psdi.mbo.MboRemote;
import psdi.mbo.MboSetRemote;
import psdi.util.MXException;

/**
 * Sets the Workorder description with a new one obtained concatenating the
 * following related descriptions:
 * - :JOBPLAN.DESCRIPTION
 * - :PM.LOCATIONS.DESCRIPTION
 * - :PM.ASSET.DESCRIPTION
 * 
 * @author Bruno Portaluri
 */
public class ActionSetDescriptionFromPm implements ActionCustomClass
{
  public ActionSetDescriptionFromPm()
  {
    super();
  }

  public void applyCustomAction(MboRemote mbo, Object[] params) throws MXException, RemoteException
  {
    String desc = "";
    
    // Get the description of the Job Plan
    MboSetRemote jp = mbo.getMboSet("WO_JOBPLAN");
    if (jp.getMbo(0)!=null)
    {
      desc = desc + jp.getMbo(0).getString("DESCRIPTION");
    }

    
    // Get the description of the Job Plan
    MboSetRemote pm = mbo.getMboSet("WO_PM");
    
    if (pm.getMbo(0)!=null)
    {
      // Get the description of the PM's Location
      MboSetRemote locations = pm.getMbo(0).getMboSet("LOCATIONS");
      if (locations.getMbo(0)!=null)
      {
        desc = desc + " - " + locations.getMbo(0).getString("DESCRIPTION");
      }
      
      // Get the description of the PM's Asset
      MboSetRemote asset = pm.getMbo(0).getMboSet("ASSET");
      if (asset.getMbo(0)!=null)
      {
        desc = desc + " - " + asset.getMbo(0).getString("DESCRIPTION");
      }
    }

    // Truncates to fit the field length
    desc = desc.substring (0, 100);
    
    System.out.println("Setting WO's " + mbo.getString("WONUM") + " description:" + desc);
    
    mbo.setValue("DESCRIPTION", desc, MboConstants.NOACCESSCHECK|MboConstants.NOVALIDATION_AND_NOACTION);
  }
}


July 13, 2013

How to make record readonly based on an attribute's value

This entry is part of the Conditional Expressions HowTo.

A very typical customization task is to make readonly some records of a specific table based on the value of an attribute.
For example you may wish prevent the editing of purchase orders that have a total costs higher than 1000$ for a specific group. Here is a small tutorial about how you can achieve this.

Open Administration - Conditional Expression Manager application and create the following conditional expression:

  • Condition: POCOST
  • Description: Total cost is more than 1000
  • Type: EXPRESSION
  • Expression: totalcost>1000



Now go to the Security - Security Groups application. Choose the desired group and open the Data Restrictions tab.
Create the following Object Restriction:

  • Object: PO
  • Type: READONLY
  • Reevaluate: true
  • Condition: POCOST


If you now logon with a user belonging to the chosen group and open the Purchase Orders application you will see that POs with a total cost of more than 1000 cannot be modified.

July 9, 2013

Best practices for Maximo projects

Today I have received the following questions from one of our customers.
  • Are there any best practices or recommendations on how to develop and maintain different versions of a Maximo based solution?
  • How can we do source control?
  • Are there any compare tool/utility to find differences in various version of application (available in different environments)?
Expanding a little, in this article I will present my own recipes to cook successful Maximo projects.


Development Methodology

I am a strong fan of Agile philosophy and less enthusiastic adopter of Agile software development methodologies like Scrum, XP or Crystal.
I really believe that the right way to seek success and perfection in software development project is to strive to align your processes, organization and culture to the four value statements of the Agile manifesto whatever methodology you are using.

Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration over contract negotiation
Responding to change over following a plan

There is no silver bullet here. Every project is different. Every customer is different. You have to experiment and improve keeping in mind those principles.
My own motto is: Start Small, Grow Fast. I always use this as a very simple guiding principle.





Workspace structure

I suggest to keep all the files and documents in a single place. There is no need to create boundaries between development, test or project management people. Everybody is on the same ship and a great collaboration is fundamental for an efficient and productive team. If possible, give access to the customer to entire set of files and documents. Foster mutual trust and establish a partnership.
This is a common set of directories in a project folder.
  • Mbo: Home of an Eclipse project for Mbo Java code (aka businessobjects).
  • Web: Home of an Eclipse project for UI Java code (aka maximouiweb).
  • Applications: Applications definitions exported in XML files. Any time a change is made, the app definition must be exported and stored here.
  • Scripts: TPAE 7.5 scripts.
  • Database: Custom database triggers and SQL scripts.
  • Docs: Requirements, plans and procedures as well as architectural and design documents. All the team members should use this folder to collaborate for a lean workgroup.
I know that some of these files are stored in a safe place in the Maximo database. However, I think it is better to keep together all the custom code in a common repository where you can also search for previous versions of a specific file.


Collaboration, Backup, Versioning

The workspace described above must be shared across all the team members including specialists, architects, developers, project managers and stakeholders.
Avoid using email to exchange documents. This could quickly become a nightmare. Break old habits. Share a list of tasks on Google Docs and ask everyone to keep it updated. Create a design document and edit it in real time during a review session. Many times we don't need strict rules and processes.

Regarding the technology for storage and versioning of the workspace it really depends on the size of the team. As a general rule:
  • 1-3 members: A shared folder with a weekly backup is enough. Cloud services like Google Drive, SkyDrive, DropBox, etc. are great and free. Google platform enable a powerful collaboration platform with chat, email, real time document collaboration and sharing.
  • 4-6 members : Here you will need some versioning system like CVS, SVN or Git. You may decide to setup your own server or to go cloud.
  • 7 or more: You need some requirement/bug management system. Those systems are typically called ALM (Application Lifecycle Management). IBM Rational Team Concert is a great and powerful tool but can be a little complex to administer. There are tons of ALM services on the cloud


Tools

First of all, share a common set of productivity tools. Look at Maximo specialist Swiss Army Knife for my selection of tools.
If you have to develop Java customization you have to set some coding standards.
In real world scenarios you will always face some challenges to keep in sync development, test and production environments. Unfortunately, there is no tool to compare two different Maximo environments. That's why I have develop my own method.
An effective technique is to periodically clone the production environment to the test and development environments with a procedure like this.
On the other side it is important to use Migration Manager to move packages to be released from dev to test to production.

July 7, 2013

Commodity Codes in Maximo

Commodity codes are standard classification codes for products and services used to detail where money is spent within a company.

In Maximo commodity codes are used to define similar types of items, tools, or services. Commodity codes are also grouped together in commodity groups. A commodity group contains a grouping of individual commodity codes.
Commodity groups and codes can be created and managed selecting the Add/Modify Commodity Codes action in the one of following applications: Companies, Item Master, Purchase Orders, Service Items, Tools. This IBM TechNote describes how to manually enter commodity codes.

Once you have defined commodities you can associate them with company, contract, and item records. You can also associate commodities with individual purchase order or requisition lines for items, service items, or tools that do not have commodity codes assigned to them, including special order materials or services.


Classifying items, tools, services with commodity groups and commodity codes provides a way to analyze and optimize spending by product type. To support such spending review process, Maximo provides the Commodity Analysis report in the Item Master application.


The Commodity Analysis report shows a summary list of items received during a given time period grouped by commodity groups and vendors. The first part of the report shows the received cost by commodity groups presented as a bar chart.



The second part of the report shows data in a table format. For each commodity group, the cost summary for each vendor is computed and shown as subtotal.


This report is useful in identifying what commodities made up the bulk of purchase costs and thus, are critical for cost controls. For large organizations it can be used to compare price points from different vendors in order to restructure and optimize expenditures across sites and divisions.


There are several standards for commodities classifications like UNSPSC, HS, NIGP. Many clients define their own classifications codes and groups in Maximo.
The UNSPSC (United Nations Standard Products and Services Code) standard is well known and is translated into many languages. Codes can be downloaded for free in PDF format or purchased in Excel format. Is it also possible to search and browse codes with a simple search engine.

It may be also interesting to hear something from you.
What is your preferred commodity codes structure in Maximo?
Do you use standard codes or have you defined you own structure?

July 5, 2013

How to import Failure Codes from Excel into Maximo

This article is outdated! Checkout MxLoader tool.

This entry is part of the Maximo Integration Framework series.

Creating and maintaining the hierarchy of failure codes can be quite complex using the standard Failure Codes application. Unfortunately there is no common solution to import Maximo failure codes. This evening I have worked on creating an Excel spreadsheet that can help in such cases.

This is an experimental tool. Use with care on development environments.
Leave a comment on this page both if you have problem (I'll try to fix them) and if you are able to use it successfully in your environment.


Data Model

Before going on, we need to understand how Maximo stores failure codes and their hierarchy of problems, causes and remedies.
The FAILURELIST table stores the hierarchy of problems, causes and remedies. The PARENT field holds the parent-child relationship while the FAILURECODE field points to another table called FAILURECODE that stores the descriptions of the failure codes in the various languages.
It is important to understand that a specific failure code can be attached to several places of the failure list hierarchy. This makes quite complex to manage this structure.


Export Failure List

A simple way of exporting failure codes and list is through SQL queries.

 
select orgid, failurecode, description, langcode from failurecode;


select f.orgid, f.failurelist classid, f.failurecode class, p.failurelist problemid, p.failurecode problem, c.failurelist causeid, c.failurecode cause, r.failurelist remedyid, r.failurecode remedy
from failurelist f
left outer join failurelist p on p.parent=f.failurelist and p.type='PROBLEM'
left outer join failurelist c on c.parent=p.failurelist and c.type='CAUSE'
left outer join failurelist r on r.parent=c.failurelist and r.type='REMEDY'
where f.parent is null
order by f.failurecode, p.failurecode, c.failurecode, r.failurecode;


Import

Create the following Object Structures.
Object Structure: FLL-FAILURECODE
  • Consumed By: Integration
  • Object: FAILURECODE
Object Structure: FLL-FAILURELIST
  • Consumed By: Integration
  • Object: FAILURELIST

Now download the FailureCodesLoader Excel spreadsheet and open it. Go on the Config sheet and set the correct hostname of your Maximo server. Clicking of the link the browser will open and should display the following message: Servlet is running. Please use HTTP POST to post data.
Now you are ready.

The Failure Codes and Failure List sheets allow to upload data into the two tables described before.
The Failure Codes sheet is straightforward to use. Just fill the worksheet with your failure codes descriptions and click on the little arrow on the toolbar.


This will execute a VBA macro that will call the FLL-FAILURECODE Object Service through an HTTP POST request.

The Failure List sheets represents the the failure codes hierarchy in a flat table with the same structure as exported by the above SQL query.
The Excel macro will handle the necessary logic to manage the failure list hierarchy. Once the objects are created and the hierarchy is populated, the macro will fill the 'ID' columns with the correct values. Once the ID values (greyed cells) are filled, the failure node is created in the hierarchy and shouldn't be changed.

At first it may seem a little tricky at the beginning, but after having played a little bit with the tool, it will be easy to create a complete failure list hierarchy of 1000 codes and more.