Author Archives: Choon-Chern Lim

Spring Boot: Connecting to IBM MQ over JMS using non-IBM JRE

There are several ways to connect to IBM MQ:-

  • com.ibm.mq.MQQueueManager
  • com.ibm.mq.jms.MQQueueConnectionFactory
  • com.ibm.msg.client.jms.JmsConnectionFactory

This article shows you how to connect with Spring’s JmsTemplate.

CONNECTIVITY INFO

Typically, the MQ admin will provide the following connectivity info that allows you to connect to MQ:-

  • Queue manager name, ex: MY.QUEUE.MANAGER
  • Host name, ex: server.com
  • Port, ex: 1415
  • Channel name, ex: MY.SSL.CHANNEL
  • SSL Cipher Suite, ex: SSL_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • User, ex: user
  • Password, ex: password
  • Queue name, ex: MY.QUEUE

DEPENDENCY

Add the following dependency:-

dependencies {
  compile 'com.ibm.mq:mq-jms-spring-boot-starter:2.1.1'
}

SPRING CONFIGURATION

While the connectivity info can be hardcoded in Spring Boot’s application.properties, it’s probably more logical to use Spring @Configuration to dynamically set the values especially dealing with credential.

So, create a Spring configuration that looks something like this:-

// while all the value are hardcoded here for simplicity sake, you can inject
// sensitive values from DB, through <code>Environment</code>, etc.
@EnableJms
@Configuration
class JmsConfig {
  // Adding @Primary will force Spring Boot to use this bean
  // instead of the one provided by the dependency 
  @Primary
  @Bean
  MQConfigurationProperties mqConfigurationProperties() {
    System.setProperty('javax.net.ssl.keyStore', '/path/to/keystore.jks')
    System.setProperty('javax.net.ssl.keyStorePassword', 'XXXXXXX')

    return new MQConfigurationProperties(
      queueManager: 'MY.QUEUE.MANAGER',
      channel: 'MY.SSL.CHANNEL',
      connName: 'server.com(1415)',
      user: 'user',
      password: 'password',
      userAuthenticationMQCSP: true,
				
      // If the provided SSL cipher suite begins with "SSL", 
      // replace it with "TLS" instead.
      // SSL_* is IBM JRE CipherSuite name.
      // TLS_* is Oracle JRE CipherSuite name. 
      sslCipherSuite: 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256',
				
      // true - if using IBM JRE
      // false - if using non-IBM JRE, ex: Oracle, OpenJDK, etc
      useIBMCipherMappings: false
    )
  }
}

USING JMS TEMPLATE

Finally, to listen to the given queue, it is as easy as autowiring JmsTemplate and start using it.

@Autowired
JmsTemplate jmsTemplate

...

final Message message = jmsTemplate.receive('MY.QUEUE')
println message

React: Debugging Layout Thrashing

PROBLEM

When the React app grows larger over time, it is highly likely to run into situations where the component keeps re-rendering for no apparent reason.

There are many reasons why this is happening… to name a few…. parent component re-renders, this.props or this.state has changed, etc.

The key is to quickly find out what causes the component to re-render constantly.

SOLUTION

The simplest solution, in my opinion, is to paste the following block into the troublesome component:-

componentDidUpdate(prevProps, prevState) {
  const debug = (label, currObject = {}, prevObject = {}) => {
    Object.entries(currObject).forEach(([key, currValue]) => {
      if (prevObject[key] !== currValue) {
        console.log(`[DEBUG] ${label} has changed: `, key);
        console.log('[DEBUG] - BEFORE : ', prevObject[key]);
        console.log('[DEBUG] -  AFTER : ', currValue);
      }
    });
  };

  debug('Prop', this.props, prevProps);
  debug('State', this.state, prevState);
}

Adding this componentDidUpdate(..) lifecycle allows us to quickly find out which property or state has changed.

When running the app, the console may display something like this:-

Console Log

The key is to look for identical object or array displayed in both “BEFORE” and “AFTER” statements. This shows that while the values look similar, they fail on strict equality check (‘===’), which causes the component to re-render.

Groovy/Java: Handling Byte Order Marks When Reading a File

PROBLEM

Given a file with the following content:-

10,20

When reading the file:-

def inputStream = new FileInputStream('test.csv')
def value = inputStream.text.trim()

println "|${value}|"

… the following values are printed:-

| 10,20|

Even though the value is trimmed, there is still a leading space in front of text.

A further inspection reveals the leading space is not a regular space:-

// first character is not a space
assert value.charAt(0) != (char) ' '

