Ear plugin -- how to set context-root for web modules

By default the Gradle Ear plugin automatically generated the context-root element for each web module. The context-root appears to be the artifact name with the extension stripped off.

The problem with the default is that the context-root is going to change every time the version web module’s version changes. That’s not going to work for my needs and I would assume for others as well. We need to set a constant context-root regardless of the version on the artifact.

Is there some way to override the default value for the context-root?

I guess I didn’t mention it in the original post but I am referring to the context-path element in the application.xml file. See below for ran example of an application.xml file generated by the Ear plugin:

<?xml version="1.0"?>
<application xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" version="6">
  <display-name>my-ear</display-name>
  <module>
    <web>
      <web-uri>my-war-SNAPSHOT.war</web-uri>
      <context-root>my-war-SNAPSHOT</context-root>
    </web>
  </module>
  <library-directory>lib</library-directory>
</application>

I figured something out that works but it feels like a total hack. Here’s the script:

apply plugin: 'ear'
  dependencies {
    deploy project(path: ':my-war', configuration: 'archives')
}
  ear {
    deploymentDescriptor { webModule(project(":my-war").war.archiveName, "customContextPath") }
}

Which produces:

<?xml version="1.0"?>
<application xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" version="6">
  <module>
    <web>
      <web-uri>my-war-SNAPSHOT.war</web-uri>
      <context-root>customContextPath</context-root>
    </web>
  </module>
  <library-directory>lib</library-directory>
</application>

Is this the only way to do it?

I believe I have found a way to do this my using a closure which calls a function to map the filenames to context paths. Code below:

apply plugin: 'ear'
  dependencies {
    deploy project(path: ':my-war', configuration: 'archives')
}
  /* setup filename to context-path mappings */
webModuleMap = [
            'my-war': 'customContextPath'
        ]
  def findContextPath(String filename) {
    def me = webModuleMap.find {filename.startsWith(it.key)}
    if (!me) throw new StopExecutionException("Filename could not be mapped to context-path ${filename}")
    me.value
}
  ear {
    deploymentDescriptor {
        configurations.deploy.files.collect {f ->
            webModule(f.name, findContextPath(f.name))
        }
    }
}

Still interested in finding a better, more standard, conventional way though.

Hi, I personally prefer the first solution.

The second is a good base for integration in gradle it self.

May be you could provide a patch in Jira.

Does this solution still work? I’m getting following error if I use

project(":my-war").war.archiveName

inside the ear task:

  Could not find property 'war' on project ':my-war'.  

I also cannot use any variables as archive name that are setup by a task, even if the ear task depends on this custom task. It seems that the values are evaluated before the war project is even loaded or the custom task executed.

Any ideas how to solve this?

I use gradle 1.0