A collection of thoughts, ideas and rants inspired by my career in the fintech and banking industry.

Converting from JUnit to TestNG

The TestNG Eclipse plugin has a feature that will convert your unit tests from JUnit to TestNG in a few simple clicks, and it works pretty well for the most part. However, I soon noticed that it was replacing Assert.assertX with AssertJUnit.assertX. Upon further inspection, this was because TestNG’s Assert uses different argument ordering. For example

// JUnit  
Assert.assertEquals(message, expected, actual);

// TestNG  
Assert.assertEquals(actual, expected, message);  

Each argument has moved.

[Read More]

Using Factory Beans in Spring Java Configs

I recently went through an exercise of converting Spring XML configuration files to Java-based configuration. The process went well for the most part, but I encountered an oddity around how to use factory beans when using Java configs.

In XML, factory beans would be used like this

<bean id="MyDataSource"  
class="org.springframework.jndi.JndiObjectFactoryBean"  
p:jndiName="jdbc/MyDataSource"  
p:resourceRef="false"  
/>  

In Java however, this has to be separated into two separate @Beans

@Bean  
public JndiObjectFactoryBean getJndiObjectFactoryBean() {  
	JndiObjectFactoryBean jndi = new JndiObjectFactoryBean();  
	jndi.setJndiName("jdbc/MyDataSource");  
	jndi.setResourceRef(false);  
	return jndi;  
}

@Bean  
public DataSource getSampleDataSource() {  
	return (DataSource) getJndiObjectFactoryBean().getObject();  
}  
Java  Spring 

Atomic construction

Bugs caused by multi-threading can be very difficult to find. Here’s one I encountered recently.

private static MyObject INSTANCE;

public void init() {  
	if( INSTANCE == null) {  
		initInstance();  
	}  
}

private static synchronized void initInstance() {  
	if( INSTANCE != null) {  
		return;  
	}  
	INSTANCE = new MyObject();  
	INSTANCE.initThis();  
	INSTANCE.initThat();  
}  

At first glance, this code is fine. It uses a synchronized static method to create the singleton, using double-checked locking to make sure it only gets created once. But on closer inspection it is possible for the null check in init() to pass before the INSTANCE has been fully initialized.

[Read More]

On vlogs

Video blogs, or vlogs, are becoming increasingly popular and if you have a decent following on Twitter/Facebook/etc then you probably also have a YouTube channel from which to pontificate.

Vlogs are great. I get to know you a little better because I can hear your accent, the tone of your voice, and see all the non-verbal facial expressions that add so much to any communication.

But there are several downsides, too.

[Read More]

Moving on

Today is my last day at CIBC and that makes me sad. It’s been an honour and a privilege to work with Mike Salvagna and his fantastic development team for the last 18 months. Mike has assembled one of the best development teams in Toronto that, in his words, “can build anything”. I believe he’s right.

Tomorrow I start at Intelliware where I’ll be leading another FX project. I’m looking forward to the challenges that this new position will bring, but I can’t help feeling down about leaving behind such a great team at CIBC.

[Read More]

Writing deterministic tests

Non-deterministic unit tests are like kryptonite for an automated build. They cause intermittent build failures and the development team becomes accustomed to ignoring a failing build. This is a Bad Thing.

Thread.sleep(x) in a unit test is a recipe for non-deterministic behaviour. Think about what happens when this test is run on a slow machine. How big does X need to be?

I often see this anti-pattern in multi-threaded code where the test case is waiting for some asynchronous task to complete, and the test case has to guess at how long the task will take, and then asserts on some condition that the task was supposed to change.

[Read More]

List.clear() throws UnsupportedOperationException

Consider the following code

String[] s = new String[]{""};  
List<String> list = Arrays.asList(s);  
list.clear();  

All looks good, right? When you run it you get:

java.lang.UnsupportedOperationException  
	at java.util.AbstractList.remove(AbstractList.java:144)  
	at java.util.AbstractList$Itr.remove(AbstractList.java:360)  
	at java.util.AbstractList.removeRange(AbstractList.java:559)  
	at java.util.AbstractList.clear(AbstractList.java:217)  

This is because Arrays.asList(array) returns a fixed-size list backed by the specified array. Fixed-size being the operative word.

Java 

Arrays.asList() gives a list with wrong size

Try this out for fun.

int[] i = new int[]{1, 2, 3};  
System.out.println(Arrays.asList(i).size());

Integer[] ii = new Integer[]{1, 2, 3};  
System.out.println(Arrays.asList(ii).size());  

Output:
1
3

What the hell, Java? This is totally unexpected behaviour!

In this case Java is being a bit pedantic. See, Collections can contain only contain Objects, and an int is not an Object but int[] is an Object, so that’s why you get a list with only 1 element.

[Read More]
Java 

How to set JMSXUserID in Websphere MQ using Spring JMS

Every time I work with MQ and Spring JMS I want to poke my eyes out with a dull instrument. It’s always a pain in the neck. My most recent challenge was trying to get the JMSXUserID field to flow through to the application on the other side of MQ.

First, I created a MessagePostProcessor to add the JMS header

public class MyMessagePostProcessor implements MessagePostProcessor  
{  
	private String userId;

	@Override  
	public Message postProcessMessage(Message msg) throws JMSException  
	{  
		msg.setStringProperty(JmsConstants.JMS_IBM_MQMD_USERIDENTIFIER, userId);  
		msg.setStringProperty("JMSXUserID", userId);  
		return msg;  
	}  
}  

But when I checked the queue with HermesJMS I could see that the JMSXUserID had been overwritten somewhere, so I fired up WireShark and watched for the message and confirmed that the message that was going over the wire already had the JMSXUserID field overwritten. This was a good thing - the issue was in the IBM MQ JMS client code.

[Read More]

Big Data and HR

This piece from the New York Times touches on a subject that I’m passionate about - the challenges of hiring good people. Deep into it, it mentions that:

“…the most proven method, Dr. Lewin said, is a referral from someone already working there. Current employees know the culture, he said, and have their reputations and their work environment on the line.”

The big data thing is a cool, tech solution, but really it’s referrals that matter.

[Read More]