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

Gist: Detailed stacktrace

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')
        )
    }
}

      

GitHub: Sample Project

+3


source to share


2 answers


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!

+2


source


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.

+1


source







All Articles