*http://jira.codehaus.org/browse/MNG-5652
<http://jira.codehaus.org/browse/MNG-5652>*


On 21 June 2014 15:28, Jason van Zyl <ja...@takari.io> wrote:

> 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 <
> stephen.alan.conno...@gmail.com> 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 <pbened...@apache.org> 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 <
> >> stephen.alan.conno...@gmail.com> 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 <pbened...@apache.org> 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 <
> >>>> stephen.alan.conno...@gmail.com> 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
>
>
>
>
>
>
>
>
>
>

Reply via email to