powered by Slim Framework
Follow @NesbittBrian rss

Using morphia with Play 2.0 and the sl4j logging error

Nov 28, 2011

I am in the middle of another fun side project using Play 2.0 and Scala. I am (strangely?!?) using morphia to access mongoDB as the datastore with my own Scala based wrapper. Yes I looked at casbah, rogue, salat but came back to morphia in the end since I had used it before. I'll probably go back to some of those other Scala specific libraries, probaly salat, but it just wasn't my focus this time around.

I came across an issue that boiled down to a logging change from Play 1.X to 2.0. Its an easy fix actually but the exception was weird (and got worse with subsequent page loads) enough that I'll post it here and hope I can save someone time.

The top of the exception stack that you get looks like this:


Caused by: java.lang.IllegalArgumentException: can't parse argument number
   at java.text.MessageFormat.makeFormat(MessageFormat.java:1339) ~[na:1.6.0_23]
   at java.text.MessageFormat.applyPattern(MessageFormat.java:458) ~[na:1.6.0_23]
   at java.text.MessageFormat.(MessageFormat.java:350) ~[na:1.6.0_23]
   at java.text.MessageFormat.format(MessageFormat.java:811) ~[na:1.6.0_23]
   at org.slf4j.bridge.SLF4JBridgeHandler.getMessageI18N(SLF4JBridgeHandler.java:251) ~[jul-to-slf4j.jar:na]
   at org.slf4j.bridge.SLF4JBridgeHandler.callLocationAwareLogger(SLF4JBridgeHandler.java:209) ~[jul-to-slf4j.jar:na]
   at org.slf4j.bridge.SLF4JBridgeHandler.publish(SLF4JBridgeHandler.java:285) ~[jul-to-slf4j.jar:na]
   at java.util.logging.Logger.log(Logger.java:481) ~[na:1.6.0_23]
   at java.util.logging.Logger.doLog(Logger.java:503) ~[na:1.6.0_23]
   at java.util.logging.Logger.logp(Logger.java:672) ~[na:1.6.0_23]
   at com.google.code.morphia.logging.jdk.JDKLogger.log(JDKLogger.java:107) ~[na:na]
   at com.google.code.morphia.logging.jdk.JDKLogger.debug(JDKLogger.java:38) ~[na:na]
   at com.google.code.morphia.mapping.MappedClass.(MappedClass.java:113) ~[na:na]
   at com.google.code.morphia.mapping.Mapper.getMappedClass(Mapper.java:200) ~[na:na]
   at com.google.code.morphia.mapping.Mapper.getCollectionName(Mapper.java:208) ~[na:na]
   at com.google.code.morphia.DatastoreImpl.getCollection(DatastoreImpl.java:546) ~[na:na]
   at com.google.code.morphia.DatastoreImpl.createQuery(DatastoreImpl.java:374) ~[na:na]
   at com.google.code.morphia.DatastoreImpl.find(DatastoreImpl.java:395) ~[na:na]

Then on the next page reload you start seeing exceptions like this:


NoClassDefFoundError: Could not initialize class models.Player$

Play 2.0 uses slf4j bridge SLF4JBridgeHandler.install() as it configures the root logger. This causes morphia to throw errors when the logger is in DEBUG mode. The last stack trace in morphia code is a call to log.debug("MappedClass done: " + toString());. There is a sl4fj morphia extension that you need to include in your classpath and then ensure you call to register the logger extension at startup and the error no longer happens. You can put it in a static {} block if you want or the Global object beforeStart().

For java the code is:


MorphiaLoggerFactory.registerLogger(SLF4JLoggerImplFactory.class);

For Scala the code is:


MorphiaLoggerFactory.registerLogger(classOf[SLF4JLogrImplFactory]);

Depending on where you register the new logger extension you might still see the exception. The other solution (as provided by Green Luo who manages the morphia Play module) is to call the init() which sets the internal loggerFactory to null.


MorphiaLoggerFactory.init();
MorphiaLoggerFactory.registerLogger(SLF4JLoggerImplFactory.class);

Hopefully I'll launch this side project tonight/tomorrow and I'll post about it like I did about moving my blog to Play 2.0.

For reference I have also posted responses on the morphia group as it has been asked there as well and an invalid bug was logged.

https://groups.google.com/d/topic/morphia/Ad8x1BYqD3w/discussion
http://code.google.com/p/morphia/issues/detail?id=328

This blog is now running on Play 2.0 BETA  Home Fun Play 2.0 project launch : Sidney Crosby Art Ross Watch and My NHL  
blog comments powered by Disqus