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.
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.
I have a question about the integration the eclipse and maven.
I have a project A with dependencies in project B which is itself just a container for a bunch of projects B-i.
Project B is imported in Eclipse but most of the B-i are not imported in eclipse. Sometimes, I want to work on a patch in B-n. So I import the B-n project and dependency resolving usually works well, that is, project A uses the project B-n and recompiles.
Problem happens often when I want to discard the local dependency, close the local project, and make sure that the remote B-n from our repository is used by A (let's say that the other team patched project B).
What is the good and proper "way" to do that kind of patching/ensure that A is using the remote/server version of B-n and not the previously compiled local jar ?
Removing the local project ? Removing the dependency in the local project ? Will I always have to "clean install" project A when I do such a change ?
Thanks.
If I understand you correctly, you do the following:
You have a project B-n with a version (say 1.0.0-SNAPSHOT). It is built on some kind of build server.
Then you check it out, built it locally (still with version 1.0.0-SNAPSHOT). Now you want to discard your locally built version and refer again to the 1.0.0-SNAPSHOT from the repository (correct me if you did not understand you correctly).
For that, you can purge the local repository by dependency:purge-local-repository. You can start this from Eclipse through "Run As -> Maven Build...". See also
https://maven.apache.org/plugins/maven-dependency-plugin/examples/purging-local-repository.html
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 found an annoying issue working with m2eclipse in Eclipse.
My workspace contains 2 projects, an application A and a library B. The application A POM has B as a dependency and everything works correctly. (The project dependecy is found and used when I build the application)
But if I change some code in project B and I forgot to mvn:install it, when I build the application it uses the last built version of the library and it loses my last changes.
Is there a way to force Maven / M2Eclipse to check if the source code of the dependecy is newer than the last version built, and to install it when installing/ deploying the main application?
Or maybe my approach is wrong or is something obvious that I'm missing?
You can tell m2eclipse to use resolve dependencies from the workspace rather than through the normal mechanisms. In your project properties (NOT workspace properties), select Maven->Resolve dependencies from Workspace projects.
This will mean that when you change B and subsequently build A, the changes should be picked up automatically.
If, however, you build outside Eclipse, you'll have to do the normal mvn install to get the correct dependencies.
I don't know of a way to tell maven to build the library first, then build your project. You could put two maven commands into a script and run the script.
Alternatively, you could put both projects inside a maven parent project, and then build the parent. This causes all child project to be built too (so in your case the library, and the application).
I think you have couple of options here
If you can change the maven project set up, I would suggest you to use maven multimodule
Option two might solve your problem but still involves a manual stop when you change your dependent project B, Do this on for your dependent project in eclipse
Select Library B ==> Properties ==> Maven ==> in the input box under Goals to invoke after project clean: ==> enter : install
To deploy any change that you made to Project B in eclipse to maven local/remote repo, You have to run Clean build in eclipse, This will deploy the latest Library B to the maven repository
Also make sure your Library B version is a SnapShot during the development
If you are looking to run the latest snapshots on your local machine you should try to set things up to launch directly from Eclipse.
Apart from avoiding the problem you originally posted about, it also has other advantages.
It will save you a lot of time by not having to perform intermediate build steps.
You can start and stop servers without having to leave your IDE.
The Eclipse console has extra features that you don't get from the system console.
You don't have to modify your start scripts to attach a debugger.
Our software is written in Java and comprise many (7) projects.
These projects are Netbeans ant projects.
I'm considering to converting them to maven2.
Where can I find some hints for doing such thing?
Don't read that book. It will only make you confused. Read this book instead: "Maven - The definitive guide" http://www.sonatype.com/books/maven-book/reference/ .
Also, the maven site has a lot of information, but the structure is terrible so you'll need to use google to navigate in it.
Here is my suggestion:
Do this by hand, not with "automagic" "help" from the IDE. Maven integration doesn't work that good yet, not in any IDE.
Make sure you program project is divided into modules under a common umbrella module, so that each module produces a single binary artifact (jar, war,...) possibly accompanied by the javadoc of the source code behind that artifact, a zip with the source code etc. The basic principle is that each module produces a single artifact, containing all the non-test-code under that module. You can do this while the project is still built by ant.
Each module should conform to the standard maven directory layout. The build destination is under [module]/target/[output-type, e.g. "classes"]. The source code is under [module]/src/main/[src-type e.g. "java"] and [module]/test/[src-type]. The artifact consists of all the code under src/main, and none of the code under src/test, as it built to the target directories. You can do this while the is still built by ant.
Start by transforming the sub-module that has no dependencies on other modules in the project.
Now you can create the parent maven module pom.xml with artifact type "pom", consisting of one of the modules below. Make a child module for the first submodule (the one with only external dependencies), using the umbrella module as "parent". Remember that you need to specify version for the parent. Remember to add the child module as a "module" in the parent too. Always use ${project.version} as version in the child modules when you create multi-module projects like this. All modules under a parent must be released simultaneously in a single operation, and if you use this setting maven will make sure the version fields stay the same across all modules and gets updated everywhere during the release. This may make it difficult to re-use the existing numbering scheme, but that doesn't matter. You are never going to run out of version numbers anyway.
Add the necessary dependencies, and make sure you can build the parent and the child module together using the command "mvn clean install" from the parent module.
Proceed with the rest of the modules the same way. Dependencies to other modules under the same parent project should also use ${project.version} as the "version" they are depending on, meaning "the same version as this". NOTE THAT in order to build, the module you are depending on must be built using "mvn install", so that it gets deployed to you local (computer) repository. Otherwise the depending module will not be able to find the classes. There are NO source-code dependencies between modules in maven, only dependencies to built and packed versions installed in local and remote repositories. This can be very confusing if you come from ant-projects. Build from the root module until you get comfortable with this. It takes two days.
Don't use maven integration in IDEs. It is a bad idea. Use "mvn idea:idea" or "mvn eclipse:eclipse" to set up your workspace as a non-maven ordinary IDE project. The inter-module dependencies mechanisms in maven and the IDE aren't identical and will never be. Also, if you have several mavenized projects with dependencies in between, you want to have several of these in your workspace with dependencies set up between. You can do this with mvn idea:idea / eclipse:eclipse if you create a separate maven project file called "workspace.xml" (or whatever) in the same directory as parent module, set up as a multi-module project containing modules "." and "../otherproject" (only one-way reference here, no parent ref back). If you run "mvn idea:idea / eclipse:eclipse -f workspace.xml" you get a workspace with all these modules linked together. No IDE integration lets you do that. This sound like a lot of extra work, but the workspace.xml-file is really small. It doesn't have to contain all that dependency stuff and all that, only the reference to the modules you want to bind together in your IDE.
I did a succeful migration of NetBeans Ant project to Maven project using the instruccions by Joseph Mocker here: http://forums.netbeans.org/ptopic55953.html
I cite the important part:
close the project
rename the build.xml, nbproject files/folders to something so NB won't recognize them.
close and restart NB (so any memory cache knowledge of the project is gone)
copy in an empty pom from some other project.
open the project back up in NB (NB should now identify it as a maven project)
rearrange the files to follow the maven way (™)
This won't be an easy task since Maven2 expects the files to be organized in a specific way. Anyway Better Builds with Maven is a free book that should get you started. It will help you understand Maven and it also has a chapter on migration.
I discovered that the migration is not necessary. The real requirements that I need was automatic download of dependencies (libraries).
This is also achieved by Ivy which nonetheless uses maven repositories.
I solved converting project from ant to ant+ivy with IvyBeans.
I have built a script to migrate Ant builds to Maven. You can find more information here:
https://github.com/ewhauser/ant2maven
It won't help you with fixing your directory structure and or any additional Ant tasks, but it removes a lot of the tedious steps to get started.