Grails log4j SMTPAppender NoClassDefFoundError
How do I set up SMTPAppender in a new Grails 2.4.5 project? When working in a development environment, I get a NoClassDefFoundError:
| Log4j error: ERROR Log4j initialization error: javax / mail / Message
| Java.lang.NoClassDefFoundError: javax / mail / Message
I set up a dependency for javax.mail and set up log4j like this:
dependencies {
provided 'javax.mail:mail:1.4.7'
}
log4j = {
appenders {
appender new org.apache.log4j.net.SMTPAppender(
name: 'smtp',
layout: pattern(conversionPattern: '%d{MM-dd-yyyy HH:mm:ss.SSS} [%t] %c %M %x%n%p: %m%n')
to: 'example@example.com',
from: 'example@example.com',
subject: 'Grails Message',
SMTPHost: '127.0.0.1')
)
}
}
source to share
I know this post is old, but I struggled with the same until I found a solution that at least works for me (not with SMTPAppender, but with Sentry - with the same purpose).
Explanation I found with errors where you get
Log4j error: ERROR Log4j initialization error: javax / mail / Message
Java.lang.NoClassDefFoundError: javax / mail / Message
Come from this piece of code:
dependencies {
provided 'javax.mail:mail:1.4.7'
}
The thing is, when you compile everything, when you try to do grails run-app
, you get this error.
The explanation I found is that log4j is initialized before maven dependency is resolved.
I wrote a comment on how I used Sentry as an application. https://github.com/getsentry/raven-java/issues/184#issuecomment-259432057
Basically, instead of adding the maven dependency, I downloaded the java file and added it to the grails project in src / java
So for the Sentry por example I added SentryAppender.java to my.package.sentry and then in log4j added:
appenders {
environments {
// This block is set up to use the stock raven SentryAppender in
// production. Sentry Appender runs into all kinds of
// class loading weirdness when used in a forked grails environment
production {
appender new my.package.sentry.SentryAppender(
name: 'sentry',
dsn: 'REDACTED',
threshold: org.apache.log4j.Level.WARN
)
}
// Uncomment this block if you need to test sentry
// in a dev environment
development {
appender new my.package.sentry.SentryAppender(
name: 'sentry',
dsn: 'REDACTED',
threshold: org.apache.log4j.Level.WARN
)
}
}
}
root {
warn 'stdout', 'sentry'
error 'stdout', 'sentry'
additivity = false
}
thus, it does not depend on external dependence.
I assume you can do something similar to mail dependency and add java files to src folder.
Hope this helps!
source to share
It looks strange - did you merge the dependency block and the block log4j
here at the same time, or are they in the same file in your application? The dependency must be in BuildConfig.groovy
, and the block log4j
must be in Config.groovy
. Also, it doesn't have to be log4j {
, but rather log4j = {
.
This is most likely a matter of time. If Config.groovy
parsed before the Javamail dependency is resolved, it will fail. Try commenting out the parts that reference the Javamail classes and run grails clean
and grails compile
. This will resolve dependencies and add this jar to the classpath. Then you can uncomment this code and run grails compile
again.
source to share