MaVeN build takes, most of the times, wrong file - java

I use the org.apache.maven.plugins maven-assembly-plugin version 2.2-beta-5 to build a jar-with-dependencies. One of the jars I include contains a persistence.xml file. The project that I build also has a persistence.xml file. The build finishes well.
The problem however is that most of the times the wrong persistence.xml file ends up in the jar-with-dependencies. If I, without changing anything, rebuild (and sometimes a few more times) then the correct persistence.xml is present.
I searched for a solution but I could not find a working example. How can I define in my pom.xml that I want my project's persistence.xml file in the jar-with-dependencies and not the one from the included jar?
My MaVeN version is Apache Maven 3.6.3 and all builds are done with mvn clean package.

Use maven-shade-plugin instead of mavenassembly-plugin to exclude the persistence.xml file from your dependencies
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>my:other:jar</artifact>
<excludes>
<exclude>persistence.xml</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
More info on this approach in the Apache Maven Shade Plugin documentation

Cannot comment about time taken to build the executable without looking into your project.
By default Maven copies files from your ${project.basedir}/src/main/resources location to the executable jar file. So If persistence.xml is not being included in fat jar then check your folder structure and check the location of your xml file.

Related

Unzip and re zip a file using Maven?

Question: is there any way in Maven (without resorting to an ant plugin) to unzip a file, cd into the directory, remove the file, and the rezip it, all as part of the build?
This is necessary as it is a complex build and also do not want to have to use gradle to accomplish this task.
The requirement of unzipping, removing file and zipping again can also be met in one single step by the truezip-maven-plugin and its remove goal which:
Remove a set of files from an existing archive.
The official examples also cover this scenario.
Given the following snippet:
<properties>
<archive>${project.basedir}/sample.zip</archive>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>truezip-maven-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<id>remove-a-file</id>
<goals>
<goal>remove</goal>
</goals>
<phase>package</phase>
<configuration>
<fileset>
<!-- note how the archive is treated as a normal file directory -->
<directory>${archive}</directory>
<includes>
<include>hello.txt</include>
</includes>
</fileset>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
And executing:
mvn clean package
The build will process the ${archive} file (in this case a sample.zip at the same level of the pom.xml file, that is, in the project.basedir directory) and remove from it the hello.txt file. Then rezip everything.
I just tested it successfully, you can even skip the properties section if not required. However, you should also carefully know that:
The zip file should not be under version control, otherwise it would create conflicts at each build
The behavior most probably should not be part of the default Maven build, hence good candidate for a Maven profile
the plugin replaces the original file, so if that was an issue you could firstly copy it to another location and then process it as above. To copy it, you could use the maven-resources-plugin and its copy-resources goal.

How maven jar project works when it is packaged to jar?

I am new to maven. I have created a maven project which will be packaged to JAR. I did clean package then jar is created. When i extracted the same jar, i could not see any dependencies (jars) i added in pom.xml inside the packaged jar. If i give this jar to third party clients how will the code work without any dependent jars ? Please help me how maven manages the jars?
Thanks!
Maven handles dependencies based on how you configure the dependency plugin.
See this reference for a simple example of how to do this.
In this example, the following code configures where your dependencies will end up:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>log4j</includeGroupIds>
<outputDirectory>${project.build.directory}/dependency-jars/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Then this code sets up the classpath for your main jar, which will allow anyone running it to find these dependencies
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.mkyong.core.App</mainClass>
<classpathPrefix>dependency-jars/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
Your other option would be to create a single jar, with all dependencies included, by following this example here
You could distribute the jar and the POM file if you want to try and provide your users with the files in that manner, but they'd need to be able to access your Maven repository where those dependencies are kept.
Core maven doesn't handle this. Maven is a build tool, its work is to build an artifact (a jar in your case). Dependencies you define in your module's pom.xml file are needed to get the code compiled. You'll need maven plugins to do so.
Now, you're asking not about the build, but the distribution of your compiled binaries.
If I understand it should be a lot of jars (your and your dependencies). Alternatively you may distribute the code as a jar + dependencies inside.
Example:
A first case:
If your code resides in module A (say, the code is in packages org.a.*) and depends on some thirdparty (say, log4j, whose classes reside in org.apache.log4j) than you can expect that you jar will only contain the classes of module a and you expect that the log4j will be added by the user of your module automatically (The first case).
A second case:
module a.jar will contain both org.a.* and org.apache.log4j.* classes, everything in the same module.
In general the first approach is more "healthy" and in this case you shouldn't do anything in maven. Maybe your distribution tool/documentation should contain this information.
If someone uses the module a in his/her code like a thirdparty (if you develop a framework or something) and if his/her project is mavenized, than the fact you've defined a dependency on log4j will make the maven to download the log4j as well as your a.jar (In maven notation, this is called "transitive dependencies").
If you're interested in the second case (this can be relevant if you define some "client application", like "jndi client for some server" for example) you might want to take a look on Maven shade plugin
Beware this can lead to dependency hell (what if the application that uses your client also makes use of log4j? what if the log4j-s are of different version)/
Bottom line, you probably want the first approach, think twice before you decide the second approach :)
One more tip, if you just want to download all the dependencies of your module "a" you might want to use maven dependency plugin - type the following in the command prompt
mvn dependency:copy-dependencies
and you'll find all the dependencies in target/dependencies folder
Hope this helps and happy mavening
The simplest solution to the problem is to use the maven-assembly-plugin which can create such jar with dependencies like the following:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>distro-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Afterwards you can distribute the created jar xyz-1.0-jar-with-dependencies which contains the defined dependencies.
If you need more control on how the resulting artifact is created or if some files needed to be overwritten etc. you might take a deeper look into maven-shade-plugin

