Difference between projectHelper.attachArtifact and project.getArtifact().setFile - maven

I'm currently facing an issue with the execution of my MUnit tests using the command line.
I'm facing a problem of "duplicate project artifact assignment" Using version 1.2 of mule-domain-maven-plugin that was fixed here with version 1.3. Removing this line of code causes FileNotFoundException on mule-domain-config.xml when running my MUnit.
After decompiling the code, I can see that 1.2 (which works with my MUnits), has 2 lines of code :
this.projectHelper.attachArtifact(this.project, "zip", domain);
this.project.getArtifact().setFile(domain);
I can see that 1.3 has only this line :
this.projectHelper.attachArtifact(this.project, "zip", domain);
Does anybody know the difference between this.projectHelper.attachArtifact(this.project, "zip", domain); and this.project.getArtifact().setFile(domain); and how to resolve this issue?

The difference is the same as the difference between the main artifact and attached artifacts.
First of all, an artifact is, put simply, an object containing the Maven coordinates pointing to it (group id / artifact id / version / classifier / type), a repository where to resolve it or where it was resolved, and a file, which is the actual concrete file to use / download / upload.
Except for POM projects, a Maven project generates a single main artifact. It depends on its packaging; for example a project with a packaging of jar will create a main JAR artifact whose file contains all the classes of your project, and a project with a packaging of war will create the web application. Furthermore, the project itself is tied to its POM file; this means that a project, not only has a file for its main artifact, but also has reference to the POM file that created it. It is only for projects of packaging pom that no main artifact will be created; this is because such projects are parent or aggregator projects, containing build logic to be shared between multiple projects, but they do not produce a main deliverable.
In addition to this, a project has attached, or secondary, artifacts. They correspond to additional artifacts that are also generated during the build of a project, and differ from the main one by their classifier and/or type, and, naturally, their actual file. Those additional artifacts are installed and deployed alongside the main one. As an example, a typical project of packaging jar would also generate its Javadoc and Sources as a JAR file as attached artifacts having the classifier javadoc and sources. It follows that a project of packaging pom can only have attached artifacts, since it has no main artifact. Finally, it is perfectly allowed to have a project without attached artifacts; only the main one (or none at all in case of a pom project) would get deployed.
Inside a Maven plugin, all those considerations comes down to the following:
The main artifact of a project is retrieved with project.getArtifact(), as an Artifact.
project.getArtifact().setFile(...) sets the actual file of the main artifact of the project. Again, for a project of packaging jar, this would be the actual JAR file that was generated on-disk. Concrete example: it is what the Maven JAR plugin does.
The MavenProjectHelper component is used to attach artifacts to the project. projectHelper.attachArtifact(project, "zip", file); would attach an artifact of type ZIP to the given project, with no classifier, and whose file is the given file. There is an overload to attach an artifact with a classifier. Concrete example: it is what the Maven Assembly Plugin does when it is configured to attach the artifacts it produces.
project.setFile(file) sets the POM file of the Maven project that created it.
To give examples, we can consider the artifacts deployed under org.mule.tools.maven in Central. Under the artifact id mule-maven-plugin, there are multiple files:
mule-maven-plugin-2.1.jar is the main artifact file,
which was created by the POM file mule-maven-plugin-2.1.pom,
while mule-maven-plugin-2.1-javadoc.jar and mule-maven-plugin-2.1-sources.jar are attached with their respective classifier.
As second example, consider the artifact id mule-esb-maven-tools. The only file deployed (except for the hash files) is mule-esb-maven-tools-1.1.pom. This is perfectly normal since it's a POM project, so it has no main artifact (there are no JARs or other deployed); there's only the POM file of the project, with no attached artifacts.

Related

Converting one module to standalone Maven project, including a minimal working POM

