Tuesday, October 2, 2012

Logging Configuration for Testing

I realized this morning that putting the name of the test in the logging frameworks (log4j/slf4j) Mapped Diagnostic Context (MDC) gives great context to every logging statement. I'm not sure why I didn't do this before. Well, I've always had a different log4j (and now slf4j) configuration file sitting in src/test/java to change the level of local classes while executing tests. This configuration almost always goes to the console where the main code will log to a file.
This example uses log4j but slf4j has the same MDC class.
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  <appender class="org.apache.log4j.ConsoleAppender" name="console">
    <param name="Target" value="System.out" />
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d{ISO8601} %X{testMethod} %-5p %c - %m%n" />;
    </layout>
  </appender>
  <root>
    <priority value="debug" />
    <appender ref="console" />
  </root>
</log4j:configuration>
Then, in Java, you'll need a custom TestWatchman that uses the same string 'testmethod' as seen above inside the french braces %X{testMethod}):
/**
 * This helpfull little thing works in concert with the log4j configuration.
 * There are two steps to it's use:
 * <ol>
 * <li>declare a Rule in your test: @Rule public TestNameMDC testNameMDC = new TestNameMDC();</li>
 * <li>include the %X in the log4j pattern: %X{testMethod}</li>
 * </ol>
 * Note that the 'testMethod' in french braces above must match the {@link #MDC_KEY} defined here.
 *
 */
public class TestNameMDC extends TestWatchman {

  private static final String MDC_KEY = "testMethod";

  @Override public void starting(FrameworkMethod method) {
    MDC.put(MDC_KEY, method.getName());
  }
 
  @Override public void finished(FrameworkMethod method) {
    MDC.remove(MDC_KEY);
  }

  public String getMethodName() {
    return (String)MDC.get(MDC_KEY);
  } 
}

Tuesday, September 25, 2012

Scala on Play 2: List to Json Response

I've been writing some Scala. My first Scala app as a matter of fact. I looked at lift, I looked at play. I liked play better, so I'm learning Scala within the context of creating an application on the Play 2.0 framework.
So there's this problem. I have a list of objects, created via case class from the DTO layer. I want them returned from the Controller as Json. Oddly, the documentation on github does not give an example of this use case. I'm sure that if I were more versed in Scala, the solution would be obvious. If I were doing this in java, I would just for-loop over the list of case-class-instances to build a new list of Json. Or, I would annotate the case class (or DTO in java-speak) so that the Json layer would know how to json-ify each instance in the list.
What really surprises me is why doesn't the transformation happen automatically. Just create the Json for me. I don't really care what the names of the fields are in the json. Honestly, it's easier if the json uses the same field names.
But what's the Scala way?
Well, that documentation I liked to indicates that you need to
Json.toJson( Map )
Sure, that makes sense, I want the keys of the map to be the label and the value of the map is the value of the json field.
val jsonObject = Json.toJson(
  Map(
    "users" -> Seq(
      toJson(
        Map(
          "name" -> toJson("Bob"),
          "age" -> toJson(31),
          "email" -> toJson("bob@gmail.com")
        )
      ),
      toJson(
        Map(
          "name" -> toJson("Kiki"),
          "age" -> toJson(25),
          "email" -> JsNull
        )
      )
    )
  )
)
Being new to Scala, I have to scream WTF!? Why does the example show making up all the $%#!&@ data! How does that help put it into place? How can I utilize that? Oh, wait, I know. In that controller where I manufacture stupid data! OK, so after calming down, lets go try stackoverflow. I found this:http://stackoverflow.com/questions/8695335/how-to-render-json-response-in-play-framework-v2-0-latest-build-from-git
I was really expecting the answer to be a transformation. But no. This stackoverflow answer shows the solution as being an implicit object. Hmmm? I had not heard of those implicit objects.
implicit object BlahFormat extends Format[Blah] {...}