maven: how to include annotation-generated .java files in the .jar

I have some java 7 annotation processors (for xtend) on my class-path. Via some annotations they create java files.
This works great, in Elipse and in the Maven build.
The generated files end up in target/generated-sources/annotations as expected.
The corresponding generated .class files also end up where expected and are thus part of the final jar file.
Since I need to also include all java source files in my .jar file (there should be only one .jar file with the sources and classes) for GWT,
I have specified src/main/java as a resources dir (so that Maven copies the files to the classes dir and they end up in the jar file).
the trick with the resources directory does not really work for my generated files, because Maven will first copy all resources and then start the compilation (which in turn will generate the .java files via the annotation processors).
How can I tell Maven to copy also include the generated .java files in the .jar?
You can bind the maven-resources-plugin to the prepare-package phase to achieve copying annotation sources before packaging proper:
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-annotations</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>target/generated-sources/annotations</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
I hope that helps.
Cheers,

Does maven have an ability to pack single *.dll to jar without any sources?

I'd like to add *.dlls as third party libs to my repository and during packaging process just pack them to *.jar, sign them and copy to some specific folder.
Signing and coping are well done and work correctly (as expected by using maven-dependency-plugin and maven-jarsigner-plugin). But I didn't find any method to automatically pack single dll to jar (without any sources like maven-assembly-plugin does).
Solution that I see by the time: add to my repository not a "pure" dll, but already packed to jar lib (packed by myself)... but it's not a good idea, I guess)
It sounds like you've successfully retrieved your .dll (with dependency plugin) and signed it (jarsigner plugin), and it's somewhere in your ${project.build.directory} (which defaults to target).
If that's correct, give this a try:
Define the packaging of your project as jar
Retrieve dlls
Make sure the jarsigner:sign goal is bound to the prepare-package phase. It binds to package by default and we need to ensure jarsigner:sign runs before jar:jar.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jarsigner-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<id>sign</id>
<phase>prepare-package</phase> <!-- important -->
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
Configure the jar plugin to include the signed dll(s)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<!-- using this ID merges this config with default -->
<!-- So it should not be necessary to specify phase or goals -->
<!-- Change classes directory because it will look in target/classes
by default and that probably isn't where your dlls are. If
the dlls are in target then directoryContainingSignedDlls is
simply ${project.build.directory}. -->
<id>default-jar</id>
<configuration>
<classesDirectory>directoryContainingSignedDlls</classesDirectory>
<includes>
<include>**/*.dll</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
Now, running mvn clean package should give you a jar containing your signed dlls.
If JACOB requires manifest config there are docs explaining how to do this.
Good luck!
I would recommend to pack your dll's as a zip archive via maven-assembly-plugin and let that module deploy the zip archive as attached to your usual pom. The packaging of that project should be pom instead of default.
I would be a little bit confused if i download a jar and find dll's inside it,
but if you prefer you could create jar via the maven-assembly-plugin or use the maven-jar-plugin.

Is it best to Mavenize your project jar files or put them in WEB-INF/lib?

I've been doing this for all of the jar files that my Spring MVC project needs:
call mvn install:install-file -DgroupId=vegetables -DartifactId=potatoes -Dversion=1.0 -Dfile=vegetables-1.0.jar -Dpackaging=jar -DgeneratePom=true
Recently I must have exceeded some limit on how many dependencies you can list in your pom.xml file because I got an error that said:
Your command line is too long
So I removed some dependencies from the pom.xml that my project no longer uses and I was able to run the project with maven again.
My question is, should I put install all jar files into my Maven repository as I have been doing so far? Or should I put some of them into the WEB-INF/lib directory?
What's the best practice here?
I've been doing the same that you do with the command line, but by configuring maven-install-plugin in my POM (please read the note at the end):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<executions>
<execution>
<id>install-vegetables</id>
<phase>initialize</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${project.basedir}/lib/vegetables-1.0.jar</file>
<groupId>vegetables</groupId>
<artifactId>potatoes</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
</configuration>
</execution>
<execution>
<id>install-minerals</id>
<phase>initialize</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${project.basedir}/lib/minerals-1.0.jar</file>
<groupId>minerals</groupId>
<artifactId>rocks</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
</configuration>
</execution>
</executions>
</plugin>
It is much less efficient, because files get installed over and over, but it is much less annoying than making it manually. Anyway, I think you should give it a try.
All your dependencies should reside under the local repository. According to the Maven convention/best practices, you should not keep jar files in your project.
Convert your project to a fully war based Maven project. This will place all your dependencies (jar files) under your webapp's WEB-INF/lib directory. Thus you will not have to worry about long paths.
You just need to add the dependencies in your pom.xml file, no need to install them manually. Maven will download the libraries and put it in your local repository whenever needed. Only if you want to use third party(custom) libraries, you may go for installing it in your local repository.

Categories