maven war plugin and custom Manifest file - java

I'd need Maven war plugin to use a custom MANIFEST.MF. As I read from the documentation you can put your MANIFEST.MF file in src/main/resources/META-INF/ and add the following configuration to your pom.xml file:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
However I see the MANIFEST.MF added in the WebRoot/META-INF is the default one. I can't find what is going wrong. Any suggestion or link to github projects where it does work ?
Thanks

First in your configuration you missed the <groupid>!
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
...
<configuration>
<archive>
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
And then be aware that only those entries of your own manifest are used which are not in the generated by the plugin!
The content of your own manifest file will be merged with the entries created by Maven Archiver. If you specify an entry in your own manifest file it will override the value created by Maven Archiver.
See the apache maven plugin page for entries of the default manifest, and configurable entries. Then you can add further own entries by providing a manifest using <manifestFile>
edit: If you want to use a 1:1 copy you could try to get this done my using the maven assembly plugin, but I think you can you do this with the normal mavne plugins.

Related

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:
build timestamp
buildnumber (from CI server)
groupId
artifactId
version
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?
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.

Get maven deploy plugin artifact version at runtime in my war

Is there anyway to get at runtime the full artifact version / build number generated by the maven deploy plugin of my war at runtime?
It'd be ok if the maven process generated and packaged up a properties file with the value.
Keep in mind that my project generates unique (timestamped) artifact versions for every deploy.
Try this:
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries/>
<addDefaultSpecificationEntries/>
</manifest>
</archive>
</configuration>
That will add the maven details from the pom that build the war into the MANIFEST.MF file, which you can read at runtime.
Another way that I occasionally use is to use filtering of properties files, and drop the pom values into there - useful if you already have a property file/config loading mechanism in place.
Then, when it's deployed, which uses the same values from the pom, you're fine.
-Chris
You could package it up in your Manifest file using maven-jar-plugin which can be read through you application wherever you need.
Here is the basic configuration which would write the properties in pom.xml to your Manifest file.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>false</addClasspath>
</manifest>
<manifestEntries>
<Implementation-Vendor>Vendor Name</Implementation-Vendor>
<Implementation-Version>${revision}</Implementation-Version>
<Build-Timestamp>${timestamp}</Build-Timestamp>
<Build-Number>${release}_${revision}</Build-Number>
</manifestEntries>
</archive>
</configuration>
<executions>
<!-- your jar executions here -->
</executions>
</plugin>
where your property values would be defined in pom.xml as :
<properties>
<timestamp>${maven.build.timestamp}</timestamp>
<release>DevelopmentBuild</release>
<revision>Some Value</revision>
<properties>
EDIT:
This can be done using maven-war-plugin also.
You can get more information on WAR Manifest Customization Here.

Maven Jar Builder: Could not find or load main class

