Grails doesn't log plugins - grails

I cannot make the standard logging mechanism work for plugins without the use of the #Slf4j or #CompileStatic annotations.
The main application's standard logging is functioning properly.
I can't figure out why it doesn't work without the annotation.
grailsVersion=4.1.1, groovyVersion=2.5.14
logbook.groovy is including the packages:
List<String> debug = [
'grails.app',
'foo', // My application and some plugins
'boo', // only grails plugins
]
debug.each {
logger(it, DEBUG, ['FILE'], false)
}

Related

Grails 3.3.8 does not reload the changes made to the project

I have a project with grails 3.3.8, the problem is that once I edit a controller or a gsp file, the changes are not reflected in the web browser even though the following message appears when it detects a change:
Controller.groovy change, compiling...
I have tried to start the app in the following way:
grails -reloading run-app.
And also with:
// File: build.gradle
import grails.util.Environment
...
bootRun {
final Boolean reloadEnabled =
Boolean.valueOf(
System.properties[Environment.RELOAD_ENABLED])
if (reloadEnabled) {
systemProperty Environment.RELOAD_ENABLED, reloadEnabled
}
}
...
grails -Dgrails.env=custom -Dgrails.reload.enabled=true run-app
According to this link https://intellij-support.jetbrains.com/hc/en-us/community/posts/207602705-Grails-3-not-automatically-hot-swapping-changed-code-after-upgrading-to-2016-1-3 it appears that hot reloading of classes only suns to happen in grails 3.3.x when the environment is set to development.
I've not been able to confirm that for myself however. I notice you are providing "custom" as your environment. Maybe try changing it to the development environment and see if that helps.
Also just want to confirm that your not just seeing behaviour listed in Grails auto recompile never completes (Grails 3.3.6)

grails 3 - Update grails config during Plugin "doWithApplicationContext"

I've got a plugin that, during startup, reads some properties from the applications Config file, creates some domain objects and then needs to update the configuration with some additional information. However, it seems that the config object available during doWithApplicationContext is not the actual grailsApplication.config object.
For instance, attempting to do something straightforward in the MyPluginGrailsPlugin.groovy file like:
void doWithApplicationContext() {
grailsApplication.config.put('test', 'testValue')
}
does not update the config.
If this plugin is incldued in an application, at any point after startup, grailsApplication.config.getProperty('test') will return null.
How does one go about updating the config map during plugin startup?
NOTE: In grails 2, this used to work.
With this code snippet in MyPluginGrailsPlugin.groovy's doWithApplicationContext, new properties were successfully added into the application's config object.
ConfigObject myConfigObject = new ConfigSlurper().parse(props)
PropertySource propertySource = new MapPropertySource('grails.plugins.myPlugin', [:] << myConfigObject)
def propertySources = grailsApplication.mainContext.environment.propertySources
propertySources.addFirst propertySource
As an additional note: in doWithApplicationContext in my plugin, changing the config object like this worked in Grails 2 and no longer works in Grails 3.
grailsApplication.config.merge(myConfigObject)
grailsApplication.configChanged()

Disable reloading in Grails 3.1 / springloaded

I'm trying to disable automatic reload/recompiling in Grails 3.1 as I would like to use JRebel instead.
I find springloaded rather limited, but more importantly is constantly fails with
File /Users/engrun/Development/projects/grailsPoc/grails-app/controllers/grailsPoc/HelloController.groovy changed, recompiling...
java.lang.IllegalAccessException: Class org.springsource.loaded.ReloadableType can not access a member of class org.springframework.aop.framework.CglibAopProxy$ClassLoaderAwareUndeclaredThrowableStrategy with modifiers "public"
I have tried all kinds of settings that I have found available, however, none actually disables reloading when running the run-app command
I have tried
disable.auto.recompile=true
on command line, GRAILS_OPTS, and in application.yml
I have tried the
-noreloading
flag, both on command line and GRAILS_OPTS.
According to docs, this should have worked
https://grails.org/wiki/Auto%20Reloading
And the answer accepted as the correct one here
how can I disable reloading in a grails 3.0.0 app?
does not work either.
Have anyone actually succeeded in disabling auto-reloading in Grails 3.1?
(And successfully configured Grails 3 with JRebel?)
In 3.x apps you can disable Spring Loaded by adding
grails {
agent {
enabled = false
}
}
to build.gradle.
Burt's answer is correct related to the question -> how to disable autoreloading.
However, Anton's answer is relevant to the second/related issue on getting Jrebel to work.
I now have a working example, which works with both
gradle bootRun -Pjrebel -> disable springloaded, using jrebel
gradle bootRun -> uses springloaded
and
grails
grails> run-app
My config is a combination of
export GRAILS_OPTS="-javaagent:$JREBEL_HOME/jrebel.jar -Drebel.base=/Users/<username>/.jrebel"
and build.gradle
rebel {
alwaysGenerate = false
showGenerated = true
//rebelXmlDirectory = "build/classes"
}
if (project.hasProperty('jrebel')) {
bootRun.dependsOn(generateRebel)
grails {
agent {
enabled = false
}
}
tasks.withType(JavaExec) {
jvmArgs "-javaagent:jrebel.jar"
jvmArgs "-Xverify:none"
}
}
Thanks #burt-beckwith and #anton-arhipov for your input!
To enable JRebel for Grails 3 project you need to configure -javaagent argument with the corresponding path the jrebel.jar in build.gradle file:
tasks.withType(JavaExec) { jvmArgs "-javaagent:jrebel.jar" }

