When building an ear through the Maven ear plugin, I experienced that applying package
without clean
can lead to inconsistent results: If I change the version of a dependency, the dependency now appears twice in the ear, in the old and the new version. If I build the ear without version numbers in the jar names, I get just one jar, but old versions are not replaced properly.
I looked at the source code
http://svn.apache.org/viewvc/maven/plugins/tags/maven-ear-plugin-2.10.1/src/main/java/org/apache/maven/plugin/ear/EarMojo.java?view=markup
Especially the lines from 436 are interesting: There checks whether to update files in target, but apparently only checks for the absolute path and the lastmodified date.
Summarized: Am I right that changing the dependencies (or their versions) always requires to call clean
before the build? Or is there some intelligence in package
which I missed?
Yes... most of the time you should call clean
when changing your dependencies or any other build configuration, otherwise previous build elements may collide with a new build (as seems to be your case here). Generally speaking, to make sure previous build elements won't collide with a new build you should call clean
before-hand - configuration changes or not.
But there are exceptions: if you know for sure that previous build elements won't impact your new build, you can skip clean
. However most of the time you cannot know, or skipping clean
is simply not possible without causing such collisions. I explain in details below.
When you build your project with Maven, it will generate files and other elements under the ${project.build.directory}
folder (target
by default). These elements are then used to create your artifact (EAR in your case) during the package
phase.
Without calling clean
after a build, all the elements under target
will still be there during the next build and may impact it. How can Maven plugins tell the difference and know which elements are from old builds or new ones? Files timestamp are obviously not sufficient, and unless using some obscur mechanism to identify which files are from which build, it is hard to do.
If I change the version of a dependency, the dependency now appears twice in the ear, in the old and the new version.
That's probably because your build copy dependencies under target
and your packaging plugin will include an entire directory into the generated artifact (in your case, the EAR). For example, if you run your build twice with different version:
mydep-1.0.jar
is generated in target/classes/mydep
and your plugin includes all files from target/classes/mydep
into the EAR. Everything's fine. mydep-2.0.jar
is generated but mydep-1.0.jar
is still in target/classes/mydep
. The entire target/classes/mydep
directory is included and both versions end-up in the EAR. If I build the ear without version numbers in the jar names, I get just one jar, but old versions are not replaced properly.
That's because some plugins - for optimization - won't re-compile or re-do actions if they see the results already exists. In your case, as you pointed out, the EAR plugin probably keeps the "old" version of the file because it already exists, where in fact a more recent version with the same name should replace it. That's probably because you did not specify a version:
mydep-0.1.jar
existed and a new mydep-0.2.jar
was created but both were included in your EARmydep.jar
which is not overriden by the most recent version because "it already exists", thus the "old" file stay in place and get included in the EAR. Conclusion: Maven plugins are not able to differentiate with a 100% certainty if an element is from a previous build or a new one. When you are updating your build configuration, you should always call clean
to ensure there won't be a collision between old and new build elements. Even without build configuration changes, it may be necessary to call clean
- but that's another matter.
I would recommend to always call clean
when running a build, unless no collision is possible and it provides a real value such as a time gain because rebuilding the entire project is too long or other reasons justifying it.
EDIT: as per @JF Meier request for sources, the Running Maven guide provides advice as per the clean
goal and the related inconsistency risks:
Inconsistent output
Most plugins are optimized to know if they have to execute their task. In some cases the output can be polluted from a previous build and the end result is not what you expected. In such rare situations you can call the
clean
phase which means: remove the output directory. You can also call it asmvn clean verify
which means: first clean up the output directory, next build the project and verify the outcome.
See if the issue persists by compiling the latest version of maven-ear-plugin (3.0.0, more recent than 2.10.2, itself more recent than the official 2.12.1)
As you can see in the latest code EarMojo.java
, the function copyModules()
has changed from the 2.10.1 implementation, and might be more robust.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With