Friday, January 19, 2018

Risk Assessment Tool


I originally posted this at Interloc Solution's blog.

At my current client, we use a Change Request approach to Maximo changes.  A Change Request is created describing the new functionality desired.  Developers work on these changes in separate Subversion branches.  Change Requests are chosen for a Release, then merged together, tested, and deployed.  The merged changes are then merged back into our Trunk and the process repeats.  Change Requests are not necessarily deployed during the next Release.  It can be several Releases before a Change Request is deployed.

When it is decided to include a Change in a Release, a risk assessment is performed.  Two common questions are “What has this change touched,” and “Does it require regression testing.”  The intent is not to get into the details of the change, but to provide a rough overview that can help QA get an idea of the scope of the change.

We have recently introduced a Risk Assessment Tool modeled on the FAA’s Flight Risk Assessment Tool.  It is available on GitHub.  We are looking for a better acronym than MRAT or RAT when referring to this tool.  I welcome any input on the matter.

It is simply a list of development activities that are weighted depending on their potential impact.



Once development on a Change Request is complete, the developer creates a copy of the Risk Assessment Tool specific for their change.  The developer goes through and places a “1” in the Applicable column for anything that applies.  An overall score for the page is calculated automatically.

The development activities are then grouped together into more general types of changes and provides an overall score.

The end product is an overall summary of what has been changed (e.g. Screen, Database, Coding, etc.) and a score that gives an idea of the size of the change.  A bigger number means a bigger change means bigger risk and implies more testing.

The Considerations column contains notes to the developer to check common mistakes associated with a change.  For example, a consideration for adding a database column that is part of an Object Structure is that it has the potential of affecting external systems that consume that Object Structure.  The consideration column also contains notes to QA about what should be tested.  When an Mbo save method is modified, the Consideration is that testing should include saving a record.

The Score calculation is simply Weight × Applicable.  The common usage is to place a “1” in the Applicable column.  In the beginning we toyed around with the idea of using larger numbers to represent larger changes.  For example, if two Mbo classes were modified, then place a “2” in the Applicable column.  We felt this had the potential of overweighting changes.  We decided to go with ranges — 1 file, 2 to 5 files, etc — each with a different weight.

Where the FAA Flight Risk Assessment Tool gives meaning to the calculated scores — 0-10 Not Complex Flight, 11-20 Exercise Caution, 20-30 Area of Concern — we haven’t yet determined appropriate ranges and what those ranges might mean, so any outside thoughts or input would be welcome.
There are some obvious areas that are missing from this tool, such as Work Flow.  We don’t use it, so we don’t have a section for it. So any thoughts or input would be welcome here as well.

The Risk Assessment Tool is a simple approach that gives an overview of where changes took place and how much of an impact they might have.

Custom Start Center Portlets

I originally posted at Interloc Solution's blog.


Maximo's Start Center is populated with a number of different portlets.  They provide KPI data, Favorite links, the user's Inbox, among other things.  While it is possible to create custom portlets in Maximo, out of the box functionality does not permit saving them in a Start Center template.

Having looked into how Start Center templates are managed, I have created some extensions that permit saving custom portlets in a Start Center template.  Using these customizations "simplifies" custom portlet design to 10 easy steps.  They are:
  1. Modify the SCCONFIG service in Maximo with ISStartCenterService.
  2. Create an application for the portlet with READ and NOPORTLET signature options for it.
  3. Create a new service class that implements CustomPortletHandler.
  4. Create a data table to store portlet settings.
  5. Create a definition in the PORTLET table.
  6. Create a portlet data class for the jsp presentation file.
  7. Create a jsp file to display the portlet.
  8. Register the new portlet jsp.
  9. Create a DataBean for the configuration screen.
  10. Create a presentation screen for modifying portlet data.
What follows will be a breakdown of the steps listed above.  You can follow along with the MaximoIFramePortlet, a sample portlet that places an IFrame in the Maximo Start Centre.  The source is available on GitHub at https://github.com/ThatMaximoGuy/MaximoIFramePortlet.

Modify SCCONFIG

Refer to MaximoIFramePortlet/tools/maximo/en/isiframe/iframe_001.dbc

Modify the classname of the SCCONFIG service in Maximo to com.interlocsolutions.maximo.app.scconfig.ISStartCenterService.  The class can be found in the Interloc Solutions MaximoPortlet.jar.
The SCCONFIG service handles saving and loading Start Center templates.  An investigation of the base class shows that all the out of the box portlets are hard coded into the service without any extension points to handle custom portlets.  

The ISStartCenterService implements an extension mechanism to work with any number of custom portlets without any additional modifications to the service class.

The ISStartCenterService will identify any Maximo services that implement the CustomPortletHandler interface. When it loads or saves a Start Center template, it will identify any custom portlets and delegate loading and saving of the porlet data to the correct service. This permits creating many different custom portlets without any additional modifications to ISStartCenterService.

Create an Application for the Portlet

Refer to MaximoIFramePortlet/tools/maximo/en/isiframe/iframe_001.dbc

