28

I have a maven project which generates a jar via the maven assembly plugin I want to run as a console app. However, the MainClass attribute is not being set in MANIFEST.MF. Here is my plugin configuration:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.2.1</version>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <archive>
                    <manifest>
                        <mainClass>net.justaprogrammer.poi.cleanser.Cleanser</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>

However, this does not get added to the MANIFEST.MF in the jar generated by mvn package. The manifest generated is below:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: zippy
Build-Jdk: 1.6.0_25

What am I doing wrong?

mhaller
  • 14,122
  • 1
  • 42
  • 61
Justin Dearing
  • 14,270
  • 22
  • 88
  • 161
  • That works exactly as advertised. Are you sure you're looking in the right output jar? – Ryan Stewart Oct 16 '11 at 16:12
  • As far as I can tell yes. My pom.xml contains no plugins with the name jar in it. As I stated in my edit I am using `mvn package` to generate my jar. The jar is called PoiCleanser-0.1.0.BUILD-SNAPSHOT.jar and is at the root of the target folder. – Justin Dearing Oct 16 '11 at 16:37

4 Answers4

26

I missed that you weren't generating your assembly on package. You have a jar project, so Maven will build a jar using the maven-jar-plugin. You don't have to have anything in your pom to tell it that. That's Maven's convention-over-configuration working for you. The jar it builds will have only your project classes and resources in it. If you want to add a Main-Class to the manifest in that jar, you should configure the jar plugin to do so. Basically, just move that archive configuration to the jar plugin.

However, if you actually want to assemble an executable fat jar--that is, a jar that includes all of your classes as well as the classes of all of your dependencies--then you have the setting in the right place, but you need to actually run the assembly plugin either using mvn assembly:single or by binding that goal to a lifecycle phase. To be clear, if you do this, then your project will output two jars: one that contains your project files and one that contains that plus the contents of all the libraries that your project depends on. The former is built by the jar plugin. That latter is built by the assembly plugin. Note that fat jars aren't commonly used, and you can run into unusual problems when you use them because they're rather outside the realm of normal Java stuff.

Ryan Stewart
  • 126,015
  • 21
  • 180
  • 199
  • Ryan, that is very informative. I'm not particularly married to a fat jar, but I'm glad I understand the difference now. I'll test and mark your answer as correct. – Justin Dearing Oct 16 '11 at 20:04
  • Ryan, I just tried `mvn assembly:single` and I have a "fat jar" with all my dependencies, a Main-Class in my MANIFEST.MF, but I don't actually have the code I wrote in it. I think the jar plugin is best, but I'd like a proper jar plugin as well. – Justin Dearing Oct 22 '11 at 19:11
  • I'll make a separate question for the assembly plugin. – Justin Dearing Oct 22 '11 at 19:23
9

For copy&paste fans like me, assembled from above answer, and http://maven.apache.org/plugins/maven-assembly-plugin/usage.html#Execution:_Building_an_Assembly:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
      <archive>
        <manifest>
          <mainClass>com.db.search.filenet.Load</mainClass>
        </manifest>
      </archive>
    </configuration>
    <executions>
      <execution>
        <id>assemble-all</id>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
      </execution>
    </executions>
  </plugin>
Frischling
  • 2,100
  • 14
  • 34
  • wrong answer, as the OP question is exactly the fact that the mainClass here isn't written in the manifest because of the fact that the OP is using the assembly on the same project that the jar generated. So the declaration need to be moved to the maven-jar-plugin. – Walfrat Jun 21 '21 at 12:31
  • Don't get you - @mhaller sais he's using the assembly plugin, so I shouldn't deviate from that in my answer. – Frischling Dec 19 '22 at 11:15
1

If you happen to be using the maven shade plugin to build a fat jar (rather than or in addition to using the assembly plugin), it's worth noting that the shade plugin handles entires in the MANIFEST.MF file a bit differently; see the shade plugin's executable jar page.

ryanbwork
  • 2,123
  • 12
  • 12
0

You probably need to add the maven-jar-plugin configuration too and configure the MainClass there also. The assembly unpacks all JAR files (e.g. project jar and dependency jars) and I think that the last MANIFEST.MF found in the list of JAR files "overwrites" the expected/generated manifest.mf.

mhaller
  • 14,122
  • 1
  • 42
  • 61