Skip to content
Advertisement

Customize Manifest in War task

I need to modify Manifest file during the assembly of WAR file. I need to add a list of all files on a class path to avoid java.io.IOException: CreateProcess error=206, The filename or extension is too long exception being thrown when I want to execute this java file on Windows machine.

Declared directly in build script this task does the work.

task pathingWar(type: War) {
  getArchiveAppendix().set("pathing")
  doFirst {
    manifest {
      attributes "Class-Path": sourceSets.main.runtimeClasspath.files.collect { project.uri(it) }.join(" ")
    }
  }
}

However I wanted to create a standalone task in buildSrc directory like in the code below. War gets created with the pathing appendix in name, but there is no additional Class-Path property inside MANIFEST.MF file even if classpathFiles variable holds required values while debugging the execution of the task.

class PathingWar extends War {

   PathingWar() {
    getArchiveAppendix().set("pathing")
  }

  @TaskAction
  def setManifestTask() {
    def classpathFiles = ((SourceSet)((SourceSetContainer) getProject().getExtensions().getByName("sourceSets"))
            .getByName("main")).getRuntimeClasspath().getFiles().collect {project.uri(it)}.join(" ")
    setManifest(getManifest().attributes(["Class-Path": classpathFiles]))
  }
}

Attributes won’t be set to the Manifest, what did I missed when translating logic from build script to custom task?

Update

After further inspection I see that when setManifestTask() annotated with @TaskAction is being executed is already being too late. At this point war is generated under the build/libs folder. I need another way of configuring the manifest. I don’t know which other approach to use.

Advertisement

Answer

I tried to set manifest Class-Path attribute in the doFirst{} block so that it would be set as first action and similar like in the original script without a success. Still jar was generated before closure in doFirst was executed.

After I read the following answer https://stackoverflow.com/a/16413207/978302 I understood I shouldn’t be overriding functionality of a War task. Instead I have to configure it with available inputs and result will be generated behind the scenes.

Final solution doesn’t contain any actions defined. Only additional configuration for:

  • archivaAppendix
  • manifest

Task definition:

class PathingWar extends War {

  PathingWar() {
    getArchiveAppendix().set("pathing")
    manifest {
      def classpathFiles = ((SourceSet) ((SourceSetContainer) getProject().getExtensions().getByName("sourceSets"))
              .getByName("main")).getRuntimeClasspath().getFiles().collect { project.uri(it) }.join(" ")
      attributes "Class-Path": classpathFiles
    }
  }
}

BTW: I still don’t understand why the task defined in script works as expected.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement