Observing class loading preparation phase

During javac compilation, Java class is translated into a sequence of instructions and corresponding metadata. This intermediate representations allows JVM to dynamically extend the runtime environment with custom classes and execute code created in different languages (e.g. Scala or groovy). A *.class file can be considered as a key-value pair which has a specific name and corresponding binary representation.
To be able to execute any code, JVM needs to find that representation and read it, which is called loading.
Loaded class is not usable at that point, because it may be invalid or it may refer to external types. Putting the loaded class in the runtime context is called linking.
The next step is to initialize static variables for the class and run static initialization code blocks.

The whole process is described in details in chapter 5 of Java Language Specifiaction. The topic is covered eagerly in countless articles and books. It seems, however, that one of the subphases of the linking phase does not get as much coverage as the others.

During the linking phase there are different activities performed by the JVM. Due to security reasons the first subphase in responsible for extensive bytecode verification. Preparation consists of static field creation in initialization of their default values (for example: 0 for int, false for boolean, etc.). Constraints are imposed on the overridden methods return types as well. Finally, all types referenced by the class being linked are resolved.

The subphase responsible for initializing static fields to its default value is often forgotten. While imposing type constraints on methods seems like dark arts from high-level code perspective, the step when the defaults are set is tangible and can be observed.
The following sample is by no means a good coding practice since it might introduce unexpected behavior. The class presented below holds an instance of itself as a static member. It has additional static field and a non-static field as well. Non-static field refers to the static one, which at that point is initialized to its default value, zero. Changing the order of static fields would eliminate the error.

public class UnexpectedValue {
    static final UnexpectedValue instance = new UnexpectedValue();

    static int DEFAULT_VALUE = 123;

    int member;

    public UnexpectedValue() {
        this.member = DEFAULT_VALUE * 10;
    }
}

While we’re tempted to think that the valueOfMember should be set to 1230, it actually holds 0, because of unexpected value from DEFAULT_VALUE.

@Test
public void shouldResolveToDefaultIntValue() throws Exception {
    int valueOfMember = UnexpectedValue.instance.member;

    assertThat(valueOfMember, is(equalTo(defaultIntValue())));
}

int defaultIntValue() {
    return 0;
}

Testing JMS bridge to IBM MQ with Spring Boot

Not invented here syndrome gained recognition in software development, because it’s relatively common phenomenon. It has its roots in psychology, where it was identified as knowledge communication problems of decision makers (Martin, E. (2007). Knowledge Communication Problems between Experts and Decision Makers: an Overview and Classification. Electronic Journal of Knowledge Management, 5(3), pp.291-300.). Specific technical choices of other people comprise an easy target for complaints, especially when artifacts that were picked are not state-of-the-art anymore.
The fact that architectural decisions were made elsewhere is a lousy excuse for writing low-quality code. Bare in mind that low-quality comes in different shapes and sizes. One of them is related to tests. Writing poor tests or no tests at all is a repugnant practice. But it’s tempting to blame proprietary middleware messaging system for missing integration tests – setting up additional broker is costly, mundane, cumbersome, etc. A simple solution can be to rely on standardized API for communication and then replace target system with the one you have control over.
Nelson Elhage recently described how he writes tests. In his post he encourages to write lots of fakes, meaning to mock complex things that are not crucial to current testing subject. As an example he provides an idea of in-memory mock for Amazon S3 storage. The same concept can be applied to messaging middleware.
Apache Kafka has an embedded version of broker included in test module out of the box. You can set up your tests to communicate with full-blown Kafka broker which happens to reside in memory. No such facility exists for IBM Websphere MQ, however equipped with JMS interfaces one can take advantage of a system that is a bit more flexible.
In one of my previous posts I shortly described, how to get started with IBM MQ with Spring Boot and JMS. Having all classes designed for testability greatly reduces the effort needed to wire up a working example. Some hints on testing IBM Websphere MQ with Spring Boot were put together previously, however using HornetQ with Spring Boot became deprecated. The current post can be treated as an update.
Configuration is divided into two classes. One is tightly coupled with IBM Websphere MQ and defines a connection factory. The other configuration class defines a number of messaging components that depend on aforementioned factory.
There’s no need for running IBM MQ instance in tests. An in-memory queuing solution can be used, for example Apache ActiveMQ Artemis in embedded mode. Spring Boot provides a starting point for Artemis as starter dependency, which allows automatic detection of dependencies in classpath, important components instantiation and handful of autowiring capabilities. Excellent for testing purposes with low plumbing overhead.
To get started with Artemis the following dependencies have to declared.

dependencies {
	// ...
	testCompile 'org.springframework.boot:spring-boot-starter-artemis'
	testCompile 'org.apache.activemq:artemis-jms-server:1.3.0'
	testCompile 'org.springframework.boot:spring-boot-starter-test'
	testCompile 'org.awaitility:awaitility:2.0.0'
}

As a next step the code must somehow indicate that Artemis is supposed to run in embedded mode. To achieve the goal, an entry in application.properties must be added.

spring.artemis.mode=embedded
# ...

When it comes to configuration classes, only non-IBM-related one can be picked. It will rely on Spring Boot to provide default connection factory to an in-memory queue. We can even extend the configuration class and replace specific beans with the implementation that fits tests better.

@Configuration
static class TestConfiguration extends MQConfiguration {
    List<String> receivedMessages = new CopyOnWriteArrayList<>();

    @Override
    @Bean
    public Consumer<String> messageConsumer() {
        return receivedMessages::add;
    }

    public boolean hasReceivedMessages() {
        return !receivedMessages.isEmpty();
    }

}

SpringBootTest annotation allows limiting set of classes which contains beans definition, so that a single test class populates Spring context only with significant components. It makes tests faster and less error-prone.

@RunWith(SpringRunner.class)
@SpringBootTest(classes = { MQGatewayIntegrationTest.TestConfiguration.class, MQGateway.class, MQProperties.class })
@EnableAutoConfiguration
@EnableJms
public class MQGatewayIntegrationTest {
    @Inject
    JmsTemplate jmsTemplate;

    @Inject
    TestConfiguration configuration;

    @Value("${pl.ciruk.blog.mq.incoming-queue}")
    String queue;

    @Test
	public void shouldReceiveMessageInListener() throws Exception {
        String message = "This is a test message";

        jmsTemplate.convertAndSend(queue, message);
        await().atMost(5, TimeUnit.SECONDS)
                .until(configuration::hasReceivedMessages);

        assertThat(configuration.receivedMessages, contains(message));
    }

    // ...
}

Complete code can be found on Github.