Using gradle-tomcat-plugin

Hi, I am trying to get the gradle-tomcat-plugin working - we are running gradle + maven concurrently because haven’t ever been able to get tomcat plugin working in gradle.

The tomcatRun and tomcatRunWar tasks don’t work - tomcatRunWar has library issues and tomcatRun seems to just load an empty webapp.

build.gradle:

apply plugin: "war"
apply plugin: "groovy"
apply plugin: "tomcat"
  buildscript {
  classpath "gradle-tomcat-plugin:gradle-tomcat-plugin:0.8.2", "org.apache.tomcat:catalina:6.0.35" // and coyote, jasper, jdbc, mysql, etc
}
  dependencies {
  tomcat "org.jboss.weld.servlet:weld-servlet:1.1.3.Final"
}
  war {
  from('../content/src/main/webapp/resources') { into('resources') }
  webXml = file('src/main/resources/web.xml')
}
  tomcatRun {
  dependsOn("war")
  contextPath = ""
  webDefaultXml = file("src/main/resources/web.xml")
  configFile = file("src/main/etc/embedded-context.xml")
}
  tomcatRunWar {
  contextPath = ""
  webDefaultXml = file("src/main/resources/web.xml")
  configFile = file("src/main/etc/embedded-context.xml")
}

tomcatRunWar has slf4j errors - it seems like an incorrect version of slf4j is being loaded instead of 1.5.8, as is configured in upstream projects (I have compile project(":server") dependency, and the server module uses slf4j 1.5.8). I have tried manually adding slf4j 1.5.8 to the tomcat configuration, and get the same error:

:web:war
:web:tomcatRunWar
Error configuring application listener of class org.jboss.weld.environment.servlet.Listener
java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log(Lorg/slf4j/Marker;Ljava/lang/String;ILjava/lang/String;Ljava/lang/Throwable;)V
... stacktrace...
Skipped installing application listeners due to previous error(s)
Error listenerStart
Context [/] startup failed due to previous errors
Started Tomcat Server
The Server is running at http://localhost:8080/

tomcatRun seems to initialize find, but no webapp is available:

:artemis-web:war
:artemis-web:tomcatRun
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/usr/local/gradle/gradle-1.0-milestone-7/lib/logback-classic-1.0.0.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/brett/.gradle/caches/artifacts-7/artifacts/30e551990fc3185e7269f863a1c1b023/org.jboss.weld.servlet/weld-servlet/1.1.3.Final/jar/weld-servlet-1.1.3.Final.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/brett/.gradle/caches/artifacts-7/artifacts/30e551990fc3185e7269f863a1c1b023/org.jboss.weld.servlet/weld-servlet/1.1.3.Final/jar/weld-servlet-1.1.3.Final.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/brett/.gradle/caches/artifacts-7/artifacts/30e551990fc3185e7269f863a1c1b023/org.slf4j/slf4j-log4j12/1.5.8/jar/slf4j-log4j12-1.5.8.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
Class 'javax.ejb.PostActivate' not found, interception based on it is not enabled
Class 'javax.ejb.PrePassivate' not found, interception based on it is not enabled
Started Tomcat Server
The Server is running at http://localhost:8080/

startup above looks fine, but when I try access the webapp, I get:

Exception in thread "http-8080-1" java.lang.NullPointerException
        at java.util.concurrent.ConcurrentLinkedQueue.offer(ConcurrentLinkedQueue.java:190)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler$1.offer(Http11Protocol.java:551)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler$1.offer(Http11Protocol.java:568)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:632)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
        at java.lang.Thread.run(Thread.java:619)

Any suggestions on where I am going wrong?

And then I run out of permanent generation memory: Exception in thread “ContainerBackgroundProcessor[StandardEngine[localEngine]]” java.lang.OutOfMemoryError: PermGen space

Hi Brett,

The Tomcat plugin is a third-party plugin and doesn’t ship with Gradle. I think your issue would have gotten better attention if you’d opened an issue on the GitHub plugin page.

The first issue I see in your configuration is that you don’t assign the Tomcat libraries to the ‘tomcat’ configuration outside of the ‘buildscript’ closure. This has changed with version 0.8 and was mentioned in the RELEASE notes as well as the README file. In your case it would to look like this:

repositories {
    mavenCentral()
}
  dependencies {
    def tomcatVersion = '6.0.35'
    tomcat "org.apache.tomcat:catalina:${tomcatVersion}",
                // and coyote, jasper
}

All other dependencies (project dependencies) get assigned to the usual configurations e.g. ‘compile’ etc. and not the ‘tomcat’ configuration. If you want to use a specific version of SLF4J you’d need to assign this in your ‘dependencies’ closure of your web app submodule (outside the ‘buildscript’ closure) using the ‘compile’ configuration.

dependencies {
    compile ...
}

The tasks ‘tomcatRun’ and ‘tomcatRunWar’ already depend on the WAR plugin internally so you don’t need to assign it: ‘tomcatRun { dependsOn(“war”) }’ is not needed. I’d try to assign the context a different value and a blank String to see if you can reach the web app. There was an bug in the plugin for the root context path and I am not sure if this is affecting you as well. This will be fixed with 0.8.3 which hasn’t been pushed yet.

