Throw it into a JIRA and tag the component FDPFC. I can only find 8 issues related to features requiring POM format changes. I seem to recall more.
On Jun 20, 2014, at 11:55 AM, Stephen Connolly <[email protected]> wrote: > Well I've had this proposal in one form or another on and off for the past > 2-3 years. Jason recently stated that he only wants to look at concrete > proposals as the first stab for what/how to extend the pom format... so > here is a very concrete example proposal ;-) > > > On 20 June 2014 16:50, Paul Benedict <[email protected]> wrote: > >> Ah, the woes of fragmented jars. That's the bane of EE dependency >> management. Figuring out the superset/subset stuff is indeed terrible. Good >> job, Stephen, to propose a solution for it. >> >> >> Cheers, >> Paul >> >> >> On Fri, Jun 20, 2014 at 10:03 AM, Stephen Connolly < >> [email protected]> wrote: >> >>> Well this started out from a need for a more effective <excludes>. >>> >>> The issue with <excludes> is that you have to apply it to each and every >>> dependency... when what you really want to say is "see this dependency >>> here? well that is the same as X, Y and Z so don't pull them in from the >>> transitive dependencies" >>> >>> If you like that is the second use case in my proposal. >>> >>> The first use case is less relevant from the "better excludes" point of >>> view, but I believe it to be more useful. >>> >>> The third use case is for when you don't trust upstream to get things >>> right. Keep in mind that if, as a general principle, you don't trust >>> upstream to express things mostly correct then what the hell are you >> doing >>> trusting them to express their transitive dependencies correctly? >>> >>> Tooling would allow us to validate a pom's claims of equivalence. But >>> ultimately I think we need this concept to deal with te fragmentation of >>> API jars and implementations of APIs that we see taking place in central. >>> >>> >>> On 20 June 2014 15:27, Paul Benedict <[email protected]> wrote: >>> >>>> I am having trouble understanding how grouping together artifacts that >>> are >>>> "equivalent" gain me anything in my project building. I am already >> doing >>>> this in my POM today by excluding what's equivalent. Is this proposal >>>> simply about adding semantic information to the POM so it's more >> apparent >>>> what the intent is? >>>> >>>> Furthermore, whoever defines the equivalence needs to be extremely >>> careful. >>>> Not all "equivalent" jars are actually equivalent. Most people have >>>> learned, for example, that the javaee-api:6.0 jar in Maven is all stubs >>> and >>>> can't be used for unit testing; so people go to find EE jars from JBoss >>> or >>>> GlassFish, to get the full functionality. So I am not sure I'd ever >> want >>>> someone telling me what's equivalent during consuming. >>>> >>>> >>>> Cheers, >>>> Paul >>>> >>>> >>>> On Fri, Jun 20, 2014 at 7:51 AM, Stephen Connolly < >>>> [email protected]> wrote: >>>> >>>>> "supplies" concept proposal >>>>> =========================== >>>>> >>>>> Introduction >>>>> ------------ >>>>> >>>>> The following is a proposal for Maven in a post-modelVersion-4.0.0 >> era. >>>> The >>>>> aim of this proposal is to simplify the management of dependency >> trees >>> in >>>>> the decentralised era of artifact production that we find ourselves >> in. >>>>> >>>>> The core issue is that different organisations can produce artifacts >>> that >>>>> may overlap. The easiest example is the servlet-api. If we restrict >>>>> ourselves to version 2.5 of the servlet specification there are >> quite a >>>> few >>>>> artifacts that all deliver the exact same content: >>>>> >>>>> * `jetty:servlet-api:2.5-6.0.2` >>>>> * `org.daisy.libs:servlet-api:2.5.0` >>>>> * `org.mortbay.jetty:servlet-api-2.5:6.1.14` >>>>> * >> `org.jboss.spec.javax.servlet:jboss-servlet-api_2.5_spec:1.0.1.Final` >>>>> * etc >>>>> >>>>> **Note:** this is a generic problem that is not restricted to the >>>>> servlet-api, the servlet-api just provides the example that will be >>> most >>>>> familiar to everyone. >>>>> >>>>> So where these multiple artifacts supplying the equivalent content >>>> becomes >>>>> a problem is when the dependency tree is being calculated. If you >> have >>>> two >>>>> dependencies each declaring transitive dependencies on different >>>> artifacts >>>>> that supply equivalent content, then you end up with two copies of >> the >>>> same >>>>> JAR file in your classpath. >>>>> >>>>> In the case of the servlet-api, the hack most people use is to >> declare >>>> the >>>>> servlet-api with scope `provided` thus preventing it from being >>>> transitive. >>>>> This is, however, a hack. In a more ideal world it would be better to >>> let >>>>> the servlet-api be transitive and only when we get to the WAR module >>>> would >>>>> we declare that a specific servlet-api is to be provided in the >>>> containers >>>>> that the WAR is targets for deployment into. >>>>> >>>>> We can take a second example that does not have the luxury of a *de >>>> facto* >>>>> hack. >>>>> >>>>> * `javax.faces:jsf-api:2.1` >>>>> * `org.jboss.spec.javax.faces:jboss-jsf-api_2.1_spec:2.1.28.Final` >>>>> * `org.apache.myfaces.core:myfaces-api:2.1.13` >>>>> >>>>> Now in the case of the JSF API, you are supposed to bundle the JSF >> API >>> in >>>>> your WAR file. So if I use three JSF component libraries, I could >> very >>>> well >>>>> end up with three different but equivalent JSF API jars in my WAR >> file. >>>>> >>>>> Ideally what we want is some way of telling Maven that these >> artifacts >>>> are >>>>> equivalent. >>>>> >>>>> Proposal >>>>> -------- >>>>> >>>>> Introduce the concept of "supplies" to the project model. The concept >>>> needs >>>>> three changes to the project model: >>>>> >>>>> 1. An explicit top level construct for a project to explicitly >> declare >>>>> up-front artifacts that it knows - at the time the project is being >>>>> authored - to contain equivalent content to at least a subset of the >>>>> project's content. Declarations could include a claim from: `subset`, >>>>> `superset`, `disjoint` and `equivalent` with the default being >>>> `disjoint`. >>>>> 2. An explicit sub-element of the `dependency` construct to allow >>>> consumers >>>>> to *post-facto* declare a specific dependency as supplying equivalent >>>>> content for other dependencies >>>>> 3. An extension to the `dependency/excludes/exclude` construct to >> allow >>>>> consumers to remove claims a dependency makes with respect to >> supplying >>>>> equivalent content >>>>> >>>>> By way of illustration, here are some examples of these constructs >>> mapped >>>>> to a Model Version 4.0.0 like XML schema. As the >>> post-modelVersion-4.0.0 >>>>> schema is not yet known, this represents the best way to illustrate >> how >>>> the >>>>> concept will work, but note that this proposal does not suggest a >>> schema >>>>> for this concept. >>>>> >>>>> ### Example 1 >>>>> >>>>> This illustrates how we would want, say, the `myfaces-api` project >>> model >>>> to >>>>> look. >>>>> >>>>> ``` >>>>> <project> >>>>> <groupId>org.apache.myfaces.core</groupId> >>>>> <artifactId>myfaces-api</artifactId> >>>>> <version>2.1.3</version> >>>>> ... >>>>> <supplyManagement> >>>>> <supplies> >>>>> <groupId>javax.faces</groupId> >>>>> <artifactId>jsf-api</artifactId> >>>>> <version>[2.1,2.2)</version> >>>>> <claim>superset</claim> >>>>> <supplies> >>>>> <supplies> >>>>> <groupId>org.jboss.spec.javax.faces</groupId> >>>>> <artifactId>jboss-jsf-api_2.1_spec</artifactId> >>>>> <claim>equivalent</claim> >>>>> <supplies> >>>>> </supplyManagement> >>>>> ... >>>>> </project> >>>>> ``` >>>>> >>>>> This indicates that the `myfaces-api` artifact is intended to be >>> useable >>>> as >>>>> a drop-in replacement for either the `javax.faces:jsf-api` artifact >>>> within >>>>> a bounded range or for any version of the >>>>> `org.jboss.spec.javax.faces:jboss-jsf-api_2.1_spec` artifact. If you >>> get >>>> a >>>>> supplier conflict in your classpath, then Maven should fail the >> build. >>>>> >>>>> For example if somebody forked `myfaces-api` but did not list >>>> `myfaces-api` >>>>> in the fork's supplyManagement and you end up with both `myfaces-api` >>> and >>>>> `myfaces-fork-api` in your classpath. Maven can detect that there are >>> two >>>>> dependencies that both claim to supply `javax.faces:jsf-api` and fail >>> the >>>>> build, thereby letting the user add either exclusions or additional >>>>> supplies information to one of the artifacts and preventing duplicate >>>>> artifacts on the classpath. The build need not be failed if the >>> supplies >>>>> claims provide a resolution. e.g. if the claim is `equivalent` then >>> that >>>>> implies that there is a 1:1 mapping and hence the artifacts are >> drop-in >>>>> replacements. However where the claim is `superset` we cannot know >> that >>>> the >>>>> extra content in our artifact is the same as the extra content in >>> another >>>>> artifact which has a superset of `javax.faces:jsf-api`. >>>>> >>>>> ### Example 2 >>>>> >>>>> This illustrates a JSF component library that is working with the >>>> existing >>>>> JSF APIs >>>>> >>>>> ``` >>>>> <project> >>>>> ... >>>>> <dependencies> >>>>> <dependency> >>>>> <groupId>javax.faces</groupId> >>>>> <artifactId>jsf-api</artifactId> >>>>> <version>2.1</version> >>>>> <supplyManagement> >>>>> <supplies> >>>>> <groupId>org.jboss.spec.javax.faces</groupId> >>>>> <artifactId>jboss-jsf-api_2.1_spec</artifactId> >>>>> <claim>equivalent</claim> >>>>> <supplies> >>>>> <supplies> >>>>> <groupId>org.apache.myfaces.core</groupId> >>>>> <artifactId>myfaces-api</artifactId> >>>>> <version>[2.1,2.2)</version> >>>>> <claim>equivalent</claim> >>>>> </supplies> >>>>> </supplyManagement> >>>>> <dependency> >>>>> </dependencies> >>>>> ... >>>>> </project> >>>>> ``` >>>>> >>>>> In this case we are publishing a transitive dependency with >> additional >>>>> supplyManagement injected. Consumers of this project would thus gain >>> the >>>>> benefit of collapsing their transitive dependencies for any of these >>>> three >>>>> artifacts. As all artifacts are declared with `equivalent` claim, >> thus >>>> the >>>>> nearest of those three artifacts to the project will win as per the >>>>> standard dependency resolution rules when dealing with conflicting >>>> version >>>>> requirements in the transitive dependency tree. >>>>> >>>>> ### Example 3 >>>>> >>>>> Finally, there is the case where you need to correct an incorrect >> claim >>>> of >>>>> supply >>>>> >>>>> >>>>> ``` >>>>> <project> >>>>> ... >>>>> <dependencies> >>>>> <dependency> >>>>> <groupId>javax.faces</groupId> >>>>> <artifactId>jsf-api</artifactId> >>>>> <version>2.1</version> >>>>> <exclusions> >>>>> <exclusion> >>>>> <groupId>org.jboss.spec.javax.faces</groupId> >>>>> <artifactId>jboss-jsf-api_2.2_spec</artifactId> >>>>> <scope>supplies</scope> >>>>> <exclusion> >>>>> </exclusions> >>>>> <dependency> >>>>> </dependencies> >>>>> ... >>>>> </project> >>>>> ``` >>>>> >>>>> This would typically be coupled with adding back in a correct >> supplies >>>>> definition, but we need to allow for people to correct the graph >> after >>>> the >>>>> fact of their dependencies being deployed to the remote repository. >>>>> >>>>> ### Claim conflict resolution >>>>> >>>>> The four classes of claim can be resolved using the following matrix >>>>> >>>>> ``` >>>>> >> +---------------------------------------------------+ >>>>> | A >> | >>>>> >> +------------+------------+------------+------------+ >>>>> | subset | equivalent | superset | disjoint >> | >>>>> >> +---+------------+------------+------------+------------+------------+ >>>>> | | subset | conflict | A wins | A wins | conflict >> | >>>>> | >> +------------+------------+------------+------------+------------+ >>>>> | | equivalent | B wins | A or B | A wins | conflict >> | >>>>> | B >> +------------+------------+------------+------------+------------+ >>>>> | | superset | B wins | B wins | conflict | conflict >> | >>>>> | >> +------------+------------+------------+------------+------------+ >>>>> | | disjoint | conflict | conflict | conflict | conflict >> | >>>>> >> +---+------------+------------+------------+------------+------------+ >>>>> ``` >>>>> >>>>> The default unspecified claim is `disjoint` which indicates that some >>> of >>>>> the content is reproduced, but not all and there is additional >> content >>>>> added. With such a claim there will always be conflict and the build >>>> should >>>>> fail until the Project Model is updated to either remove some of the >>>> claims >>>>> or resolve the dependency clash. >>>>> >>>>> The ideal claim is `equivalent` which indicates that the two >> artifacts >>>> are >>>>> bi-directionally substitutable. This does not mean that the contents >>> are >>>>> identical. It does mean that they both deliver on the same contract >> in >>> an >>>>> equivalent fashion. >>>>> >>>>> The `subset` and `superset` claims are for aggregation APIs. So for >>>> example >>>>> the Java EE Web Profile API is a superset of the various spec APIs >> that >>>>> make up the Java EE Web Profile and a subset of the full Java EE >>>>> specification. The use of the `subset` claim should be reserved to >>> those >>>>> cases that are strict subsets. If anything is added that is not in >> the >>>>> supplied artifact then the correct claim is `disjoint`. >>>>> >>>>> ### Validation of supplies claims >>>>> >>>>> We do not want to introduce Java bias with this feature. As a result >>> the >>>>> validation of claims and supplies directives will be left to plugins. >>> For >>>>> the Java case we should probably provide either/both an enforcer rule >>> or >>>> a >>>>> maven hosted plugin to assist in checking JAR projects against the >>>> declared >>>>> supplies declarations, but Maven core should not be concerned with >>>> solving >>>>> the validation problem. >>>>> >>>>> Similarly, while there may be advantages in a more fine grained API >>>>> contract negotiation between dependencies, to bind such a concept >> into >>>> the >>>>> project model would significantly taint the Maven project model with >>> more >>>>> Java-centric concepts. Given that current software development >>> typically >>>>> uses at least two core languages: Java and JavaScript, we should be >>>> aiming >>>>> to reduce Java-centric constructs from Maven rather than increase >> them. >>>>> >>>>> ### Backporting >>>>> >>>>> It will not be possible to fully express this concept in a >> modelVersion >>>>> 4.0.0 project model. Thus if generating 4.0.0 compatible project >>> models, >>>>> the aim should be to fully resolve the dependencies of the project >>> using >>>>> all available information and express that as the transitive >>>> dependencies. >>>>> >>>>> Thus we will not expose the "supplies" information to modelVersion >>> 4.0.0 >>>>> parsers but we will expose the end results of that and present the >>> final >>>>> effective flattened dependency tree. >>>>> >>>>> modelVersion 4.0.0 consumers will thus be no worse off than they >>> already >>>>> are and those consumers understanding newer modelVersions can get the >>>>> enhanced tree resolution that they would not get otherwise. >>>>> >>>> >>> >> Thanks, Jason ---------------------------------------------------------- Jason van Zyl Founder, Apache Maven http://twitter.com/jvanzyl http://twitter.com/takari_io --------------------------------------------------------- We all have problems. How we deal with them is a measure of our worth. -- Unknown
