I'm creating some Maven artifacts for various dependencies for our projects, and while I'm taking my best guess at group / artifact IDs, I'd like to add something to flag them as "unofficial" and created by us for compilation, so that should we find official sources for the same thing in the future there's no confusion and we can simply change to point to the identifiers. Is there a best/common/reccomended practice for doing so?
I was just thinking something like setting groupId="org.providername.unofficial", but since Maven's all about "doing it our way" I just want to see if there's a precedent for something different already...
Maven coordinates to uniquely identify any artifact include groupId, artifactId and version. So, changing any of those would allow you to differentiate your artifact from other one. However if you want to be able to use your version instead of a standard artifact as one of the dependencies of some other component you would have to keep the same groupId and artifactId, or else you'd have to deal with excludes in that dependency. So, for that is would be the best to change just version, e.g. add some qualifier like 1.0mycompayname.
Is there a best/common/recommended practice for doing so?
To my knowledge, there is no official recommended practice for this (since the artifacts are non public after all) but I find that using a flag is a good idea that we also use (with an "internal" qualifier) and we also put such artifacts in a special "third-party" group of our repository manager.
Related
I am trying to set conflict managers in Ivy, but I can't find a concrete example of how to set them. For example, to set the "strict" manager, what would this look like?
<conflict-managers>
???
</conflict-managers>
<rant>
Yeah, isn't Ivy documentation a hoot! I mean, does it have to be well organized and complete? Does it really have to make sense. I mean, it's not like my job depends upon it!
Wait a second, it does...
</rant>
Sorry, I have to get the state of Ivy documentation off my chest. It makes Maven documentation look wonderful in comparison.
The best book on Ivy I've found is Manning's Ant in Action. It's a seven year old book that's out of print (but is still available as an ebook. If it wasn't for this book, (which is using Ivy 1.4), I would have been completely lost. Unfortunately, it doesn't delve deep into the Ivy settings.
There is a listing of all of the possible conflict managers buried deep in the Ivy documentation.
all this conflicts manager resolve conflicts by selecting all revisions. Also called the NoConflictManager, it doesn't evict any modules.
latest-time this conflict manager selects only the 'latest' revision, latest being defined as the latest in time. Note that latest in time is costly to compute, so prefer latest-revision if you can.
latest-revision this conflict manager selects only the 'latest' revision, latest being defined by a string comparison of revisions.
latest-compatible this conflict manager selects the latest version in the conflicts which can result in a compatible set of dependencies. This means that in the end, this conflict manager does not allow any conflicts (similar to the strict conflict manager), except that it follows a best effort strategy to try to find a set of compatible modules (according to the version constraints)
strict this conflict manager throws an exception (i.e. causes a build failure) whenever a conflict is found.
I haven't played around with them, but I believe you simply do the following in the ivy-settings.xml:
<conflict-managers>
<latest-revision/>
</conflict-managers>
You can also define conflict management in your ivy.xml too which might be a bit more practical since it can be defined on a module-by-module basis.
Of course a few examples would have gone a long way with this, but the Ivy documentation doesn't provide many.
The best book on Ivy I've found is Manning's Ant in Action.
That was me. Ivy has moved on a lot since then, and so have builds
One issue with the ivy conflict managers is that it differs from maven, whose policy is "shallowest on the graph first", that picks the closest one. This is good if you explicitly ask for a version, bad if you have >1 transitive dependency when "closest" isn't what you want.
With ivy you can hit the strict resolve which says "you have to explicitly resolve every single conflict in your dependencies". This adds extra work # build time, but has a key result: if you explicitly declare the versions of things you want, you are now in control of what you have in your classpath.
The Ivy reference documentation strictly follows the XML tag structure of the ivy.xml and ivy-settings.xml files. You are expected to extract the information required directly from the document structure.
Decoding from the Ivy docs:
The conflict-managers tag is for declaring what conflict managers a project may use and configuring them if they accept configuration, not for setting the conflict manager to use.
<conflict-managers>
<latest-cm name="mylatest-conflict-manager" latest="my-latest-strategy"/>
<compatible-cm name="my-latest-compatible-conflict-manager" latest="my-latest-strategy"/>
</conflict-managers>
The settings tag has an attribute for choosing the default conflict manager:
<settings defaultConflictManager="strict"/>
Or in an ivy.xml:
<dependencies>
<dependency.../>
<conflict manager="strict">
</dependencies>
Note that most of the conflict managers are more liberal in their interpretation of your intentions than you would expect. Two examples:
* Branches are considered irrelevant, if a dependency is available on two branches the "latest" family of resolvers will pick the latest available from either.
* Both the "latest-time" and "latest-revision" resolvers ignore version constraints except to set boundaries on the matching space. e.g. if a depends on b-1.0 and c-1.0 but c-1.0 depends on b-5.0 then you will get b-5.0 despite it not meeting the constraint requested.
I assume your need is result of discovering one of these design flaws.
We are currently attempting to port a very (very) large project built with ant to maven (while also moving to svn). All possibilities are being explored in remodeling the project structure to best fit the maven paradigm.
Now to be more specific, I have come across classifiers and would like to know how I could use them to my advantage, while refraining from "classifier anti-patterns".
Thanks
from: http://maven.apache.org/pom.html
classifier: You may occasionally find a fifth element on the
coordinate, and that is the classifier. We will visit the classifier
later, but for now it suffices to know that those kinds of projects
are displayed as groupId:artifactId:packaging:classifier:version.
and
The classifier allows to distinguish artifacts that were built from
the same POM but differ in their content. It is some optional and
arbitrary string that - if present - is appended to the artifact name
just after the version number. As a motivation for this element,
consider for example a project that offers an artifact targeting JRE
1.5 but at the same time also an artifact that still supports JRE 1.4. The first artifact could be equipped with the classifier jdk15 and the
second one with jdk14 such that clients can choose which one to use.
Another common use case for classifiers is the need to attach
secondary artifacts to the project's main artifact. If you browse the
Maven central repository, you will notice that the classifiers sources
and javadoc are used to deploy the project source code and API docs
along with the packaged class files.
I think the correct question would be How to use or abuse attached artifacts maven? Because basicaly that is why classifiers are introduced - to allow you to publish attached artifacts.
Well, Maven projects often implicitely use attached artifacts, e.g. by using maven-javadoc-plugin or maven-source-plugin. maven-javadoc-plugin publishes attached artifact that contains generated documentation by using a javadoc classifier, and maven-source-plugin publishes sources by using sources classifier.
Now what about explicit usage of attached artifacts? I use attached artifacts to publish harness shell scripts (start.sh and Co). It's also a good idea to publish SQL scripts in the attached artifact with a classifier sql or something like that.
How can you attach an arbitary artifact with your classifier? - this can be done with build-helper-maven-plugin.
... I would like to know how I could use them to my advantage ...
Don't use them. They are optional and arbitrary.
If you are in the middle of porting a project over to maven, keep things simple and only do what is necessary (at first) to get everything working as you'd like. Then, after things are working like you want, you can explore more advanced features of maven to do cool stuff.
This answer is based on your question sounding like a "This features sounds neat, how can I use it even though I don't have a need for it?" kind of question. If you have a need for this feature, please update your question with more information on how you were thinking of utilizing the classifier feature and we will all be more informed to help you.
In contrast to Jesse Web's answer, it is good to learn about classifiers so that you can leverage them and avoid having to refactor code in addition to porting to maven. We went through the same process a year or two ago. Previously we had everything in one code base and built together with ant. In migrating to maven, we also found the need to break out the various components into their own maven projects. Some of these projects were really libraries, but had some web resources (jsp, js, images, etc.). The end result was us creating an attached artifact (as mentioned by #Male) with the web resources, using the classifier "web-resources" and the type "war" (to use as an overlay). This was then, and still does after understanding maven better, the best solution to port an old, coupled, project. We are eventually wanting to separate out these web resources since they don't belong in this library, but at least it can be done as a separate task.
In general, you want to avoid having attached artifacts. This is typically a sign that a separate project should be created to build that artifact. I suggest looking at doing this anytime you are tempted to attach an artifact with a separate classifier.
I use classifiers to define supporting artefacts to the main artefact.
For example I have com.bar|foo-1.0.war and have some associated config called com.bar|foo-1.0-properties.zip
You can use classifers when you have different versions of the same artifact that you want to deploy to your repository.
Here's a use case:
I use them in conjunction with properties in a pom. The pom has default values which can be overriden via the command line. Running without options uses the default property value. If I build a version of the artifact with different property values, I can deploy that to the repo with a classifier.
For example, the command:
mvn -DmyProperty=specialValue package install:install-file -Dfile=target/my-ear.ear -DpomFile=my-ear/pom.xml -Dclassifier=specialVersion
Builds a version of an ear artifact with special properties and deploys the artifact to my repo with a classifier "specialVersion".
So, my repo can have my-ear-1.0.0.ear and my-ear-1.0.0-specialVersion.ear.
I'm currently in the process of moving some project from Ant to Maven. Conformist as I am, I want to use well-established conventions for finding groupId and artifactId, but I can't find any detailed conventions (there are some, but they don't cover the points I'm wondering about).
Take this project for instance, first the Java package: com.mycompany.teatimer
Tea timer is actually two words, but the Java package naming conventions forbid the insertion of underscores or hyphens, so I'm writing it all together.
I chose the groupId identical to the package ID because I think that's a good idea. Is it?
Finally, I have to pick an artifactId, I currently went for teatimer. But when I look at other Maven projects, they use hyphens to split words in artifactIds, like this: tea-timer. But it does look weird when concatenated to the groupId: com.mycompany.teatimer.tea-timer.
How would you do this?
Another example:
Package name: com.mycompany.awesomeinhouseframework
groupId: com.mycompany.awesomeinhouseframework (?)
artifactId: awesome-inhouse-framework (?)
Weirdness is highly subjective, I just suggest to follow the official recommendation:
Guide to naming conventions on groupId, artifactId and version
groupId will identify your project uniquely across all projects,
so we need to enforce a naming schema.
It has to follow the package name
rules, what means that has to be at
least as a domain name you control,
and you can create as many subgroups
as you want. Look at More information
about package names.
eg. org.apache.maven, org.apache.commons
A good way to determine the granularity of the groupId is to use
the project structure. That is, if the
current project is a multiple module
project, it should append a new
identifier to the parent's groupId.
eg. org.apache.maven, org.apache.maven.plugins,
org.apache.maven.reporting
artifactId is the name of the jar without version. If you created it
then you can choose whatever name you
want with lowercase letters and no
strange symbols. If it's a third party
jar you have to take the name of the
jar as it's distributed.
eg. maven, commons-math
version if you distribute it then you can choose any typical
version with numbers and dots (1.0,
1.1, 1.0.1, ...). Don't use dates as they are usually associated with
SNAPSHOT (nightly) builds. If it's a
third party artifact, you have to use
their version number whatever it is,
and as strange as it can look.
eg. 2.0, 2.0.1, 1.3.1
Your convention seems to be reasonable. If I were searching for your framework in the Maven repo, I would look for awesome-inhouse-framework-x.y.jar in com.mycompany.awesomeinhouseframework group directory. And I would find it there according to your convention.
Two simple rules work for me:
reverse-domain-packages for groupId (since such are quite unique) with all the constrains regarding Java packages names
project name as artifactId (keeping in mind that it should be jar-name friendly i.e. not contain characters that maybe invalid for a file name or just look weird)
Consider the following for building a basic first Maven application:
groupId
com.companyname
artifactId
project
version
0.0.1
However, I disagree the official definition of Guide to naming conventions on groupId, artifactId, and version which proposes the groupId must start with a reversed domain name you control.
com means this project belongs to a company, and org means this project belongs to a social organization. These are alright, but for those strange domain like xxx.tv, xxx.uk, xxx.cn, it does not make sense to name the groupId started with "tv.","cn.", the groupId should deliver the basic information of the project rather than the domain.
I wonder what is the Maven way in my situation.
My application has a bunch of configuration files, let's call them profiles. Each profile configuration file is a *.properties file, that contains keys/values and some comments on these keys/values semantics. The idea is to generate these *.properties to have unified comments in all of them.
My plan is to create a template.properties file that contains something like
#Comments for key1/value1
key1=${key1.value}
#Comments for key2/value2
key2=${key2.value}
and a bunch of files like
#profile_data_1.properties
key1.value=profile_1_key_1_value
key2.value=profile_1_key_2_value
#profile_data_2.properties
key1.value=profile_2_key_1_value
key2.value=profile_2_key_2_value
Then bind to generate-resources phase to create a copy of template.properties per profile_data_, and filter that copy with profile_data_.properties as a filter.
The easiest way is probably to create an ant build file and use antrun plugin. But that is not a Maven way, is it?
Other option is to create a Maven plugin for that tiny task. Somehow, I don't like that idea (plugin deployment is not what I want very much).
Maven does offer filtering of resources that you can combine with Maven profiles (see for example this post) but I'm not sure this will help here. If I understand your needs correctly, you need to loop on a set of input files and to change the name of the output file. And while the first part would be maybe possible using several <execution>, I don't think the second part is doable with the resources plugin.
So if you want to do this in one build, the easiest way would be indeed to use the Maven AntRun plugin and to implement the loop and the processing logic with Ant tasks.
And unless you need to reuse this at several places, I wouldn't encapsulate this logic in a Maven plugin, this would give you much benefits if this is done in a single project, in a unique location.
You can extend the way maven does it's filtering, as maven retrieves it's filtering strategy from the plexus container via dependency injection. So you would have to register a new default strategy. This is heavy stuff and badly documented, but I think it can be done.
Use these URLs as starting point:
http://maven.apache.org/shared/maven-filtering/usage.html
and
http://maven.apache.org/plugins/maven-resources-plugin/
Sean
If you are developing a large evolving multi module maven project it seems inevitable that there are some dependencies given in the poms that are unneccesary, since they are transitively included by other dependencies. For example this happens if you have a module A that originally includes C. Later you refactor and have A depend on a module B which in turn depends on C. If you are not careful enough you'll wind up with both B and C in A's dependency list. But of course you do not need to put C into A's pom, since it is included transitively, anyway. Is there tool to find such unneccesary dependencies?
(These dependencies do not actually hurt, but they might obscure your actual module structure and having less stuff in the pom is usually better. :-)
To some extent you can use dependency:analyze, but it's not too helpful. Also check JBoss Tattletale.
Some time ago I've started a maven-storyteller-plugin to be able to deeper analyze the poms, but the project is very far from production/public use. You can use the storyteller:recount goal to analyze the unused/redundant dependencies.
The problem with the whole story is - how to determine "unused" things. What is quite possible to analyze is for instance class references. But it won't work if you're using reflection - directly or non-directly.
Update November 2014.
I've just moved my old code of the Storyteller plugin to GitHub. I'll refresh it and release to the central so that it's usable for others.
I
personaly use the pom editor of M2Eclipse to visually view the dependency tree (2D tree). Then I give a look in my deliverable (war, ear) lib directories. Then still in M2Eclipse pom dependencies viewer I go to every 3rd party, and right click on the dependency I want to exclude (an exclusion is added automatically in the right dependency).
There is no golden rules, simply some basic tips:
a lot of pom are not correct: a lot of 3rd party libs out there require way too much dependencies in the default compile scope, if everybody carefully craft their pom, you must not have so much unwanted dependencies.
you need to guess by the name of dependencies what you will have to exclude, best example are parsers, transformer, documentbuilder: xalan, xerces, xalan alfred and co. try to remove them and use the internal jdk1.6 parser, common apache stuff, log4j is also worth looking at.
look also regularly in lib delivery if you do not have duplicate libraries with different version (the dependency resolver of maven should avoid that)
go bottom up, start with your common modules, then go up till the service layer, trimming down dependencies in every module, dont try to start in modules ear/war, it will be too difficult
check often if your deliverable are still working, by either testing or comparing and old deliverable with the new one (especially in web-inf/lib directory what has disappeared with winmerge/beyoncompare)
When you have A -> B, B -> C, and then refactor such that A -> (B, C). IF it is the case that A still compiles against B, you very much don't want to simply pick up the dependency because you receive it transitively.
Think of the case when A -> (B-1.0, C-1.0), B-1.0 -> C-1.0. Everything's in sync, so to avoid "duplication" you remove C from A's dependency. Then you upgrade A to use B-2.0 -> C-2.0. You begin to see errors because A wants C-1.0 classes but found C-2.0 classes. While quickly reconcilable in this scenario, it is far less so when you have lots of dependencies.
You very much want the information in A's pom that says that it explicitly expects to find C-1.0 on the classpath so that you can understand when you have transitive dependency conflicts. Again, Maven will do the job of ensuring that the "closest" version of any particular jar ends up on your classpath. But when things go wrong - you want all the dependency metatdata you can get.
On a slightly more practical note, a dependency is unused when you can remove it from your pom and all of your unit/integration/acceptance tests still pass. ;-)