Create an application definition in MAXAPPS for the portlet.  It must have READ and NOPORTLET sigoptions.  The main table name for the new application will be the data table created later.  The data table will hold the user settings for the portlet.

In the MaximoIFramePortlet, an additional sigoption is created to limit the user’s ability to change the url assigned to the IFrame.

Create a New Service Class

Refer toMaximoIFramePortlet/src-mbo/com/interlocsolutions/maximo/app/iframe/ISIFrameService.java

Create a new service class that implements com.interlocsolutions.maximo.app.scconfig.CustomPortletHandler.  The CustomPortletHandler interface marks the service as able to save and load a custom portlet.  The methods the interface provides will do the work of saving and loading the portlet.

The methods xmlNodeName and portletName identify which portlet the service is responsible for managing.  The xmlNodeName is the name found in the Start Center Template XML.  The portletName is the name found in the SCCONFIG database table.

The loadPortlet method is called when the portlet is loaded from the SCTEMPLATE XML.  The method is called with a reference to the XML node from the Start Center Template that represents the definition for the portlet.  It also receives a reference to a class that is doing most of the work of loading the portlet.  If you have a layout with any child elements in the XML, the copyContentUId has to be called for each child element.  The last parameter is a reference to the LAYOUT Mbo that is the parent for any of the portlet data.
In the MaximoIFramePortlet, the loadPortlet is responsible for loading the URL and IFrame window size from the XML and populating it in a data table in the database.

The savePortlet method is called when the portlet is saved to the SCTEMPLATE XML.  It has the same parameters as loadPortlet, but the data travels from the database to XML.  It is responsible for creating the XML nodes that will be saved in the Start Center Template.
In the MaximoIFramePortlet, the savePortlet creates the XML node for the MaximoIFramePortlet and sets the URL and window sizes as attributes of the XML node.

Refer toMaximoIFramePortlet/tools/maximo/en/isiframe/iframe_001.dbc

Register this new class with Maximo.

Create a Data Table

Refer to MaximoIFramePortlet/tools/maximo/en/isiframe/iframe_001.dbc

Create a data table to store portlet settings. It must have a LAYOUTID field the same as LAYOUT.LAYOUTID. It must also have a relationship defined between LAYOUT and itself. 

Refer toMaximoIFramePortlet/src-mbo/com/interlocsolutions/maximo/app/iframe/ISIFrameCfgSet.java
MaximoIFramePortlet/src-mbo/com/interlocsolutions/maximo/app/iframe/ISIFrameCfg.java

Create and register an MboSet for the data table so that the layoutid of the data table is populated from the owner when a record is created.  If the Mbo extends from com.interlocsolutions.maximo.app.scconfig.AbstractPortletConfig, then it will handle that properly.

In MaximoIFramePortlet, the data table contains the URL to display in the IFrame and its height and width.

Create a Portlet Definition

Refer to MaximoIFramePortlet/tools/maximo/en/isiframe/iframe_001.dbc

Create a definition in the PORTLET table. The PORTLETID should match the value returned from CustomPortletHandler.portletName().  This will be displayed in the Available Portlets list in the Start Center Layout and Configuration screen.

In MaximoIFramePortlet, the portlet name is going to be called ISIFRAME and it will be a Wide portlet.

Create a Portlet Data Class

Refer to MaximoIFramePortlet/src-ui/com/interlocsolutions/maximo/webclient/iframe/IFramePortlet.java

Create a class that extends from psdi.webclient.controls.PortletDataInstance. This class will provide data access methods to the underlying data for the jsp presentation file.  Basically this class is responsible for taking the data from the Mbo and formatting it for the jsp file.  It should have a get method for each data column defined in the data table earlier.

In MaximoIFramePortlet, the IFramePortlet class defines methods to retrieve the URL, the IFrame height, and its width.

Create a JSP File

Refer to MaximoIFramePortlet/applications/maximo/maximouiweb/webmodule/webclient/components/isiframeportlet.jsp

The jsp file is what finally displays in the Start Center.  A lot of it is boiler plate.  It is most obvious where to add the custom code by referring to isiframeportlet.jsp.  Where that file has an iframe tag is where the HTML to display the portlet should go.  It’s simply standard HTML and JSP coding.  The filename should match the CONTROLNAME column from the PORTLET table definition.

In MaximoFramePortlet, there is an HTML iframe tag which takes its src, height, and width attributes from the Portlet Data Class.

Register the Portlet

Refer to MaximoIFramePortlet/src-tools/component-registry.fragment.xml
MaximoIFramePortlet/src-tools/components.fragment.xsd
MaximoIFramePortlet/src-tools/control-registry.fragment.xml
MaximoIFramePortlet/src-tools/presentation.fragment.xsd

For Maximo to know how to display the portlet, it needs to be registered as a component.  For that, entries in component-register.xml, components.xsd, control-registry.xml, and presentation.xsd must be created.

