jbang icon indicating copy to clipboard operation
jbang copied to clipboard

Could //DEPS support a path to a file?

Open jmini opened this issue 3 years ago • 10 comments

Is your feature request related to a problem? Please describe.

Gradle allows to add a local file as dependency https://docs.gradle.org/current/userguide/declaring_dependencies.html

This is sometimes quite handy.

To perform some tests I wanted to replace

//DEPS com.mycompany:my-lib:1.2.3` 

By a local file that I have just built locally (not pushed yet to any maven repo):

//DEPS ~/Git/my-project/my-lib/build/libs/my-lib-1.3.0-SNAPSHOT.jar

Describe the solution you'd like

The possibility to use path for jars (absolute and relative?). Maybe supporting also wildcards?

I am also fine having to use //DEPS_FILE or anything else to indicate that I am pointing to a file instead of some maven coordinates.

Current behavior

With the current version of JBang, I get this error:

[jbang] [ERROR] [ERROR] Invalid dependency locator: '<path to the jar>'.  Expected format is groupId:artifactId:version[:classifier][@type]

jmini avatar Feb 07 '22 08:02 jmini

There isn't really anything preventing us from doing this and command line already have support for --class-path which simply gets passed directly to the compilation.

So you can use jbang --class-path your.jar my.java for now and we could add //CLASSPATH or similar as option.

maxandersen avatar Feb 07 '22 08:02 maxandersen

One of my main motivation for using Jbang is to simplify the commands I have to enter.

myScript --some input

Instead of:

java -jar some-lib.jar --some input

(and this is an easy case)


So a big :+1: to be able to put this inside the file executed by jbang.

//CLASSPATH is working for me.

jmini avatar Feb 07 '22 09:02 jmini

@maxandersen a problem here. Now jbang info classpath Hello.java does not contain some-lib.jar in classpath for development. DEPS from file system or HTTP URL still be useful for some cases.

//DEPS ~/Git/my-project/my-lib/build/libs/my-lib-1.3.0-SNAPSHOT.jar
//DEPS https://ci.example.com/projecta/demo-last.jar

linux-china avatar Feb 08 '22 18:02 linux-china

Yes. If we do this it should also reflect in tools classpath.

maxandersen avatar Feb 08 '22 18:02 maxandersen

I had a case where I wanted to give a locally built version a try with my jbang script. This would be similar to the gradle feature of composite builds with substitutions…

I was looking for the possibility to use //JARS in my jbang file, and I found my own issue again.

So I thought maybe it helps to add a comment with the motivation for this.


I have a script that has this as dependency:

//DEPS org.gitlab4j:gitlab4j-api:5.0.1

But now I would like to replace this jar with a locally built version of the project gitlab4j-api.

So in my local fork I already have the jar ready (obtained with mvn compile) __path_to_gitlab4j-api_fork__/target/gitlab4j-api-5.1.0-SNAPSHOT.jar

In the local fork I can run:

mvn org.apache.maven.plugins:maven-dependency-plugin:3.5.0:list

From the output:

[INFO] The following files have been resolved:
[INFO]    jakarta.activation:jakarta.activation-api:jar:1.2.2:compile
[INFO]    org.glassfish.jersey.inject:jersey-hk2:jar:2.35:compile
[INFO]    org.glassfish.jersey.core:jersey-common:jar:2.35:compile
[INFO]    jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile
[INFO]    org.glassfish.hk2:osgi-resource-locator:jar:1.0.3:compile
[INFO]    org.glassfish.hk2:hk2-locator:jar:2.6.1:compile
[INFO]    org.glassfish.hk2.external:aopalliance-repackaged:jar:2.6.1:compile
[INFO]    org.glassfish.hk2:hk2-api:jar:2.6.1:compile
[INFO]    org.glassfish.hk2:hk2-utils:jar:2.6.1:compile
[INFO]    org.javassist:javassist:jar:3.25.0-GA:compile
[INFO]    org.glassfish.jersey.core:jersey-client:jar:2.35:compile
[INFO]    jakarta.ws.rs:jakarta.ws.rs-api:jar:2.1.6:compile
[INFO]    org.glassfish.hk2.external:jakarta.inject:jar:2.6.1:compile
[INFO]    org.glassfish.jersey.connectors:jersey-apache-connector:jar:2.35:compile
[INFO]    org.apache.httpcomponents:httpclient:jar:4.5.13:compile
[INFO]    org.apache.httpcomponents:httpcore:jar:4.4.13:compile
[INFO]    commons-logging:commons-logging:jar:1.2:compile
[INFO]    commons-codec:commons-codec:jar:1.11:compile
[INFO]    org.glassfish.jersey.media:jersey-media-multipart:jar:2.35:compile
[INFO]    org.jvnet.mimepull:mimepull:jar:1.9.13:compile
[INFO]    org.glassfish.jersey.media:jersey-media-json-jackson:jar:2.35:compile
[INFO]    org.glassfish.jersey.ext:jersey-entity-filtering:jar:2.35:compile
[INFO]    com.fasterxml.jackson.core:jackson-annotations:jar:2.12.2:compile
[INFO]    com.fasterxml.jackson.core:jackson-databind:jar:2.12.2:compile
[INFO]    com.fasterxml.jackson.core:jackson-core:jar:2.12.2:compile
[INFO]    com.fasterxml.jackson.module:jackson-module-jaxb-annotations:jar:2.12.2:compile
[INFO]    jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.2:compile
[INFO]    jakarta.servlet:jakarta.servlet-api:jar:4.0.4:compile
[INFO]    org.junit.jupiter:junit-jupiter:jar:5.8.2:test
[INFO]    org.junit.jupiter:junit-jupiter-api:jar:5.8.2:test
[INFO]    org.opentest4j:opentest4j:jar:1.2.0:test
[INFO]    org.junit.platform:junit-platform-commons:jar:1.8.2:test
[INFO]    org.apiguardian:apiguardian-api:jar:1.1.2:test
[INFO]    org.junit.jupiter:junit-jupiter-params:jar:5.8.2:test
[INFO]    org.junit.jupiter:junit-jupiter-engine:jar:5.8.2:test
[INFO]    org.junit.platform:junit-platform-engine:jar:1.8.2:test
[INFO]    org.mockito:mockito-core:jar:4.4.0:test
[INFO]    net.bytebuddy:byte-buddy:jar:1.12.8:test
[INFO]    net.bytebuddy:byte-buddy-agent:jar:1.12.8:test
[INFO]    org.objenesis:objenesis:jar:3.2:test
[INFO]    org.mockito:mockito-junit-jupiter:jar:4.4.0:test
[INFO]    org.hamcrest:hamcrest-all:jar:1.3:test
[INFO]    uk.org.webcompere:system-stubs-jupiter:jar:1.2.0:test
[INFO]    uk.org.webcompere:system-stubs-core:jar:1.2.0:test
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

I extract the list of dependencies with compile scope and I add them to my script (as replacement of the original //DEPS line)

And then I can run my jbang script with:

jbang --class-path __path_to_gitlab4j-api_fork__/target/gitlab4j-api-5.1.0-SNAPSHOT.jar <name of my script>

The alternative would be to publish the patched lib to my local maven repo.

I start to be influenced by the gradle recommendations to not use it


An other approach is to use a service like jitpack… But it would be nice to have something that works locally and with more automation so that I do not have to redo all those steps manually

The first thing would be to be able to point to a jar directly from the script (using //JARS, //DEPS_FILE or //CLASSPATH or any of those options)

The second idea of being able to do substitutions from an other build requires certainly more work and is certainly a follow up issue.

jmini avatar Jan 25 '23 10:01 jmini

@maxandersen seems to be okay with this, so we might just implement this in the future, but I do want to put an opposing view:

  • //DEPS would never be the correct option for JARs because it's for things that know how to handle dependencies. Since JARs don't know anything about dependencies that won't work.
  • //CLASSPATH or something similar could certainly work, but it goes quite a bit against the idea that everything in the source file should either be obtainable from a relative path or from a remote location.
  • Your example source shows that a line like that could easily get very long, hard to get right and hard to maintain
  • Your example source would only work for you and nobody else
  • Using --cp together with --deps or //DEPS can always cause problems because any of those JARs in that long list could potentially conflict with any of the dependencies from a //DEPS line. I feel that making the --cp a command-line-only option makes it use slightly harder and therefore people will be less likely to use it. I feel that if we add a //CLASSPATH option people will use it together with //DEPS and expect Jbang to figure things out and make it work (we can't).

So my counter-question is: you're obviously doing something very specific, why don't you simply:

  • create a script that holds the complete jbang command line with the full --cp that you need to use?
  • add an alias that executes the command with the full --cp, or
  • publish your forked gitlab4j-api to your local Maven repo and simply use //DEPS?

quintesse avatar Jan 26 '23 09:01 quintesse

Your point on pointing to jar from deps and then not be able to resolve further deps is a good point.

The usecase op has is a bit tricky as if I understand right want to use local build jar and NOT include the referenced but also have deps resolved ...

Not sure what could solve it?

maxandersen avatar Feb 01 '23 19:02 maxandersen

Not sure what could solve it?

Well I gave 3 possible solutions :-)

I do like the 3rd one the best though: just publish to your local maven repo, it's not hard, you just run mvn install. It even makes it still easy enough for people to share their setups that way: "just check out my fork of project X, run mvn install and then you can do jbang blahblah".

quintesse avatar Feb 01 '23 23:02 quintesse

Should be fixed by https://github.com/jbangdev/jbang/pull/1641

fbricon avatar Jul 10 '23 10:07 fbricon

Correct. The limitation is though it has to be a relative path.

maxandersen avatar Jul 10 '23 18:07 maxandersen