// ASCII value: 65279 vs 32
assert (int) value.charAt(0) != (int) ((char) ' ').charValue()

SOLUTION

Some editors prepend a special Unicode character called a byte order mark (BOM) to the file.

The simplest way to remove this special character is to leverage Apache Commons IO’s BOMInputStream:-

def inputStream = new BOMInputStream(new FileInputStream('test.csv'))
def value = inputStream.text.trim()

println "|${value}|"

… and now, the values are printed correctly:-

|10,20|

Spring Web: Encode ‘+’ Value Using UriComponentsBuilder

PROBLEM

Given the following code…

final String url = UriComponentsBuilder.
        fromHttpUrl('https://server').
        queryParam('var', '{var}').
        buildAndExpand('1 2+3').
        encode().
        toString()

When using Spring Web 4.3.18.RELEASE, the URL is properly encoded:-

https://server?var=1%202%2B3

However, when using version between 5.0.0.RELEASE and 5.0.7.RELEASE, the URL containing “+” value does not get encoded:-

https://server?var=1%202+3

SOLUTION

There is a ticket opened regarding this breaking change.

To properly encode “+” value, use 5.0.8.RELEASE or later.

Then, ensure encode() is invoked before buildAndExpand(..):-

// Produces https://server?var=1%202%2B3
final String url = UriComponentsBuilder.
        fromHttpUrl('https://server').
        queryParam('var', '{var}').
        encode().
        buildAndExpand('1 2+3').
        toString()

The above code can be further shorten to this:-

// Produces https://server?var=1%202%2B3
final String url = UriComponentsBuilder.
        fromHttpUrl('https://server').
        queryParam('var', '{var}').
        build('1 2+3').
        toString()

 

 

macOS + Eclipse: The ‘X’ Executable Launcher was Unable to Locate its Companion Shared Library

PROBLEM

When attempting to launch Eclipse-based app (ex: MyApp.app) on Mac, the following error is thrown:-

The 'MyApp' executable launcher was unable to locate 
its companion shared library.

SOLUTION

This problem seems to occur on macOS Sierra and later.

When unzipping the app, the lingering extended attributes prevent the app from launching.

To fix this, run the following command to remove these extended attributes:-

xattr -c MyApp.app

Then, double click MyApp.app to launch it.

React + Recompose: Calling Multiple HOC Wrappers

PROBLEM

Sometimes, wrapping a React component with multiple High Order Components (HOC) can get rather unwieldy and unreadable.

For example:-

import React from 'react';
import { withRouter } from 'react-router-dom';
import { withStyles } from 'material-ui/styles';
import withWidth from 'material-ui/utils/withWidth';

class MyComponent extends React.PureComponent {
	// ...
}

export default withRouter(withStyles(styles)(withWidth()(MyComponent)));

SOLUTION

To fix this, we can leverage recompose library.

Now, we can rewrite the above example like this:-

import React from 'react';
import { withRouter } from 'react-router-dom';
import { withStyles } from 'material-ui/styles';
import withWidth from 'material-ui/utils/withWidth';
import compose from 'recompose/compose';

class MyComponent extends React.PureComponent {
	// ...
}

export default compose(
  withRouter,
  withStyles(styles),
  withWidth(),
)(MyComponent);

Keep in mind, the HOC order defined in compose(..) is important.

Webpack + ESLint: Automatically Fix ESLint Errors

PROBLEM

Given the following webpack.config.js

module.exports = {
  ...
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.js?$/,
        loader: 'eslint-loader',
        exclude: /node_modules/,
      },
	  ...
    ],
  },
  ...
};

When running any Webpack command, ESLint may find violations and halt the entire process with the following error message:-

/path/to/front-end-stack/src/js/components/home/Home.js
  43:11  error  Expected indentation of 6 space characters but found 10  react/jsx-indent
  44:14  error  Expected indentation of 6 space characters but found 13  react/jsx-indent

x 2 problems (2 errors, 0 warnings)
  2 errors, 0 warnings potentially fixable with the `--fix` option.

SOLUTION

Certain errors (ex: trailing commas, wrong indentation, extra semicolon) are easily fixable.

There’s no need to halt the process and wait for developers to fix these obvious errors.

To configure ESLint to automatically fix these “soft” errors, add the following options block to the above rule:-

module.exports = {
  ...
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.js?$/,
        loader: 'eslint-loader',
        exclude: /node_modules/,
        options: {
          fix: true,
        },		
      },
	  ...
    ],
  },
  ...
};

If you are using any VCS, remember to commit any file changes.