logging my application's classes at DEBUG level, all others at WARN

I've configured my Grails app to read the log4j config from /conf/log4j.properties file instead of the more usual DSL in Config.groovy, by adding the following Spring bean:
log4jConfigurer(MethodInvokingFactoryBean) {
targetClass = "org.springframework.util.Log4jConfigurer"
targetMethod = "initLogging"
arguments = ["/conf/log4j.properties", 1000 * 60] // 2nd arg is refresh interval in ms
}
My goal is to log all the classes in the app itself at the DEBUG level, and all others at the WARN level. /conf/log4j.properties contains the following:
log4j.logger.com.myapp=DEBUG, CONSOLE
log4j.logger.grails.app=DEBUG, CONSOLE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%-5p myapp %c{3} %d{HH:mm:ss,SSS} %t : %m%n
It seems the namespace com.myapp is used for regular classes in my app (e.g. those under src/groovy), whereas the namespace grails.app is used for Grails artefacts (controllers, services, taglibs, etc.). However the grails.app namespace also includes artefacts from plugins, which I don't want to log at the DEBUG level.
Is there a way to enable DEBUG logging only for the classes in my application?
You append your package unto the grails.app.controllers to get just your application.
info 'grails.app.controllers.mypackage'
Adding the following solved the problem
log4j.logger.grails.app.conf.com.myapp=DEBUG, CONSOLE
log4j.logger.grails.app.filters.com.myapp=DEBUG, CONSOLE
log4j.logger.grails.app.taglib.com.myapp=DEBUG, CONSOLE
log4j.logger.grails.app.services.com.myapp=DEBUG, CONSOLE
log4j.logger.grails.app.controllers.com.myapp=DEBUG, CONSOLE
log4j.logger.grails.app.domain.com.myapp=DEBUG, CONSOLE
Presumably if a Grails app has other types of artefacts that you want to log at the DEBUG level, an additional logger should be configured for each one.

Sending log messages from Grails BootStrap.groovy and plugin descriptors

When I was introducing the Fixture module into my Grails application, I had trouble finding out how to send log messages from the application's main BootStrap.groovy and from the initialization code of my plugins.
I use the following log4j config in Config.groovy
log4j = {
appenders {
console name: 'consoleAppender', layout: pattern(conversionPattern: '%d{dd-MM-yyyy HH:mm:ss,SSS} %5p %c{2} - %m%n')
}
root {
// define the root logger's level and appenders, these will be inherited by all other loggers
error 'consoleAppender'
}
// change the default log level for classes in our app to DEBUG
def packageRoot = 'com.example.myapp'
def appNamespaces = [
packageRoot,
"grails.app.conf.$packageRoot",
"grails.app.filters.$packageRoot",
"grails.app.taglib.$packageRoot",
"grails.app.services.$packageRoot",
"grails.app.controllers.$packageRoot",
"grails.app.domain.$packageRoot",
"grails.app.conf.BootStrap"
]
// statements from the app should be logged at DEBUG level
appNamespaces.each { debug it }
}
The only change you should need to make is to set packageRoot to the root package of your app. The name/namespace of the logger that is assigned to BootStrap.groovy is grails.app.conf.BootStrap, so including this in appNamespaces ensures that it will log at the default level for the application (debug in the example above).
You don't have to do anything to get a logger instance in BootStrap.groovy, one is already provided by Grails with the name log, e.g.
class BootStrap {
def init = { servletContext ->
log.debug 'hello bootstrap'
}
}
In Grails 2.2.4:
The "log" logger is injected into the application's main BootStrap.groovy and into the plugin's descriptor (e.g.: FooGrailsPlugin.groovy)
The logger in the app's BootStrap.groovy has a name like "grails.app.BootStrap" so by enabling the appending of the "grails.app" logger in the configuration will allow displaying the messages sent through this logger.
The logger in the plugin descriptors has no package prefix, and named exactly as the descriptor class but without the groovy extension. E.g.: "FooGrailsPlugin", so it is not so easy to enable the log messages by the default injected logger. It doesn't help if you add a package definition into the top of plugin descriptor, it will not be used in the composition of the name of the logger.
Naturally, you can manually define a logger in the plugin descriptor (using a package name according to your needs) like this:
private static final log = LogFactory.getLog("yourapp.foo.FooGrailsPlugin")
After this, you can enable the "yourapp.foo" logger in the application and you will see the messages sent through the plugin descriptor's manually defined logger.

Resources