froginvasion
froginvasion

Reputation: 844

How to add a dynamically generated file to my ear archive?

Basically, we have an ear archive that has multiple dependencies. In those dependencies, we plan on filling the manifest or some properties file with multiple properties:

This should already be possible for individual artifacts that are built by our CI server, and this is also not really the problem I'm having.


Now I use maven for building my ear archive, with the maven-ear-plugin. My idea was to just use a groovy script (executed by gmaven-plus) that will read all the jar archives, and fetch the manifest. Then I can rewrite the manifest of the ear archive, or write my own properties file that contains the info I want.

import org.apache.commons.io.FileUtils
import java.util.jar.JarFile

def path = "target/${project.name}-${project.version}"
def artifactDir = new File(path)
def output = new File("$path/META-INF/build-info.properties")

def lines = []

artifactDir.listFiles().each { file->
    if (file.isFile() && (file.name.endsWith(".war") || file.name.endsWith(".jar"))) {
        def jar = new JarFile(file)
        def manifest = jar.manifest
        println "processing: $file.name"
        println manifest.mainAttributes
        println jar.properties
        manifest.mainAttributes.keySet().each { attrKey->
            def val = manifest.mainAttributes.getValue(attrKey.toString())
            lines << "$file.name.$attrKey=$val"
        }
    }
}

FileUtils.writeLines(output, lines as Collection<?>

)

This script works fine, and will write the build-info.properties file with all the info I'd like to be in there.

This is the plugin configuration:

<plugin>
    <groupId>org.codehaus.gmavenplus</groupId>
    <artifactId>gmavenplus-plugin</artifactId>
    <version>1.5</version>
    <executions>
        <execution>
            <id>create-manifest</id>
            <phase>package</phase>
            <goals>
                <goal>execute</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <scripts>
            <script>file:///${project.basedir}/src/main/gmaven/create-manifest.groovy</script>
        </scripts>
    </configuration>
</plugin>

Of course, you'll already notice what's wrong with this: the packagephase is too late, prepare-package is too early, because the ear plugin has not yet copied the dependencies I'm scanning.


Conclusion

Well, the obvious thing to do would be to unzip the ear produced, and then add the file manually, then zip it again. But that seems pretty dirty to me, and I was wondering whether there is no cleaner way to do this?

Perhaps by leverageing gradle, or some option of the maven-ear-plugin I have not yet discovered? Or just in general, how would you tackle the specific problem I am facing here?

Upvotes: 0

Views: 664

Answers (1)

khmarbaise
khmarbaise

Reputation: 97507

Why not using the maven possibilities..like the configuration for the archiver which means you can use a configuration like this for the maven-jar-plugin:

   <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-jar-plugin</artifactId>
          <version>${maven-jar-plugin.version}</version>
          <configuration>
            <archive>
              <addMavenDescriptor>true</addMavenDescriptor>
              <index>true</index>
              <manifest>
                <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
              </manifest>
              <manifestEntries>
                <artifactId>${project.artifactId}</artifactId>
                <groupId>${project.groupId}</groupId>
                <version>${project.version}</version>
              </manifestEntries>
            </archive>
          </configuration>
        </plugin>

This can also be used for maven-war-plugin, maven-ejb-plugin and for maven-ear-plugin as well...See the docs for maven-ear-plugin see archive entry.

The buildnumber from your CI solution (for example Jenkins) has an env variable BUILD_NUMBER which you can use as well...

Full example how a corporate pom can look like take a look here.

Update:

What i missed is that you can use filtering to create such file. Put a file into src/main/resources with the following content:

groupId=${project.groupId}
artifactId=${project.artifactId}
version=${project.version}

Define the following as part of your pom file:

... src/main/resources true

Furthermore this will package the above file into your ear/war/jar file.

Apart from that a file which contains already the above information can be found in earchive META-INF/groupId/artifactId/pom.properties which contains the above. Not the build number and build time...

The build time can be used by using the following:

 <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-ear-plugin</artifactId>
      <version>2.6</version>
      <configuration>
          <archive>
            <manifestEntries>
              <buildTime>${maven.build.timestamp}</buildTime>
              <buildNumber>${env.BUILDNUMBER}</buildNumber>
            </manifestEntries>
          </archive>
      </configuration>
    </plugin>

${env.BUILDNUMBER} is of course a refererence to bamboos variables which contains such information.

Upvotes: 1

Related Questions