I would like to distribute the main artifact sources (main Java and tests) of a multi module project as a simple - standalone - Maven project.
The easy parts of this can be implemented using the maven-source-plugin. This also is able to include the POM in the generated source code jar. However, this is the artefact POM, which refers to the parent POM which is not included in the jar.
Other than creating the POM manually, is there a way to generate a minimal POM which contains the dependencies (extracted from the artifact POM and its parent)?
If you create the POM with the flatten-maven-plugin, all parent relations are resolved and you get an equivalent POM without the unnecessary parts.
https://www.mojohaus.org/flatten-maven-plugin/

Understanding Java Artifacts and Maven

I am trying to understand relationship between artifact, group, class definitions.
For example, I've seen the following artifact declaration:
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.53.0</version>
Is there a file associated with this artifact?
Is this enough information to pull down the file down when building your Maven Project?
Where is it getting the file from? Is it getting it from selenium, or does Maven house these artifacts, and it is getting from Maven?
Where exactly is it downloading the artifact from?
What's in the artifact file? Class definitions? Multiple classes can be defined in there, right?
Maven seems to be making a jar file. Is it compounding all the classes into that file?
Also, how is artifact file different from JAR file and can you make your own artifact file?
Is there a file associated with this artifact?
Yes, what you have posted is known as a coordinate. It references a jar named selenium-java that is in the group org.seleniumhq.selenium.
Groups, identified by the groupId component of the coordinate, are a way of namespacing artifacts within maven to prevent naming collisions.
This coordinate says that the project has a dependency on version 2.53.0 of a maven artifact named selenium-java in the group org.seleniumhq.selenium.
Is this enough information to pull down the file down when building your Maven Project?
Yes, the coordinate is how the artifact is located within the maven repository and is enough information to locate and download the artifact when building a maven project.
Where is it getting the file from? Is it getting it from selenium, or does Maven house these artifacts, and it is getting from Maven?
Where exactly is it downloading the artifact from?
Where the file is retrieved from is based on your maven configuration. By default maven will first check the local maven repository on your machine to see if the artifact has already been downloaded. If not, it will then check Maven Central.
You can also host your own maven repositories using tools such as Nexus or Artifactory that can mirror repositories on the internet such as Maven Central as well as store artifacts you create yourself that you do not with to share with others.
What's in the artifact file? Class definitions? Multiple classes can be defined in there, right?
An artifact can be any type of file. In the case of the selenium coordinate above the artifact is a jar file. There will also be a pom file associated with that coordinate that explains all of the dependencies of the selenium-java jar.
http://search.maven.org/#artifactdetails%7Corg.seleniumhq.selenium%7Cselenium-java%7C2.53.0%7Cjar
Maven seems to be making a jar file. Is it compounding all the classes into that file?
You can build normal jars or fat jars with maven. By default maven will build a normal jar. If you wish to package all of a jars dependencies within it (i.e. fat jar) you need to use a special maven plugin.
http://maven.apache.org/plugins/maven-shade-plugin/
Also, how is artifact file different from JAR file and can you make your own artifact file?
Artifact is a generic term used to describe anything you can store within a maven repository. Maven repositories can store many different types of files. In the case of this coordinate the artifact is a jar file.

What is the necessity of declaring <packaging> in Maven POM file?

I made a Maven project and declared packaging as war.
<packaging>war</packaging>
But this returned an error,
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-assembly-plugin:2.2-beta-5:single (make-assembly) on project WaterDealer: Execution make-assembly of goal org.apache.maven.plugins:maven-assembly-plugin:2.2-beta-5:single failed: For artifact {ArtifactName:ArtifactName:0.0.1-SNAPSHOT:war}: An attached artifact must have a different ID than its corresponding main artifact.
But when I removed packaging declaration, everything worked just as expected.
Is there any specific reason for this happening? Why did declaring packaging type return an error An attached artifasct must have a different ID than its corresponding main artifact. ? How are they related?
I went through POM reference from this link Maven POM reference but did not find the information very useful.
the error is from the assembly plugin which is not directly related to the packaging.
the packaging defines the type of artifact produced by maven (in general: one pom.xml one artifact - there are exceptions to this rule, e.x. sources jars or javadocs).
the default is "jar". so if you do not specify anything maven will create a jar file.
The other available values for packaging should be a bit self explaining?
The error might be simply the name that results. So packaging jar will create a jar file, "war" will create a war file and so on. If your assembly plugin creates a war file that may conflict with the war created through the pom.xml
The packaging defines some of the binding which are done. This means if you decide to use packaging war it means to run maven-war-plugin in the package phase. This can be read in the appropriate documentation.
The question is why you using maven-assembly-plugin in a war module and apart from that why using such an old version. Take a look on this site which shows the uptodate versions of the plugins:
http://maven.apache.org/plugins/

