Friday, January 28, 2022

Carving the Rosetta into an ink stone

Turning what was into what will be

If technology ages like people, then according to this, the system we worked on was old enough in human years to vote. The enterprise web application had served the team of users for a good many years, with a long-deserved refresh. Care and time was taken to assess the changes needed. This was all the more important given that there was practically zero code freeze period available, as the old system had to roll out new changes very close to the go-live of the new version. Things tend to be hectic when similar tasks have to run in parallel. Here were some of the key considerations that we had planning everything out. 

Replacing an important desktop feature

One of the major technology that had to be benched, were the Java applets. The industry had gradually shifted away from its use over the years, but it remained typical of intranet applications to continue in its use due to a variety of factors. 

In order to throw applets out the door, one substitute was the use of local services. Many consumer product manufacturers had been providing these desktop software already. These were small programs sitting in the system tray, that are responsible for minute tasks on the client operating system. 

An application running from a web browser can only do so much, when interacting with the user desktop. Installing such a software caters for flexibility that typical web apps cannot afford, like initiating the printer spool to the hardware device without launching a separate window. We had an two implementations, using REST-based asynchronous calls for basic functionality, and more tightly coupled integrations that required WebSockets for payment terminal communications. Separating the modules this way helps delineate separation of tasks. 

Certain pitfalls we encountered, were surrounding the XSS and CSRF protections. We had to factor in the SSL certificate as part of the package as well, ultimately culminating in an installer which was able to bundle a JRE of our choice. 

API-ing the monolith

Ye olde web app was built as a monolith. Like a good coming-of-age story, this concept also required a paradigm shift. Due to the many limitations, it was impossible for the upgrade to be completely rewired into microservices. It was also impractical for this application to be totally disassembled for our many use cases. I decided we should take the middle ground, and went with a hybrid approach; it was not quite a monolith, but not yet a microservice architecture. 

An authentication service was first built from the ground up. This was a module that could run on its own, within our traditional application server environment. By ensuring that it was mostly self-contained, there is an element of future-proofing by requiring APIs to be accessed via REST-based calls. I use "REST-based", because our environment discourages fully RESTful APIs due to security concerns. This was as close to a zero-trust API flow as I could build in our case. The use case for this service was mainly for M2M (machine-to-machine) communications. Products offering OAuth solutions in the wild typically expect three-point flows, meaning that it was not immediately available for an off-the-shelf framework that provides the M2M flow which I was looking for. 

Following this construction pattern, we'd also built another module for exposing APIs to external interfaces. More of the lean REST-based request/response pairs are applied here, to avoid encumbering the consumer with legacy fields. This API service was a companion to the authentication service, as the caller is forced to provide a token with each query. A token which can only be requested from the authentication service. This API service will then make an internal API call to the authentication service for validating the provided token. 

Speaking of internal APIs, we had further expanded on that in the existing monolith. There were further offsite modules that had data transmission requirements with the central application. Applets were used to address this, but without it, the gap had to be fulfilled by the more readily usable REST-based options instead. Endpoints were added to replace what used to be Java RMI objects. 

Modernising the team processes

The suite of development tools used to be CVS with Mantis. The new direction was with Gitlab and Jira. Getting the team onboard certainly took getting used to. The development workflow had to be adjusted as we got used to the different behaviour of Git, where the source code was committed locally first, and had to be "pushed" to the remote repository subsequently. 

The old issues in Mantis were boxed and shelved entirely, as we embraced a new leaf with Jira. Certain flexibilities we were used to in Mantis were no longer available with Jira. The team had to be regularly reminded to ensure that issue status and resolutions were kept updated. The web based interface definitely helped in maintaining oversight of the outstanding issues, with priorities and progress.

Code review remained manual. This was a necessary evil, due to the immense code base, containing a multitude of legacy codes, intermingled with business logic and potentially outdated or deprecated codes. It was pertinent that all new changes were annotated clearly with start/end comment blocks. The best practices I had for software development had to be reinforced and reminded regularly to the team.

The eventual go-live of the new system was no mean feat. Part of the effort was shaved considerably and efficiently. A colleague had taken up the heavy task of preparing a installer for the event. Packaging an installer helped to streamline the deployment process, as we had various software that had to be installed into more than 100 workstations on the network. It didn't help that the desktop engineers were operated by a different vendor. We were able to take advantage of the PowerShell script, further enabled by the PSADT framework. The ten plus different installers we needed to run, could then be consolidated into this single installation. It was not perfect, and still as yet can be improved further. But it is another step in the direction to be taken.

Getting here

Happy new year! Each step that was taken, had its own story. As we build into the future, we should always keep sight of what is on the horizon. In spite of the limitations of our time, certain concessions can be made to ensure that progress in made in the correct direction. Baby steps are better than no progress at all. 

A shout out and major thanks to the team that I'd worked with. Our work is just getting started on the new version of the system, but kudos to everybody for getting this far!