Monday, November 15, 2021

Specifying the MQ username for connecting to a remote queue

Long before your time, there was a WebSphere 7 function, for using JMS to talk to Message Queues. The connectivity made use of (we believe) a default "mqm" username for accessing messages. Both the application server and codes have no awareness of such an arrangement. Nobody had any idea about this, until we were forced to dig deep into this discrepancy.

Then along came WebSphere 9, which turns out was slightly more advanced. The default is no longer used. Instead, it uses the service account that the application server was running on. This introduced some problems. The same identity needs to exist on the remote queue server that the WAS9 is connecting to. 

For most people, this might have easily concluded by having the same account be created on the other side. Naturally, this was not what is happening to warrant this post. In light of some revelations, a username that is different from the one already running the WAS9 was to be used.

I found out that it was risky to try setting the clientID, with due consideration for resource contention in a clustered environment. We tried poking around the J2C authentication alias, but it seemed to require a lot more configuration. The other option, was the username, as suggested by IBM documentation.

In order to set the value in, I located this UserCredentialsConnectionFactoryAdapter for Spring. As suggested here as well, 

For example, when using Basic client authentication, the username and password set for the Initial Context and used for the JNDI connection are inherited from the JMS data connection. However, these properties can be overridden by a username and password provided in the Connection Factory.

 I'd followed the example approximately:

 <bean id="myTargetConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
   <property name="jndiName" value="java:comp/env/jms/mycf"/>
 </bean>

 <bean id="myConnectionFactory" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
   <property name="targetConnectionFactory" ref="myTargetConnectionFactory"/>
   <property name="username" value="myusername"/>
   <property name="password" value="mypassword"/>
 </bean>

We fiddled a bit with it and took it for a spin. It seemed to take, so we were quite relieved that we didn't have to spend another 2 weeks rewriting a bunch of codes for a fix. At this point, we can confirm that the JMSXUserID remains as "mqm", according to our debug logs.

This had been a very obscure lesson, with nary an article that detailed what needed to be done. Our work is yet to done (will it ever?) but this was quite the wild ride that my colleagues and I took.

Thursday, September 30, 2021

Configuring JVM for Tomcat Service Manager

It's been slightly more than a year since my last post, but my team had recently ventured into preparing our own deployment script. At the behest of an eager member, we'd built up a PowerShell script using PowerShell App Deployment Toolkit, also known as "PSAppDeployToolkit", or even shorter as PSADT. This was a script meant to automate installation of a number of programs on the target Windows machines, silently and automatically. 

With the background of what we were doing established, this was about one specific setup we wanted to configure. One of the platforms we were using, was Tomcat 9. Fine, it was TomEE 9, using Tomcat 9, but you get the idea. Tomcat was to be installed as a service by the having our script chained to trigger the standard "service.install.as.admin.bat" script. 

Then we realised that the JVM would default to "auto", which means using whichever JRE it can find. We prefer to stick to our version for consistency. The easiest was for us to edit the provided batch script. After finding this page of documentation, I started poking around the script more. We need the --Jvm="/path/to/the/jvm.dll" option added in. 

The standard configuration out of the box is this:

"%EXECUTABLE%" //IS//%SERVICE_NAME% ^
--DisplayName=%SERVICE_NAME% ^
--StartClass org.apache.catalina.startup.Bootstrap ^
--StopClass org.apache.catalina.startup.Bootstrap ^
--StartParams start ^
--StopParams stop ^
--Startup auto ^
--JvmMs=512 ^
--JvmMx=1024 ^
--JvmSs=2048 ^
--StartMode jvm ^
--StopMode jvm ^
--LogLevel Info ^
--LogPrefix TomEE

So I just need to add it in, right? I tested.

"%EXECUTABLE%" //IS//%SERVICE_NAME% ^
--DisplayName=%SERVICE_NAME% ^
--StartClass org.apache.catalina.startup.Bootstrap ^
--StopClass org.apache.catalina.startup.Bootstrap ^
--StartParams start ^
--StopParams stop ^
--Startup auto ^
--Jvm=%PR_JVM% ^
--JvmMs=512 ^
--JvmMx=1024 ^
--JvmSs=2048 ^
--StartMode jvm ^
--StopMode jvm ^
--LogLevel Info ^
--LogPrefix TomEE

It seemed fine on the surface. And after more elaborate tests, I realised that doing so would break the Tomcat Service Manager. The memory values (JvmMs/JvmMx/JvmSs) would not take. Neither did the StartMode and StopMode parameters. I couldn't be certain if it was because of how the PSADT script worked. I'd only extracted the portion of our whole script for Tomcat to test on after all. After some more fumbling, I thought I could try adding it to the end, and gave it a shot. The command wouldn't recognise it past the LogPrefix parameter at that point. It was then that I decided to move it up 2 lines.

"%EXECUTABLE%" //IS//%SERVICE_NAME% ^
--DisplayName=%SERVICE_NAME% ^
--StartClass org.apache.catalina.startup.Bootstrap ^
--StopClass org.apache.catalina.startup.Bootstrap ^
--StartParams start ^
--StopParams stop ^
--Startup auto ^
--JvmMs=512 ^
--JvmMx=1024 ^
--JvmSs=2048 ^
--StartMode jvm ^
--StopMode jvm ^
--Jvm=%PR_JVM% ^
--LogLevel Info ^
--LogPrefix TomEE

Ha! It finally worked. The JVM was no longer "auto", the memory values took effect, and the start/stop modes were in as well. There was very little details surrounding this specific configuration, much less documentation relating to this particular quirk of positioning the option correctly.

Thursday, September 3, 2020

My minimum standards for coding in Java

People have a tendency to overlook certain issues, and may require gentle reminders every so often, to nudge them in the right direction. I'd imagine a simplified list would help with rehearsing the drill. This happens everywhere, including at work with my team, with regards to Java coding for webapp development. Here's what I've come up with succinctly abbreviated as "SCROLL":
  • Switches
  • Comments
  • Reusability
  • OWASP
  • LogLevels

Switches

Implement soft toggles that allow the running application to toggle features without server restarts. This is particularly useful for rolling out enhancements prior to the actual go-live date.

One way is to store such values in the database via system variables or code tables. The "enhanced" code should then check the switch each time it is called. Of course, not all situations can adopt this method, but I'd think that doing this as much as possible will be of great help.

Comments

Elaborate explanations in the codes will help others understand your thought processes in future. I find it equally helpful for when I revisit very old codes that was written by yours truly. The explanations for changes in workflows will be useful for troubleshooting several years down the road. 

A recommended format would be //name, date, description for single-liners. The next person could potentially approach the person who built it, and be able to discern a timeline of which set of codes came after which.

An added bonus would be if the comments were following conventional Java /** **/ format such that it can show up properly in generated javadocs.

Reusability

Optimised codes can be refactored into methods that can be write-once-run-anywhere (at the code level). This includes system variables and constants. Also part of this category are Util classes that serve a common, generic purpose.

OWASP

Security should never be an afterthought, where the OWASP still is the recommended set of guidelines that web developers should work with. Proper validations should be ensured (even for basic "!= null" checks) which will aid in the long run in case of code scans and security tests.

LogLevels

Logging is important, but so is the correct use of loglevels. Only use INFO level for production environments, while aiming to only output a single line containing all the useful information without generating extraneous logs. A sub-point would be to avoid logging sensitive data, and sanitising the output if it's necessary.


The above are meant for highlighting specific areas to focus on, in the name of brevity. Do you have any others you'd consider adding/replacing to the list?