I have a maven project that depends on another maven project which is not available on a public repo. Let's call them projects A and B, and A depends on B.
I'm currently pulling in B in project A by declaring it as an external dependency which I've placed inside an in project repo. (I call mvn bundle:bundle in project B and just copy the generated jar over to project A) The problem is, by doing this maven can't infer which dependencies B relies on since it's a bundled jar.
Let's suppose both projects A and B rely on another maven project C which is available on the remote maven repository. Project A uses project C, version 0.2 and project B uses project C, version 0.1. However, since project B is being loaded in project A as an external bundled jar, maven doesn't know this. During run time, project A tries to call a method which exists in C 0.2 but not in C 0.1. However maven built the project by importing project B first then C as the remote dependency, so C 0.2 is not in the bundled project A jar, and we get a runtime methodNotFound error.
Any idea how I can deal with this? Is it possible to just include a pom.xml file with the bundled project B jar somehow so maven knows that B relies on C as a dependency and can sort the issue out itself?
The way I'm currently working around this is just by manually setting the build order outside of maven and not using it at all for compilation.
EDIT: OK I got it to work by just including a (artifactId)-(version).pom file in the same directory as the jar for maven to get a dependency list
If you would use maven as per tutorials (e.g. here) it just works. Why are you doing bundle? Why do you need copy something? Just declare B as dependency in A's pom.xml and do mvn install for B, then A will use it from your local maven repo.
Also, if you just add both modules into single project (I'm using IDEA), IDE recognises the dependency.
Related
suppose I have a project say A which is dependent on B. so when I build project A. does maven generates the artifact of A by bundling with project B artifact?
and suppose if project B is dependent on C. then when I build project A, will it by default takes the transitive dependency c to generate the artifact? and even if it takes, what will happen if I add C as a dependency in project A pom.xml? will maven takes the C artifact for two times to build A and generates a bigger artifact file?
what will happen if I add C as a dependency in project A pom.xml?
If C's dependency has already been resolved, maven will simply ignore it if it is declared elsewhere.
will maven takes the C artifact for two times to build A and generates a
bigger artifact file?
No.
Please check https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Transitive_Dependencies for more details.
Transitivity brings a very serious problem when different versions of the same artefacts are included by different dependencies. It may cause version mismatch issue in runtime. In this case, dependency:tree command is very useful in dealing with conflicts of JARs.
$ mvn dependency:tree
Check https://howtodoinjava.com/maven/maven-dependency-management/#dependency-tree for more details.
this question is a little bit broad, things can change a little with you start to talk about Maven multi-module projects (so there is a parent-child relationship between modules). I will assume that multi-module setups are off-topic for this question.
Also: IDEs have tight integration with Maven and might add additional automatic processes on top of it. I assume this is plain Maven as it would work from a shell.
finally: there is a big difference from working with dependencies you pull in from the internet and projects you are building yourself with Maven. I am going to limit this answer to only building your own projects when it comes to dependency management. Otherwise I'd be writing the Maven manual here.
suppose I have a project say A which is dependent on B. so when I
build project A. does maven generates the artifact of A by bundling
with project B artifact?
Maven will include whatever you put in the dependencies listing; if it cannot it will fail the build. If project B is your own project, it will not automatically build B for you when you are building project A, it will only try to include whatever jar is already in your local maven repository. If there is no jar in your local repository, it will try to download it from all the Maven repositories that are known within the project. This will fail if Project B is just a project living on your harddrive, the only way then to make the jar of Project B available for usage in Project A is to actually build and install Project B first so a copy of the jar is put in your local maven repository.
Similarly if project B changes but you do not change its Maven version number, it is your own responsibility to rebuild and install it so the existing jar in your local maven repository gets overwritten.
It is possible that the dependency jar of B is pushed to a remote repository; it could be that your company is hosting or licensing a Nexus or an Artifactory for example and development builds are pushed to a snapshot repository so it can be used by several developers on different machines without them having to checkout the project and build it on their own machine. Then it depends on how Maven is configured if it will eagerly download updated versions of the jar when building project A. If you are working with a remote repository and you suspect that during the build an older version of a dependent jar is being used, this existing question's answers detail a few ways to force dependency jars to be updated when they were already downloaded before. But you should hardly ever need to use that.
and suppose if project B is dependent on C. then when I build project
A, will it by default takes the transitive dependency c to generate
the artifact?
Yes it will walk the entire dependency tree and include all transitive dependencies.
and even if it takes, what will happen if I add C as a
dependency in project A pom.xml? will maven takes the C artifact for two times to build A and generates a bigger artifact file?
Well first of all: dependencies are not included in the jar of project A by default so the size of the jar does not depend on the number of dependencies the project has. You would have to specifically use a plugin that has this functionality, often called "one jarring", "creating a fat jar" or creating an "uber jar". The Maven Shade plugin is a common way to do this.
Regardless, Maven does not allow multiple copies of the same dependency groupId+artifactId pair to exist on the classpath and will filter out duplicate copies when it finds them. This also happens when you add the same artifact multiple times within the same pom, Maven will call you out on it and include only one copy.
So no, in the end there will be only one copy of C.jar. Even if the pom of A refers to C version 1.0 and the pom of B refers to C version 1.1.
Looking for the best option, or a solution I am unaware of:
(probably unnecessary context) I developed "project A", a 1990's RPG video game ported to Java. Currently starting on "project B", a server to co-ordinate project A to run as a MMORPG.
Project A, lives in gitHub, compiles in maven and has no dependencies on project B.
Project B, (will) live in gitHub, has dependencies on "project A", and aspires to compile in maven
I would like both to sit in separate github repositories
I would like project B's pom.xml to specify the version of 'project A' needed.
No preference if this is achieved via specifying a git branch/version or maven artifactId/version.
I would like running maven for project B to find either:
(if available) Project A's last local build of specified version.
(fallback) Projects A's latest version on gitHub
I would prefer not to host project A Jars in some url (or git repo from project A, or B), as they will become large due to graphics. Also that type of thing rubs me the wrong way.
I would like "project B" to "just work" via a 'git clone ...', followed by a 'mvn package'.
There seems to be a multitude of approaches:
via 3rd party: eg jitpack
via maven reactor / modules (with what appear to be several sub approaches)
running 'mvn install' from project A
nexus, artifactory
via git submodules
I would like both to sit in separate github repositories
that's trivial
I would like project B's pom.xml to specify the version of 'project A' needed.
you can use version to distinguish your jars
I would like running maven for project B to find either:
(if available) Project A's last local build of specified version.
(fallback) Projects A's latest version on gitHub
that's maven by design
I would prefer not to host project A Jars in some url (or git repo from project A, or B), as they will become large due to graphics. Also that type of thing rubs me the wrong way.
have you consider to separate resources from core? ie put them in separate project given that they least likely to change
now solution, in my opionion what you need is remote maven repository (by remote i mean opposite to local which will be accessable whenever you want to work on your project. personally i would recommend nexus, but i might be biased here, given that i have most experience with it.
other solution might be maven repository on github. never tried it, but it looks ok
You can
check out both projects on your computer, build project A with version x.y.z and then build B against A with that version. This works through the local Maven repository on your computer.
put both B and A into a multi-module project so that you can build everything at once. This means that both projects have to be in subdirectories of some parent directory.
Use your own Nexus/Artifactory. Then you can mvn deploy B in a version to this repository and resolve it in A through the same one. Works more or less like the local repository, but is much more convenient to use and search in.
Using M2Eclipse plugin. Project A depends on Project B. Project B exists both in maven local repository and on workspace. While debugging, Eclipse ignores the workspace copy and goes to maven local repository copy of Project B.
But the weird thing is, when I remove Project B from the pom.xml of Project A, Eclipse goes to workspace copy.
I have tried:
Disabling workspace resolution of Project A and re-enabling it.
Clean installing Project A and Project B.
Force updating Project A.
Neither of these worked. When I remove Project B from pom.xml of Project A, it works. When I re-add Project B to the pom.xml of Project A, Eclipse goes to maven local repo copy of Project B again. But removing Project B from the list of dependencies of Project A is obviously not the way to go.
Did anyone else observed this weird behavior? What should I do to stop this happening?
Within Eclipse, you can add, in the dependent project (Project A), a link to your workspace project (Project B), instead of the one inside your Maven local repo.
You have to do this on the dependent project (project A):
Right click > Build path > Configure Build path... and in the Projects tab, you add your workspace project.
I found it. Apparently, someone has changed the version of Project B dependency on Project A's pom.xml from TEST-SNAPSHOT to UAT-SNAPSHOT. Since the version of Project B on my workspace is TEST-SNAPSHOT, Eclipse naturally thinks that this is not the version it is looking for, and hence, it goes to maven local repository.
In other words, Project A's pom.xml changed from this:
...
<dependency>
<groupId>SomeGroupID</groupId>
<artifactId>Project_B</artifactId>
<version>TEST-SNAPSHOT</version>
</dependency>
...
to this:
...
<dependency>
<groupId>SomeGroupID</groupId>
<artifactId>Project_B</artifactId>
<version>UAT-SNAPSHOT</version>
</dependency>
...
And this is the pom.xml of the Project B in my workspace:
...
<groupId>SomeGroupID</groupId>
<artifactId>Project_B</artifactId>
<version>TEST-SNAPSHOT</version>
...
Since Project A references UAT-SNAPSHOT version of Project B (instead of TEST-SNAPHOT version), Eclipse naturally thinks that Project B in my workspace is not the project which Project A is looking for. Hence, Eclipse goes to my local maven repository.
Take home message is, one should check very carefully that the version being referenced, and the version of the project which you expect to be referenced matches exactly.
I have two GAE Java projects, A and B. I want to use some of the mature classes from A in B (and continue to use them in A too, of course). Both projects were created using maven and then imported into Eclipse (in my mind, this kinda makes maven primary and Eclipse secondary :-).
What is the best way to do this, keeping maven primary?
I expect the solution will be something like:
Create a new maven project C.
Move the common classes to C.
Include C as dependency in pom.xml of A and B (possible to do this without first exporting C as a jar?).
Hopefully after this I will be able to run and test (mostly done by running mvn appengine:devserver) A and B independent of each other.
My knowledge of maven is limited, so how do I create (e.g., which archetype to use) this project C such that:
it will import successfully as an independent Eclipse project,
be export-able as a jar (if need be), and,
trigger re-build of A and B when C changes, whether it is Eclipse auto-recompiling or maven recompiling when I run mvn appengine:devserver
If there is a better but completely different solution, I wouldn't mind considering that too.
Configuration:
OS: OS X 10.9.5
maven: 3.1.1
Eclipse: Kepler (4.3) with m2eclipse
Java: 1.7.0_45
Thanks!!
Well, you are very close to the "good and right" solution. You write it in your question :-)
Create a new maven project C.
Move the common classes to C. Build (mvn clean install) project C. As
a result, the JAR will be in your local repo.
Now you can include C as dependency in pom.xml of A and B.
Note that as you have mentioned, if there is any change in project C, projects A+B will have to be re-compiled.
Of course, C.JAR is ready for use and there it is not related to any IDE such as Eclipse.
Regarding which archetype to use, you can use maven quickstart archetype:
mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart
from : https://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-quickstart/
I have a maven Java project (Project A) which depends on a second project (Project B). Right now, Project A downloads Project B from the repository so it can build. However, I am also working on Project B. How can I get Maven to use the version of Project B which is on my machine and ignore the version in the repository?
If both projects have the same version (and that's a SNAPSHOT version), build Project B locally (mvn clean install) and Project A will use that version.
You can do mvn install on B so it will be installed into local repo and used from there by A. You can aggregate these two projects as modules of multi-module project so they can be build within same build reactor and see each other. You can also use IDE plugin (like m2e for Eclipse) that supports what you're saying about if you have both project in the same workspace.
The last option is probably most comfortable.