Posts Tagged ‘varargs’

Building Strings using Java MessageFormat

Monday, March 15th, 2010

Until I used SL4J, I didn't know that we can templatize String objects in a simple way. As most of us, use Log4J & apache commons logging framework for logging, we know general logging using these widely used open source frameworks. But there is more we can learn from these open source packages than just logging.

A simple debug in layman terms will be similar to writing System.out.println (String)

logger.debug("In "+location+", I said "+myMessage+" "+count+" times ");

to print "In Sunnyvale, I said Hello World! 7 times" in the log, if location="Sunnyvale", myMessage="Hello World!" and count=7

It is a simple debug statement which involves multiple String concatenation.

With SL4J, we can do the above debug like this

logger.debug("I said {} {} times ",myMessage, count);

which prints the same "I said Hello World! 7 times" in the log. Easy? huh!

After using it for a while, I thought this can be very well used for other string construction programs.

For eg, I need to make an API call to with various parameters which says userid=arun&location=sunnyvale&action=welcome

A common way of doing is :

StringBuilder sb = new StringBuilder();
sb.append("userid=").append(userid)
  .append("&location=").append(location)
  .append("&action=").append(action);

 doSomething(sb.toString());

SL4J's MessageFormatter

Using SL4J's MessageFormatter we can do

 doSomething(myFormat("userid={}&location={}&action={}", userid, location,action));

 private static String myFormat(String pattern, Object...argArray){
  return MessageFormatter.arrayFormat(pattern, argArray);
 }

I wish I can avoid my private method - myFormat, which automatically constructs array from varargs parameters.

Java MessageFormat

We already have MessageFormat from Sun(since JDK 1.4.2), which does exactly same & also supports varargs by default.

So we can do

 doSomething(
      MessageFormat.format("userid={0}&location={1}&action={2}", userid, location,action)
  );
 

There is a minor difference - we need to provide parameter number within {}, so it can pick the correct parameter to fill in flower braces. This is really useful for specific scenarios, which makes us not to worry about parameter order.

We can very well do,

 doSomething(MessageFormat.format("userid={2}&location={1}&action={0}", action,location,userid));
 

which constructs what I want.

MessageFormat is really powerful helper class for constructing String objects dynamically, without the overhead of String concatenation. It also keeps the code clean & concise. Typical use cases are internationalization (changing the text dynamically based on locale), General error message construction, String url Construction or anything in similar lines, where we know the countable set of variables to construct a string.