DZone
Java Zone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
  • Refcardz
  • Trend Reports
  • Webinars
  • Zones
  • |
    • Agile
    • AI
    • Big Data
    • Cloud
    • Database
    • DevOps
    • Integration
    • IoT
    • Java
    • Microservices
    • Open Source
    • Performance
    • Security
    • Web Dev
DZone > Java Zone > Grails Goodness: Writing Log Messages With Grails 3.2

Grails Goodness: Writing Log Messages With Grails 3.2

As of Grails 3.2, logging has changed for the log field that is injected into Grail artifacts. You can't use an object as the first argument anymore, requiring a change.

Hubert Klein Ikkink user avatar by
Hubert Klein Ikkink
·
Dec. 12, 16 · Java Zone · Tutorial
Like (2)
Save
Tweet
7.21K Views

Join the DZone community and get the full member experience.

Join For Free

Grails 3.2 changed the logging implementation for the log field that is automatically injected in the Grails artifacts, like controllers and services. Before Grails 3.2 the log field was from Jakarta Apache Commons Log class, but since Grails 3.2, this has become the Logger class from the Slf4J API. A big difference is the fact that the methods for logging on the Logger class don't accept an Object as the first argument. Before, there would be an implicit toString invocation on an object, but that doesn't work anymore.

In the following example, we try to use an object as the first argument of the debug method in a controller class:

package mrhaki.grails3

class SampleController {

    def index() { 
        log.debug new Expando(action: 'index')
        [:]
    }

}


When we invoke the index action, we get an exception:

...
2016-12-09 14:59:20.283 ERROR --- [nio-8080-exec-1] o.g.web.errors.GrailsExceptionResolver   : MissingMethodException occurred when processing request: [GET] /sample/index
No signature of method: ch.qos.logback.classic.Logger.debug() is applicable for argument types: (groovy.util.Expando) values: [{action=index}]
Possible solutions: debug(java.lang.String), debug(java.lang.String, [Ljava.lang.Object;), debug(java.lang.String, java.lang.Object), debug(java.lang.String, java.lang.Throwable), debug(org.slf4j.Marker, java.lang.String), debug(java.lang.String, java.lang.Object, java.lang.Object). Stacktrace follows:

java.lang.reflect.InvocationTargetException: null
        at org.grails.core.DefaultGrailsControllerClass$ReflectionInvoker.invoke(DefaultGrailsControllerClass.java:210)
        at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:187)
        at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
        at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
        at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
        at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
Caused by: groovy.lang.MissingMethodException: No signature of method: ch.qos.logback.classic.Logger.debug() is applicable for argument types: (groovy.util.Expando) values: [{action=index}]
Possible solutions: debug(java.lang.String), debug(java.lang.String, [Ljava.lang.Object;), debug(java.lang.String, java.lang.Object), debug(java.lang.String, java.lang.Throwable), debug(org.slf4j.Marker, java.lang.String), debug(java.lang.String, java.lang.Object, java.lang.Object)
        at mrhaki.grails3.SampleController.index(SampleController.groovy:6)
        ... 14 common frames omitted
...


When we change the log statement to log.debug new Expando(action: 'index').toString(), it works.

Another time saver and great feature is the use of placeholders, {}, in the logging message. This allows for late binding of variables that are used in the logging message. Remember when we used the Apache Commons Logging library, we had to enclose a logging statement in an if statement to check if logging was enabled. Because otherwise, the logging message with variable references was always evaluated, even though logging was disabled. With Slf4J's Logger, we don't have to wrap logging statements with an if statement if we use the "{}" placeholders. Slf4J will first check if logging is enabled for the log message — then the logging message is created with the variables. This allows for much cleaner code.

In the following example we use the placeholders to create a logging message that included the variable id:

package mrhaki.grails3

class SampleController {

    def show(final String id) {
        // Before Grails 3.2 we should write:
        // if (log.debugEnabled) {
        //     log.debug "Invoke show with id [$id]"
        // }
        // With Grails 3.2 it is only the debug method and 
        // String evaluation using {}.
        log.debug 'Invoke show with id [{}]', id
        [id: id]
    }

}


Written with Grails 3.2.3

Grail (web browser)

Published at DZone with permission of Hubert Klein Ikkink, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • 7 Ways to Capture Java Heap Dumps
  • Top 10 Automated Software Testing Tools
  • Open Source Monitoring and Metrics Landscape
  • 10 Programming Habits a Web Developer Should Embrace

Comments

Java Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • MVB Program
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends:

DZone.com is powered by 

AnswerHub logo