Opened 7 months ago

Last modified 2 months ago

#436 accepted enhancement

feature request maven exclude dependency

Reported by: aruttenberg Owned by: mevenson
Priority: blocker Milestone: 1.6.0
Component: other Version: 1.6.0-dev
Keywords: aether abcl-asdf contrib Cc:
Parent Tickets:


Like this:

To prevent dependencies from one maven artifact from stepping on another. Which they are doing. (each loads a different version)

Subtickets (add)

Change History (9)

comment:1 Changed 7 months ago by aruttenberg

Here's a snippet that poc shows how one can do this at the direct dependent level.

    (let* ((node 
	     (#"getRoot" (#"collectDependencies" (ensure-repository-system) (ensure-session) collect-request))))
      (let ((evil (find-if (lambda(e) (equal (#"getArtifactId" (#"getArtifact" e)) "org.protege.editor.owl"))
			   (jss::j2list (#"getChildren" node)))))
	(#"remove" (#"getChildren" node) evil)
	(let ((dependency-request
		(jss:new 'DependencyRequest))

For deeper dependents I think you need to use pass a DependencyFilter in the constructor of the DependencyRequest. See PatternExclusionsDependencyFilter and OrDependencyFilter

For syntax I might suggest using the syntax that PatternExclusionsDependencyFilter uses, so it would be:

(:mvn "net.sourceforge.owlapi/owlapi-distribution/4.2.6" :exclude (":org.protege.editor.owl:" ..)) for my example case of exclusion by artifactID

The patterns apparently support version ranges.

The MVN URL Scheme doesn't seem to provide for exclusions. If you used them then they would be the form for both the dependency and the exclusions - you still need to specify the exclusions separately.

I vote for the pattern over the URL

comment:2 Changed 7 months ago by aruttenberg

  • Priority changed from major to blocker

comment:3 Changed 7 months ago by mevenson

  • Owner set to mevenson
  • Status changed from new to accepted

Not sure as to which syntax to specify exclusion.

(:mvn "net.sourceforge.owlapi/owlapi-distribution/4.2.6" 
        :exclude (":org.protege.editor.owl:" ..))

What is syntax of the strings being passed to the :exclude clause here? Wouldn't it be simpler if they were regular mvn objects, i.e.

(:mvn "net.sourceforge.owlapi/owlapi-distribution/4.2.6" 
        :exclude ((:mvn "group/artifact/version")))

Of course we would probably prevent artifacts listed in an :exclude clause from having its own :exclude clause…

Last edited 7 months ago by mevenson (previous) (diff)

comment:4 Changed 5 months ago by mevenson

  • Component changed from (A)MOP to java

comment:5 follow-up: Changed 5 months ago by aruttenberg

I think it should be as I wrote, a list of strings. The strings are groupid:artifactid:version as with the ones inside a (:mvn) component, but with any of the three components blank, meaning match anything.

Or, could take a lambda with args (groupid artifactid version why) of the dependency that might be loaded and if it returns nil it means skip it. The variable "why" is the path of dependencies that led to this one. The elements could be (:mvn blah) - that works here.

I just got bit by this again.

comment:6 in reply to: ↑ 5 Changed 5 months ago by mevenson

Replying to aruttenberg:

I just got bit by this again.

I'll take a stab at this for abcl-1.5.0 after I rewrite the Aether adapter to have more meaningful failures.

Note that the naive implementation of dependency inclusions will not prevent incompatibilities between and within DEFSYSTEM forms, i.e. for a fragment like

  (:mvn "net.sourceforge.owlapi/owlapi-distribution/4.2.6" 
        :exclude (":log4j:1.2.14" ))
  (:mvn "org.apache/tomcat" 
        :exclude (":log4j:1.2.13" ))

it is undefined which log4j will be picked up.

It might be possible to do something intelligent with specialized class loaders, but given the impacts that Java 9 will have on locating and utilizing JVM artifacts, I'd rather do the simple implementation for exclusion to at least have some ability to get around bugs, and then revisit JVM artifacts when we have a reasonable abstraction which works on Java [678] as well as Java 9.

Last edited 5 months ago by mevenson (previous) (diff)

comment:7 Changed 4 months ago by mevenson

ME: We should probably split into a subticket for the near term work of the current patch by Alan, but we document here the steps to longer term solution that involves re-using ASDF abstractions in a more concise way.

After conversation on asdf-devel, Faré has outlined a plan of attack around :before methods for the planning phase.

We need to code our generalization solution against

comment:8 Changed 4 months ago by mevenson

Text of Faré's proposal

0- Aim for a single coherent set of jars within a given build, because
otherwise lies madness.

1- Within a given plan-then-perform phase, collect the set of jars and
their version intervals in a :before method on perform-plan that talks to
maven and uses some heuristic to resolve versions.

2- Across plan-then-perform phases of a same build session, record which
versions were loaded, and issue an error if it's incompatible.

3- Across build sessions, remember what version was previously loaded, and
unload/shadow it if it is incompatible (or throw an error if you can't),
and decide whether to keep or upgrade (if possible) if it's compatible.

As to writing a system that solves issues across phases, in your worst
case, your toplevel system would :defsystem-depends-on a system that loads
all the proper versions of all the jar files (or at least the problematic
ones), and then whichever phase causes some version to be loaded will have
been preempted by that first defsystem-depends-on system.

comment:9 Changed 2 months ago by mevenson

  • Component changed from java to other
  • Keywords aether abcl-asdf contrib added
  • Milestone set to 1.6.0
  • Version set to 1.6.0-dev

Interim solution: abcl-1.5.0 ships with the ASDF:MVN-MODULE component which allows one to prune the subtree via white and black listing of the transitive dependencies via explicit exclusions and inclusions.

TODO: "port" asdf-3.3, then push dependency resolution to its layer via suitable abstractions.

Last edited 2 months ago by mevenson (previous) (diff)
Note: See TracTickets for help on using tickets.