How to include dependency files in maven assembly

I have a maven project which is configured (via the use of pom.xml and assembly.xml) to package a zip file containing both the compiled webapp (war file) and all files under src/main/folder alongside it whenever we run mvn clean package assembly:single.
This project imports/uses another maven project (which becomes a jar file) and that project in turn also imports/uses a third maven project (again a jar file).
The third project also contains some files inside src/main/folder as well which I'd like to be placed alongside the other files in the zip file whenever I build the main project (the one on top of the chain that becomes a war file).
Is it possible somehow to tell maven to include all files in a specific folder inside all it's dependencies (Or in one specific dependency) alongside in the zip file?
Start here: Maven: The Complete Reference - 8.5. Controlling the Contents of an Assembly
Note that if you deploy a Maven project with assembly:assembly (which you really should configure as a <build> plugin, not use on the command line), the assemblies get "attached" to the project and installed in the repository. You can then reach them using the Maven dependency notation, i.e. mygroup:myartifact:extrafiles:zip
I've found the Assembly descriptor <dependencySets> cumbersome to configure. They really are for the simple case (including the JAR files your application needs at runtime).
Here is the general approach I would take for your desired outcome:
Use Maven Dependency Plugin dependency:copy to download the specific files from the other projects, placing them under a sub-directory of target/
Configure your assembly descriptor to add those downloaded/extracted files to your final assembly artifact.
Alternatively, hack something together using Maven Ant Run Plugin.
You will need to produce an additional assembly from the third project to package up the extra files. Append the assembly id so it produces a package named something like third-1.0.0-extrafiles.zip
Then add this as a dependency of your first project using <type>extrafiles</type> in the dependency descriptor. In the assembly for the first project you'll have to tell it to "unpack" the dependencies of this type (so you don't get a zip in a zip)

tycho plugin + maven-dependency-plugin: copy dependencies from local projects instead repositories

Main Goal: deploy a project as jar and eclipse-plugin
current state: project builds fine as jar package
Now i want to create a second project which wraps the jar project as eclipse plugin
use tycho-maven-plugin to create eclipse-plugin
add the jar of the original project (with copy-dependency)
add an Activator
export packages from jar
create correct MANIFEST.MF
i tried to copy the jar with copy-dependencies bound to create-resources. This works as long the jar is found in repository, but the local project gets ignored.
This results in a build failure since the jar is not found.
Is it possible to tell copy-dependencies to take the jar from the target directory of the project? Or should i use some other method than using tycho?
Edit:
I solved my problem with 4 projects:
normal project (nothing special here)
the wrapper project using tycho maven and copy-dependencies.
bound copy dependencies to some goal before compile (e.g. generate-resources). Excluded all artefactid which were set as dependency in the MANIFEST.MF.
a prepare project, which calls the normal project and installs it into the repo. This is needed because the tycho-maven-plugin is bound to validate and it is not possible to call the exec plugin beforehand (at least not easy).
a multi module project which calls the prepare project before the wrapper project.
Build your local project (which artifact was missed) with "mvm install". It will be deployed in your local repository ($USER_HOME$/.m2/repositories). After this dependency should be resolved.
Alternatively you can "mvn deploy" if you have local company maven repository like Artifactory or Nexus.

Resources