views:

609

answers:

1

Hi all,

I'm making a swing application with maven and I try to keep the pom.xml under tight reins (this file tends to become a pile of junk after pasting there whatever we find in google).

My pom is with jar and I use the maven-assembly-plugin with "jar-with-dependencies" descriptor. So I need to define twice the part of my project (main class and versions), once for the normal jar and the other once for the jar-with-dependencies.

I think the problem comes from the jar-with-dependencies assembly descriptor, instead of unpacking the normal jar and fusion the manifests, it creates a new jar from ${project.build.outputDirectory} wich smells strange to me.

Does anybody have a compact and elegant idea to avoid this repetition of my manifest configuration ?

Thanks, Nicolas.

+2  A: 

You can configure both the assembly and jar plugins to use a [particular manifest file. From the Creating an Executable Jar section of the assembly docs:

As you've no doubt noticed, the Assembly Plugin can be a very useful way to create a self-contained binary artifact for your project, among many other things. However, once you've created this self-contained jar, you will probably want the ability to execute it using the -jar JVM switch.

To accommodate this, the Assembly Plugin supports configuration of an element which is identical to that supported by the maven-jar-plugin (see Resources). Using this configuration, it's easy to configure the Main-Class attribute of the jar manifest:

Note the manifest you define is merged with the generated content. From the referenced jar page:

The content of your own manifest file will be merged with the entries generated by Maven Archiver. If you specify an entry in your own manifest file it will override the value generated by Maven Archiver.

The following configuration binds the assembly-plugin execution to the pre-integration-test phase (the next phase after package) and will also include the MANIFEST.MF defined under src/main/resources/META-INF.

So following this approach, you can define the common manifest contents in your MANIFEST.MF and have them be merged into the final manifest.

contents of src/main/resources/META-INF/MANIFEST.MF

Created-By: Me
Foo: bar
Main-Class: com.foo.bar.MyMainClass
Bundle-Version: 4.0.0


Update: Based on the comments about using addDefaultSpecificationEntries, the suggested approach will work in conjunction with that specification on the jar produced by the jar plugin. However it looks like the assembly plugin doesn't yet support merging the additional declarations. The jar plugin merges the manifest from src/main/resources with the additionally specified values to give this content on my test project:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Me
Built-By: Rich Seller
Build-Jdk: 1.5.0_15
Specification-Title: Unnamed - org.test:test:jar:1.0.0
Specification-Version: 1.0.0
Implementation-Title: Unnamed - org.test:test:jar:1.0.0
Implementation-Version: 1.0.0
Implementation-Vendor-Id: org.test
Foo: bar
Main-Class: com.foo.bar.MyMainClass
Bundle-Version: 4.0.0

Whereas the output from the assembly-plugin is:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Me
Foo: bar
Main-Class: com.foo.bar.MyMainClass
Bundle-Version: 4.0.0

config:

<plugin>
  <artifactId>maven-assembly-plugin</artifactId>
  <executions>
    <execution>
      <id>jar-with-deps</id>
      <phase>pre-integration-test</phase>
      <goals>
        <goal>single</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <descriptorRefs>
      <descriptorRef>jar-with-dependencies</descriptorRef>
    </descriptorRefs>
    <archive>
      <manifestFile>${manifest.file}</manifestFile>
      <!--these properties are ignored-->
      <manifest>
        <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
        <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
      </manifest>
    </archive>
  </configuration>
</plugin>
<plugin>
  <artifactId>maven-jar-plugin</artifactId>
  <version>2.2</version>
  <configuration>
    <archive>
      <manifestFile>${manifest.file}</manifestFile>
      <manifest>
        <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
        <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
      </manifest>
    </archive>
  </configuration>
</plugin>
...
<properties>
  <manifest.file>src/main/resources/META-INF/MANIFEST.MF</manifest.file>
</properties>
Rich Seller
thanks, that's an idea. But I use <addDefaultSpecificationEntries>, this would mean filtering the resource and scatering part of the configuration to another file.
nraynaud
this approach works well with non-desktop apps as well
sal
@nraynaud yes based on that additional information this solution won't work as you require. I've updated my answer to show it works for the jar plugin, but not currently for the assembly plugin (up to and including 2.2-beta-4)
Rich Seller