6

If I know the coordinates of an artifact, and a name of the class inside that artifact, can I make Maven run the class, including all of its dependencies on the Java classpath?

For example, suppose a coworker told me about a tool I can run, which is published to our internal Nexus with the artifact coordinates example:cool-tools:1.0.0. I used this answer to download the artifact. Now, I know that the main class name is example.Main. But if I just go to the artifact's download location and run java -cp cool-tools-1.0.0.jar example.Main, I get NoClassDefFoundErrors for any dependencies of cool-tools.

I'm aware of the maven-exec-plugin, but as far as I can tell that's only for projects where you have the source. Suppose I don't have access to the source, only the Nexus containing the tool (and all its dependencies). Ideally, I'd do something like mvn exec:exec -DmainArtifact='example:cool-tools:1.0.0' -DmainClass='example.Main', but I don't think the exec plugin is actually capable of this.

ETA: To be clear, I do not have a local project / POM. I want to do this using only the command line, without writing a POM, if possible.

Community
  • 1
  • 1
Coderer
  • 25,844
  • 28
  • 99
  • 154
  • I strongly doubt you can achieve this without using a pom. It might be able to construct a temporary pom on the command line though, like in the following: echo "" | mvn -f - – Torsten Jul 03 '14 at 15:06
  • Not possible. The pom lists the dependencies, without it you'll never make maven build a classpath. – Software Engineer Jul 03 '14 at 15:23
  • @Coderer Your assumption about the exec plugin is wrong. You can define the dependency in a separate pom where you define the dependencies and let exec plugin let run the class. – khmarbaise Jul 04 '14 at 08:46
  • @khmarbaise OK, so I could make a throwaway POM and set it up to "depend" on `cool-tools`, then run the exec plugin. Still a lot of work for what (I contend) *should* be possible in a one-liner. – Coderer Jul 10 '14 at 17:43
  • @EngineerDollery - I guess what I meant was, Maven has all the information needed to calculate dependencies from the commandline -- grab the POM for the specified artifact, do dependency resolution, ensure all JARs are available, and add each to the CP. Maybe this is something worth doing myself? – Coderer Jul 10 '14 at 17:46
  • @Coderer - maven has non of the information -- the POM has the information, and you said that you do not have a local POM. Even if you grabbed the artifact's POM, you still wouldn't be able to use it because you don't have the source. You need to have a local/project POM of your own, that references the artifact you're interested in, as per the comment by khmarbaise. – Software Engineer Jul 10 '14 at 18:14

5 Answers5

9

There is no out-of-the-box solution for your task. But you can create a simple script to solve it:

  • Download pom.xml of your tool from the repo.
  • Download jar of your tool.
  • Download all its dependencies.
  • Run java against resolved libraries.

Command line:

> mvn dependency:copy -Dartifact=<tool.group.id>:<tool.artifact.id>:<tool.version>:pom -DoutputDirectory=target
> mvn dependency:copy -Dartifact=<tool.group.id>:<tool.artifact.id>:<tool.version> -DoutputDirectory=target
> mvn dependency:copy-dependencies -f target/<tool.artifact.id>-<tool.version>.pom -DoutputDirectory=target
> java -cp target/* <tool.main.class>

Directory ./target will contain your tool + all dependencies.

See details on dependency:copy and dependency:copy-dependencies mojos.

Edit

As alternative, you can build classpath using libraries in the local repo by:

> mvn dependency:build-classpath -DincludeScope=runtime -f target/<tool.artifact.id>-<tool.version>.pom [-Dmdep.outputFile=/full/path/to/file]

See details on build-classpath mojo.

ursa
  • 4,404
  • 1
  • 24
  • 38
  • Is it necessary to copy all those jars to "target"? Cannot the classpath be constructed directly from artefacts in the local maven repository? – Thilo Dec 01 '14 at 00:11
  • 1
    I think `dependency:build-classpath` is a big chunk of the answer I was looking for. I haven't had a chance to run it yet, but if it actually makes sure the dependencies are in the local repo first, that basically solves my problem. I'll have to try it out! – Coderer Dec 01 '14 at 10:18
1

You could download the pom from the repository using wget, for instance. Then resolve the dependencies, and build the classpath exporting it to a file using Maven. Finally, execute with Java and the built classpath using something like bash backticks to use the content of the file.

Just like in this answer.

Community
  • 1
  • 1
Martín Schonaker
  • 7,273
  • 4
  • 32
  • 55
1

For me the first anwer almost worked, but I needed to slightly adjust the script. In the end I came (on windows machine) to following solution:

> mvn dependency:copy -Dartifact=<tool.group.id>:<tool.artifact.id>:<tool.version>:pom -DoutputDirectory=target
> mvn dependency:copy -Dartifact=<tool.group.id>:<tool.artifact.id>:<tool.version> -DoutputDirectory=target
> mvn dependency:copy-dependencies -f target/<tool.artifact.id>-<tool.version>.pom -DoutputDirectory=target
> cd target
> java -cp target/*;<tool.artifact.id>-<tool.version>.jar <tool.main.class>

On Unix/Linux machine in the last command the semicolon ";" must be replaced with colon ":". When input arguments must be provided, just put them in the last script line:

> java -cp target/*;<tool.artifact.id>-<tool.version>.jar <tool.main.class> arg1 arg2 ...
Andrushenko Alexander
  • 1,839
  • 19
  • 14
0

u can use IDEs like Intellij idea which automatically resolve dependencies as u write them in your pom

GIRISH RAMNANI
  • 614
  • 6
  • 18
0

As it has been mentioned by others already there is no solution without creating an extra POM.

One solution could be to use the Maven Shade Plugin in this POM: "This plugin provides the capability to package the artifact in an uber-jar, including its dependencies"

I think the Executable JAR is close to that what you'd like to achieve.

Gerold Broser
  • 14,080
  • 5
  • 48
  • 107