New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClassCircularityError: java/util/logging/LogRecord running webapp with JavaMelody #96

Closed
chronodm opened this Issue May 30, 2014 · 15 comments

Comments

Projects
None yet
4 participants
@chronodm

chronodm commented May 30, 2014

I'm getting the stack trace below when I try to launch my app using the embedded Tomcat container.

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':tomcatRun'.
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
...
Caused by: java.lang.ClassCircularityError: java/util/logging/LogRecord
    at net.bull.javamelody.LoggingHandler.publish(LoggingHandler.java:109)
    at org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:183)
    at org.apache.juli.logging.DirectJDKLog.debug(DirectJDKLog.java:106)
    at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:369)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:153)
    at org.apache.catalina.startup.Tomcat.start(Tomcat.java:341)
    at org.apache.catalina.startup.Tomcat$start.call(Unknown Source)
    at org.gradle.api.plugins.tomcat.embedded.BaseTomcatServerImpl.start(BaseTomcatServerImpl.groovy:37)
...

It doesn't happen when I use an external Tomcat so I expect it has something to do with Gradle's classpath and Gradle's built-in dependencies (and I don't even know how to find out what those are). I've poked around a bit and people seem to have similar problems relating somehow to SLF4J and/or Logback, neither of which my project uses. I've tried to work around it with the SLF4J legacy bridges but to no avail -- probably because I'm declaring them in my build.gradle and at that point it's too late.

It also looks like it's theoretically possible to disable JULI and make Tomcat log to log4j instead, which seems like it might have a chance of fixing the problem, but the instructions all have to do with manually replacing JARs in $CATALINA_HOME/bin and $CATALINA_HOME/lib, and I don't have the first idea how to make that happen in a Gradle context.

Any ideas?

@bmuschko

This comment has been minimized.

Show comment
Hide comment
@bmuschko

bmuschko May 30, 2014

Owner

Based on this question on Stackoverflow, this might have all sorts of root causes. You could probably exclude the Tomcaty JULI transitive dependency from your tomcat configuration or play around with your logging configuration.

Also, do you actually need Javamelody on your local embedded Tomcat? You might want to exclude its dependency locally.

Owner

bmuschko commented May 30, 2014

Based on this question on Stackoverflow, this might have all sorts of root causes. You could probably exclude the Tomcaty JULI transitive dependency from your tomcat configuration or play around with your logging configuration.

Also, do you actually need Javamelody on your local embedded Tomcat? You might want to exclude its dependency locally.

@chronodm

This comment has been minimized.

Show comment
Hide comment
@chronodm

chronodm May 30, 2014

I tried

configurations.tomcat {
  exclude(group: tomcatGroup, name: 'tomcat-juli')
}

but no luck; then I tried commenting out tomcat-embed-logging-juli from the tomcat configuration and that got me NoClassDefFoundError: org/apache/juli/logging/LogFactory.

chronodm commented May 30, 2014

I tried

configurations.tomcat {
  exclude(group: tomcatGroup, name: 'tomcat-juli')
}

but no luck; then I tried commenting out tomcat-embed-logging-juli from the tomcat configuration and that got me NoClassDefFoundError: org/apache/juli/logging/LogFactory.

@bmuschko

This comment has been minimized.

Show comment
Hide comment
@bmuschko

bmuschko May 30, 2014

Owner

If you provide me with a minimalistic project that reproduces the issue, I am going to have a look. It's kind of hard to diagnose without something to play around with.

Owner

bmuschko commented May 30, 2014

If you provide me with a minimalistic project that reproduces the issue, I am going to have a look. It's kind of hard to diagnose without something to play around with.

@chronodm

This comment has been minimized.

Show comment
Hide comment
@chronodm

chronodm May 30, 2014

I'll see what I can do, thanks.

chronodm commented May 30, 2014

I'll see what I can do, thanks.

@bmuschko

This comment has been minimized.

Show comment
Hide comment
@bmuschko

bmuschko May 30, 2014

Owner

No problem, would you mind checking it into GitHub including a Gradle wrapper so I can easily download and run it?

Owner

bmuschko commented May 30, 2014

No problem, would you mind checking it into GitHub including a Gradle wrapper so I can easily download and run it?

@chronodm

This comment has been minimized.

Show comment
Hide comment
@chronodm

chronodm commented May 30, 2014

@chronodm

This comment has been minimized.

Show comment
Hide comment
@chronodm

chronodm May 30, 2014

I'm trying to strip it down and remove JavaMelody and see if I can still get it to happen... I'll post another comment when I've pushed that.

chronodm commented May 30, 2014

I'm trying to strip it down and remove JavaMelody and see if I can still get it to happen... I'll post another comment when I've pushed that.

@chronodm

This comment has been minimized.

Show comment
Hide comment
@chronodm

chronodm May 30, 2014

Nope -- it doesn't seem to be necessary to actually have JavaMelody in the web.xml, though, so long as you include it in the classpath.

chronodm commented May 30, 2014

Nope -- it doesn't seem to be necessary to actually have JavaMelody in the web.xml, though, so long as you include it in the classpath.

@chronodm

This comment has been minimized.

Show comment
Hide comment
@chronodm

chronodm May 30, 2014

I've filed a JavaMelody issue as well in case they have any ideas.

chronodm commented May 30, 2014

I've filed a JavaMelody issue as well in case they have any ideas.

@evernat

This comment has been minimized.

Show comment
Hide comment
@evernat