I have been trying for several days now to create an executable jar file for my muli-module maven project. However, when I try to run this jar file I get "Could not find or load main class src.main.java.com.domain.Mainclass" (I have changed the name domain and MainClass for my company's privacy sake)
I have searched for days and none of the obvious tips seem to work.
My project has a main maven project that downloads all of the dependencies (packaging:POM)
and several module projects (Packaging:Jar).
Everything seems to work fine, and all of the files are compiled into class files, but somehow the main class is not being added to the pom.
My Pom File Plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-4</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.domain.project.MainClass</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
The Commands I Use: mvn clean package, then I cd into the target folder and do: java -jar jarfilename.jar
Any tips or help would be most welcomed!
Edit:
My current configuration creates a 2 jar files for every module:
projectname-jar-with-dependencies.jar
projectname.jar
When I navigate to the target folder of the module with my main class, I can successfully run the jar file. However, when I try to run the jar file of my parent maven project (the one with packageing:pom) I still get the same error. Does anyone know why the main jar file cannot find the main class?
Thanks!
You should not have src.main.java as part of the package name of your main class. It's just part of the default maven project folder structure convention. Your configuration should probably read:
<archive>
<manifest>
<mainClass>com.domain.project.MainClass</mainClass>
</manifest>
</archive>
I'm going to necro this post because it is important to have 3 different things set properly:
MainClass.java needs to be in <project_root>/src/main/java/com/domain/project/
Maven assembly plugin needs <mainClass>com.domain.project.MainClass</mainClass>
Your package should be set to com.domain.project
When those three match, Maven should package an executable JAR file.
it seems like you have one of the plugins missing. add the bellow to pom.xml file
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>yourclassnameKt</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
The plugin will add MANIFEST.mf file, which will tell the Java runtime which class to execute.
There is another issue that has the same problem ->
Kotlin + Maven assembling: no main manifest attribute
Reference: https://michaelrice.com/2016/08/hello-world-with-kotlin-and-maven/
I have a bit of a different but similar scenario so I thought I would share. I have a primary maven application packaged into a war through the build (pom.xml packaging configuration). I wanted to add a jar file that is created from one package within our source code, and added into the assembled output along with the webapp war. This allows us to deliver the web application along with a cli tool separately. I didn't want to reconfigure the pom.xml to be multi-module, but just to add a jar as a separate executable within our existing structure. I was banging my head against this for a while.
First, I ended up deleting my entire .m2 directory with maven repositories locally. It appears there may have been an issue for me here, because my ultimate code that worked seems to be the same as what wasn't working originally. I suspect the reasoning for this was I was trying different versions of libraries and was creating conflicts, but who knows. First suggestion I have if you are having issues is delete your .m2 folder and try from scratch.
Also reference #Adam Howell's answer because that is the fundamentals. I created a simplified example project to figure out why nothing was happening and in there I realized i forgot to prefix the folder structure as src/main/java... doh! Of course in my existing project, this was not the case.
And here is my plugin code i inserted in my pom.xml that worked:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.myCompany.app.cli.CLITool</mainClass>
</manifest>
</archive>
<outputDirectory>${project.build.directory}</outputDirectory>
<finalName>our-cli</finalName>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
I am pretty sure you can change the phase you want this done in, I figured earlier on in compile made since to ensure it was available for packaging later. I'm not very experienced with Maven though, so note that this may not be semantically in-line with Maven conventions.
And it worked! Not sure why this took me hours to work out although it did. This I just updated my bin.xml to include the jar file in my assembled deliverable, and Voilah! I have a jar executable separate from my webapp that I can use as a command-line interface tool.

Maven shade plugin adding dependency-reduced-pom.xml to base directory

The maven shade plugin is creating a file called dependency-reduced-pom.xml and also artifactname-shaded.jar and placing them in the base directory.
Is this a bug? Should be in the target directory. Any workaround?
You can avoid having it created by setting createDependencyReducedPom to false.
e.g.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>${maven-shade-plugin.version}</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
....
....
</plugin>
See more detail from apache
Based on bmargulies' answer and his comment on Xv.'s answer, I decided to configure the dependency-reduced POM to be output to target/, which is already ignored in my VCS.
To do that, I just added the dependencyReducedPomLocation element to the configuration element of the plugin, i.e.
<configuration>
<dependencyReducedPomLocation>${project.build.directory}/dependency-reduced-pom.xml</dependencyReducedPomLocation>
(...)
</configuration>
See https://issues.apache.org/jira/browse/MSHADE-121, and also https://issues.apache.org/jira/browse/MSHADE-124.
There is an option to move the d-r-p to elsewhere, but you may not like the consequences.
You are wrong about the -shaded jar, it always ends up in target/ unless you move it elsewhere.
You could use an old version of the plugin. Version 1.7 of the maven-shade-plugin writes to /target.
Since version 1.7.1, dependency-reduced pom.xml is written to basedir. See the issue MSHADE-124 for some reasons why it was done and what the consequences are. If you try setting dependencyReducedPomLocation, you will likely run into problems generating the site - open issue MSHADE-145.
the documentation on http://maven.apache.org/plugins/maven-shade-plugin/shade-mojo.html is incorrect when it says:
createDependencyReducedPom boolean - Flag whether to generate a
simplified POM for the shaded artifact. If set to true, dependencies
that have been included into the uber JAR will be removed from the
section of the generated POM. The reduced POM will be
named dependency-reduced-pom.xml and is stored into the same directory
as the shaded artifact. Unless you also specify
dependencyReducedPomLocation, the plugin will create a temporary file
named dependency-reduced-pom.xml in the project basedir. Default value
is: true.
the dependency-reduced-pom.xml is not stored in the same directory as the shaded artifact (target directory) ... it is in fact generated in the base directory, not target
To ignore the file you can add it to the ignore directive for your DVCS. For git, a .gitignore file is created with contents:
dependency-reduced-pom.xml
You can also add it to maven-clean-plugin configuration so it's blown away during the clean lifecycle phase: (Below assumes defaults, such as version, are defined in the POMs pluginManagement section.)
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<configuration>
<filesets>
<fileset>
<directory>.</directory>
<includes>
<include>**/dependency-reduced-pom.xml</include>
</includes>
<followSymlinks>false</followSymlinks>
</fileset>
</filesets>
</configuration>
</plugin>
</plugins>
</build>
Note that the above configuration is additive to the non-customized clean default.

How do I add an Implementation-Version value to a jar manifest using Maven's assembly plugin?

I'd like to add an Implementation-Version line to a manifest in my jar file that reflects the POM version number, using the maven assembly plugin.
Note that this is similar but different to another of my recent questions about the jar plugin.
Actually I'm a fool.. you do it in exactly the same way, i.e.
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
Silly question. Should have tried that first, really.

Categories

Resources