Start by copying the definitions from another portlet.  And make the following changes:
  • Component-registry.xml:
    1. Set the component-description name attribute to the control name of the portlet. This value will match the CONTROLNAME defined in the PORTLET table and the name of the jsp file without the extension.
    2. Set the default-value for the jsp-filename property to the name of the jsp file, without the extension.
  • Components.xsd:
    1. Set the xsd:element name attribute to match the CONTROLNAME defined in the PORTLET table. It has to match the component-description name used in the component-registry.xml.
    2. Set the default attribute of the jsp-filename property to the name of the jsp file, without extension.
  • Control-registry.xml:
    1. Set the control-descriptor name attribute to the control name of the portlet.
    2. Set the control-descriptor instance-class attribute to the fully qualified Java class name of the Portlet Data Class.
    3. Set the default-value for the relationship property to the relationship created to map from the LAYOUT table to the Data Table.
  • Presentation.xsd:
    1. Set the xsd:element name attribute to match the CONTROLNAME defined in the PORTLET table. It has to match the control-descriptor name used in the control-registry.xml.
    2. Set the default attribute of the relationship property to the relationship created to map from the LAYOUT table to the Data Table.
Refer to MaximoIFramePortlet/src-tools/com/interlocsolutions/maximo/tools/IFramePortletEnvSetup.java

MaximoIFramePortlet has a standalone application that will update the registry files.

Create a Portlet Configuration DataBean

Refer to /MaximoIFramePortlet/src-ui/com/interlocsolutions/maximo/webclient/iframe/IFramePortletBean.java

The Portlet Configuration DataBean will support the portlet configuration screen. The portlet configuration screen is the screen displayed when the “Edit Portlet” icon is clicked.  The bean has to ensure an Mbo exists to capture configuration data.

In MaximoIFramePortlet, the DataBean creates a new ISIFRAMECFG record if one doesn’t already exist.

Create a Presentation Screen

Refer to /MaximoIFramePortlet/tools/maximo/en/isiframe/isiframe.xml
The final step is to create a presentation for the portlet configuration screen.  This is done like other Maximo applications.  The beanclass for the application will be the Portlet Configuration DataBean created earlier.  The main object will be LAYOUT.  On the screen, create fields to capture all the configuration data required for the portlet. 

In MaximoIFramePortlet, there are three fields for the URL, width, and height.  The URL field is controlled the MODIFYURL sigoption.  This simply limits who can change the IFrame URL.

The Final Result

The final result is a custom Maximo Start Center Portlet.


Apache 2.4 and git

A while ago, I configured git on my server.  It seemed everything I found was on how to configure Apache 2.2 and git.  I couldn't find very much to configure it with Apache 2.4.

Here is the final configuration.  If I access using a web browser, I can navigate the repository.  If I access using git, then that works too.  Finally, it uses the system's users and passwords for authentication. 

Access is through: https://domain/git

SetEnv GIT_PROJECT_ROOT /var/lib/git
SetEnv GIT_HTTP_EXPORT_ALL

ScriptAliasMatch \
 "(?x)^/git/(.*/(HEAD | \
   info/refs | \
   objects/(info/[^/]+ | \
     [0-9a-f]{2}/[0-9a-f]{38} | \
     pack/pack-[0-9a-f]{40}\.(pack|idx)) | \
   git-(upload|receive)-pack))$" \
 /usr/libexec/git-core/git-http-backend/$1     
Alias /git /var/www/git


<LocationMatch "^/git/">
    SetEnvIfExpr "%{QUERY_STRING} =~ /git-receive-pack/" AUTHREQUIRED=yes
    SetEnvIf Request_URI "/git-receive-pack$" AUTHREQUIRED=yes

    AuthType Basic
    AuthName "Git Access"
    AuthBasicProvider external
    AuthExternal pwauth
    <RequireAny>
       <RequireAll>
          Require env AUTHREQUIRED
          require valid-user
       </RequireAll>
       <RequireAll>
          Require not env AUTHREQUIRED
          Require all granted
       </RequireAll>
    </RequireAny>
</LocationMatch>

<Directory /var/www/git>
  Options +ExecCGI
  AddHandler cgi-script .cgi
  DirectoryIndex gitweb.cgi
  SSLRequireSSL

  # Enable mod_rewrite 
  # RewriteEngine on 
  # Rewrite /git/repo.git URIs to be /git/gitweb.cgi/repo.git 
  # This assumes your repository names end with '.git'. I don't 
  # know if that is always a safe assumption. 
  # RewriteRule ^([^.]+\.git.*)$ /git/gitweb.cgi/$0 [L,PT]
</Directory>

Revisiting Querying Non-Persistent Fields

I've recently had a chance to use the method I developed to query non-persistent fields.  You can find the original article here.

It worked beautifully except it needed one small change in the DataBean's initialize method.

@Override
protected void initialize() throws MXException, RemoteException {    
    NPMboQbe.assignNewQbe(getMboSet(), new String[] { "CID_DEFECT" });    
    setQbe("CID_DEFECT", getQbe("CID_DEFECT"));
    super.initialize();
} 

This will cause the filter to be reapplied when the object is reloaded.

I have recently discovered that Maximo 7.6 ignores the filterable flag on non-persistent fields.  I'll have to spend some time to see what can be done.