Implement "Sleep" or "Wait" in WebMethods flow

I needed to send an external system a file import request. The external system would take some time to process the file before the import result can be queried. Making a status query immediately after the import request would always return an "import process is still running". It's best to wait for a few seconds before making the first attempt to query the import status.

It took quite a bit of time to look up the web for a "wait" or "sleep" function. Some posts suggested using Java flow, some recommended complex processes or involved an external library.

The easiest method I finally settled with is to use Repeat as follows:

Essentially, the flow would repeat 1 time in 5 seconds before getting to the next step (Main Mapping). The repeat loop does nothing other than just writing a line in the server log to make troubleshooting a bit easier.

The fun (and pain) of Kronos Integration

One of our clients undertook a massive IT transformation program which involved switching to a new financial management system, upgrading and rebuilding a plethora of interfaces among several systems, both internal and external to the business. Kronos was chosen to replace an old timesheet software and there was the need to integrate it with other systems such as Maximo and TechnologyOne. WebMethods was used as the integration tool for this IT ecosystem. This is my first experience with Kronos. The project took almost two years to finish. As always, when dealing with something new, I had quite a bit of fun (and pain) during this project. As it is approaching the final stage now, I think I should write down what I’ve learnt. Hopefully, it will be useful for people out there who’re doing a similar task.

REST API: Kronos provides a pretty good reference source for the REST API at this Link. REST API theoretically offers the advantage of supporting real-time integration and enables seamless workflow. However, we don’t have such a requirement in this project. On the other hand, this has two major limitations.

WebMethods: Evaluate String IN and CONTAINS operator

In WebMethods, the most basic way to write a string “IN” operator is to use Branch as follows:

Another way to reduce the number of lines of code is by combining the conditions using “OR”:

Troubleshoot integration issues when Maximo stops publishing data to external system.

I had to deal with this quite often. Most of the times, I got it right and able to identify the problem quickly. In a few cases, it took some time, and usually very stressful as it mostly occurs in Production. (It occurs in DEV and PRE-PROD all the time, it’s just that people usually don’t care, and it goes unnoticed)

Today I had to deal with it again and it took me some time. The cause was something I dealt with before, was told by a colleague on how to fix it (the easy way), but I forgot. This time around, under panic mode, I restarted a few JVMs before I remembered I should ask around and was reminded by my colleague again that it could be fixed with much less damage. I told myself I should write it down for the next time, so here is the sum of what I learned:

Setting up alarms for integration

 When writing a piece of software, we are in total control of the quality of the product. With integration, many elements are not under our control. Network and firewall are usually managed by IT. With external systems, we usually don’t know how they work, or many times, not given access. Yet, any changes to these elements can cause our interfaces to fail.

For synchronous interfaces, the user would receive instant feedback after each action is taken (e.g. Maximo - GIS integration), thus, we don’t usually need to setup alarms. For asynchronous interfaces, which usually run in the background, and don’t give instant feedback, when failure occurs, it usually goes unnoticed. In many cases, we only find out about failures after it has caused some major damage.

A good interface must provide adequate mechanism to handle failures, and in the case of async integration, proper alarms and reports should be setup so that failures are captured and handled proactively by IT and application administrators.

Avoiding recursion filter on Publish Channel

The standard way to send a message from Maximo to an external system is by setting up a Publish Channel and enabling Event Listener. By default, Integration Framework doesn’t re-publish a change if it comes from another inbound interface to prevent recursion on a bi-directional interface. Although I don’t agree with this logic as one-way integration is much more common, but anyway, IBM said it is easy to override that by extending the Event Filter javaclass.

The problem is, with the rise of automation script, no one wants java customization anymore. Of course, for massive systems where performance is critical, it is still the best choice. But, for most medium-sized clients I work with, they’re all moving away from java customization.

Anyway, an approach we can deal with this is not to use Event Listener at all. Instead, we can trigger a publish from an Object Save launch point from automation script using the example python code below:

from psdi.iface.mic import PublishChannelCache
PublishChannelCache.getInstance().getPublishChannel("PUBLISH_CHANNEL_NAME>").publish(mbo, True)

 Happy coding!

Check Network/Firewall Status using PowerShell

Working with Maximo, we have to deal with network/firewall all the time. I can spend a whole day telling you fun stories (or extremely frustrating experience) I had with IT/Network guys. But that's not the point. If you end up here, I guess you're having an issue with firewall. So below is a quick recap of my tricks:

- Ping: the first thing we try when we want to see if a server is accessible from our current machine. But don't jump to a conclusion too early if it shows the server is unreachable. Sometimes, the Network Admin has disabled ping response to enhance security. 

- Telnet: to check if a port is opened, we can use telnet from Windows Command console (e.g. telnet 80). If it can be connected, means the target server is accessible on the specified port. But if it doesn't, first, make sure the server is listening on that port, before jumping to a conclusion that it's a Firewall issue. I made this mistake a few times, blaming the network, then it turned out it's Websphere/Maximo service is not running on the port that I assumed it should be running on

- PowerShell: in many cases, the server is not connected to the Internet, and Telnet is not installed, (and yes, you don't have permission to install new software either). We can use PowerShell to check network connectivity using the two commands below:

$connection = New-Object System.Net.Sockets.TcpClient("", 80)
Write-Host $connection.Connected

The first line will return some errors if it cannot connect to the server, like the screenshot below: 

 If the server is accessible via the provided IP and port, the 2nd line will return the status = Connected