For fixing your PermGen issues you will need to set a higher value in your ‘GRADLE_OPTS’ environment variable of your Gradle runtime script ‘<GRADLE_HOME>/bin/gradle’ or ‘gradle.bat’ e.g. ‘-XX:MaxPermSize=128M’. If you use the Gradle wrapper you’d of course have to change the value there.

Try to run tomcatRun on INFO level and you will the classpath that is used for your web app to debug your issues: ‘gradle tomcatRun -i’. That should fix most of your issues. Please let me know if you need additional help. You can also shoot me a mail and we can get it worked out.

Cheers,

Ben

BTW: Is there a reason why you don’t have the ‘web.xml’ sitting in the default path ‘src/main/webapp/WEB-INF’? You could save yourself some extra configuration.

Hi Benjamin, firstly, thanks for the plugin, and the assistance with it.

I think the primary cause of the problem is the contextPath. The first time I ran it, I ran it without setting the contextPath - this resulted in 404 errors due to our applications configuration, but otherwise the application initialized. I get errors after switching to “” contextPath - our application always runs under root.

web.xml is located in its current location as part of a legacy setup - just never moved it, and might move it at some point - not really too important right now.

When I initially configured the script, i had all the tomcat libraries (coyote, catalina, etc) in the tomcat configuration, but as I was setting up this post, I removed them from tomcat, and re-ran. It actually runs fine without these libraries in the “tomcat” configuration, and only having them in the buildscript’s classpath configuration.

For some reason, “tomcatRun” task does not seem to run “war” as a dependency. With the dependsOn line commented out, here is the output:

:web:compileJava UP-TO-DATE
:web:compileGroovy UP-TO-DATE
:web:processResources UP-TO-DATE
:web:classes UP-TO-DATE
:web:tomcatRun
.... tomcatRun output .....

As you can see, it runs classes, and then tomcatRun, skipping the war task. tomcatRunWar includes the war task.

The slf4j libraries are configured in my :server module’s compile configuration. the :web module has a compile dependency on project(":server"), and so the slf4j dependency is pulled through (i.e. no need to explicitly add it to :web’s compile configuration).

I am going to rebuild the plugin from master and see if it resolves the context issue.

You are right. Only the task ‘tomcatRunWar’ does depend on the ‘war’ task which aligns with the Jetty plugin behavior. All web app references for the task ‘tomcatRun’ get resolved at runtime so you don’t actually need to depend on the ‘war’ task as long as you assign ‘webDefaultXml’. You might have a special case because your resource files sit in a different directory and need to be copied.

I’d recommend you use the’ tomcat’ configuration for your Tomcat dependencies. Otherwise, you might run into classloading issues. Make sure you don’t have a different version of SLF4J pulled in as a transitive dependency. This might be your issue; having two different versions of SLF4J in your classpath.

Let me know if using the master build of the plugin fixes your problem. Otherwise, I can have a deeper look at it.

Hi Benjamin,

It was the root context bug that was causing the problem. I am able to access the web UI on root context with the latest build from master. no classpath issues, the slf4j problem seemed to be a knock-on effect of the context bug.

This only works for tomcatRunWar - the war task runs, but because of the project layout the tomcatRun task loads an empty app. I’m pretty sure it’s something to do with the fact that we have written our own web framework (Groovy-based).

Next: jrebel :slight_smile:

Great! I released version 0.8.3 of the plugin so you don’t have to rebuild it manually from master. I am still kind of surprised that you can’t get ‘tomcatRun’ working. Well, let me know if you need additional help with this. I think sending me your full build script would be helpful.

FYI: In case you didn’t see that but integrating the Tomcat plugin with JRebel is very well documented in the FAQ of the plugin’s README file.

I did see the notes in the README on github :), hopefully its straight forward. Will send through build script.

C:\mifos X\mifosx\mifosng-provider>gradle clean

FAILURE: Build failed with an exception.

  • What went wrong: Could not resolve all dependencies for configuration ‘:classpath’. > Could not find group:bmuschko, module:gradle-tomcat-plugin, version:0.9.5.

Required by:

:mifosng-provider:unspecified

  • Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get mo re log output.

BUILD FAILED

Total time: 2.08 secs

may i know what might went wrong in my case please

I have tried numerous ways to get a war deployed to tomcat with no luck ( cargo, ssh, now this ), every post, tutorial on the web fails with something, not very good gradle. This is a very common thing to do and I should be able to do this with half an hour of work. With ant and maven I was able to get this working within an hour.

Help us understand your deployment requirements and I am sure we can get you up and running with at least one of these methods. Also, we’d need to see your build code and the error message you are experiencing.

Try changing URL of the repository to https. We had same error.

Try changing URL of the repository to https.

We had same error

Please use the following configuration to declare the dependency to the plugin:

buildscript {
    repositories {
        jcenter()
    }
      dependencies {
        classpath 'org.gradle.api.plugins:gradle-tomcat-plugin:1.2.4'
    }
}