evernat Jun 1, 2014

I suggest to note your versions of gradle-tomcat-plugin, tomcat, JDK (JDK 1.6.0_38, HotSpot 64-bit server VM ?) and OS.
And I suggest to test recent versions of JDK (and of Tomcat), this may change some things.

evernat commented Jun 1, 2014

I suggest to note your versions of gradle-tomcat-plugin, tomcat, JDK (JDK 1.6.0_38, HotSpot 64-bit server VM ?) and OS.
And I suggest to test recent versions of JDK (and of Tomcat), this may change some things.

@chronodm

This comment has been minimized.

Show comment
Hide comment
@chronodm

chronodm Jun 2, 2014

Same problem with jdk 1.7.0_51. I suspect the fix might be to get Tomcat to stop using JULI, but I'm not sure how to do that in the context of the plugin. It looks like at least one project has hacked around JULI by including their own implementation of org.apache.juli.logging.LogFactory; I'll see if I can figure out a way to do that.

chronodm commented Jun 2, 2014

Same problem with jdk 1.7.0_51. I suspect the fix might be to get Tomcat to stop using JULI, but I'm not sure how to do that in the context of the plugin. It looks like at least one project has hacked around JULI by including their own implementation of org.apache.juli.logging.LogFactory; I'll see if I can figure out a way to do that.

@chronodm

This comment has been minimized.

Show comment
Hide comment
@chronodm

chronodm Jun 2, 2014

All right -- my workaround was to hack together my own LogFactory that delegated to commons-logging (cf. the SLF4J version linked in the previous comment) and use it to replace tomcat-embed-logging-juli in the tomcat Gradle configuration. In that sense it's actually easier to replace JULI in the embedded Tomcat than it is in the standalone version (no mucking around in $CATALINA_BASE). It's a shame they don't publish a standard Maven artifact you can sub in there.

The real fix is probably Issue 58, so I think we can close this one -- thanks for your time.

chronodm commented Jun 2, 2014

All right -- my workaround was to hack together my own LogFactory that delegated to commons-logging (cf. the SLF4J version linked in the previous comment) and use it to replace tomcat-embed-logging-juli in the tomcat Gradle configuration. In that sense it's actually easier to replace JULI in the embedded Tomcat than it is in the standalone version (no mucking around in $CATALINA_BASE). It's a shame they don't publish a standard Maven artifact you can sub in there.

The real fix is probably Issue 58, so I think we can close this one -- thanks for your time.

@chronodm chronodm closed this Jun 2, 2014

@chronodm

This comment has been minimized.

Show comment
Hide comment
@chronodm

chronodm Jun 3, 2014

[Headdesk] Guess what, they do publish such an artifact:

// tomcat "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}"
tomcat "org.apache.tomcat.embed:tomcat-embed-logging-log4j:${tomcatVersion}"

chronodm commented Jun 3, 2014

[Headdesk] Guess what, they do publish such an artifact:

// tomcat "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}"
tomcat "org.apache.tomcat.embed:tomcat-embed-logging-log4j:${tomcatVersion}"
@bmuschko

This comment has been minimized.

Show comment
Hide comment
@bmuschko

bmuschko Jun 3, 2014

Owner

Awesome, thanks for looking into this!

Owner

bmuschko commented Jun 3, 2014

Awesome, thanks for looking into this!

@bmuschko bmuschko added the Won't fix label Jun 3, 2014

@seregamorph

This comment has been minimized.

Show comment
Hide comment
@seregamorph

seregamorph Oct 15, 2017

Had the same issue on plugin 2.3, gradlew 4.0, jdk 1.8u144, tomcat 8.0.47.

Finally found the smallest piece of code, that provokes Error:
@Configure public class WwwApplication extends org.springframework.boot.web.support.SpringBootServletInitializer { }
In my case this is a spring-web application (SpringServletContainerInitializer locates WwwApplication and somehow it changes the internal logic of SLF4JBridgeHandler/LogMessage initialization).

The only one way to fix it that I've found is to exclude the 'jul-to-slf4j' depedency from the war/lib classpath.

At the same time there is no such a problem if start the same gradle module with bootRun task (spring-boot) or install WAR into a standalone server.

I researched this problem a little. What I've found is that the class "org.slf4j.bridge.SLF4JBridgeHandler" was both in my war/lib and gradle-api classpath (lib/jul-to-slf4j). Probably the fork https://github.com/bmuschko/gradle-tomcat-plugin/issues/58 can fix this.

seregamorph commented Oct 15, 2017

Had the same issue on plugin 2.3, gradlew 4.0, jdk 1.8u144, tomcat 8.0.47.

Finally found the smallest piece of code, that provokes Error:
@Configure public class WwwApplication extends org.springframework.boot.web.support.SpringBootServletInitializer { }
In my case this is a spring-web application (SpringServletContainerInitializer locates WwwApplication and somehow it changes the internal logic of SLF4JBridgeHandler/LogMessage initialization).

The only one way to fix it that I've found is to exclude the 'jul-to-slf4j' depedency from the war/lib classpath.

At the same time there is no such a problem if start the same gradle module with bootRun task (spring-boot) or install WAR into a standalone server.

I researched this problem a little. What I've found is that the class "org.slf4j.bridge.SLF4JBridgeHandler" was both in my war/lib and gradle-api classpath (lib/jul-to-slf4j). Probably the fork https://github.com/bmuschko/gradle-tomcat-plugin/issues/58 can fix this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment