I have three separate gradle projects. In these projects I have some code that is common to all of them. What is the best way to create common library.
I do not want to install and maintain maven repo
I know that I can create jar file and add it to all three projects but then I will need to manually add new jar after every update.
If there's any more than one person on your team you should have a continuous integration server which is publishing artifacts to a repository. You then have the option to
Develop one project and reference the other from the repository
Develop on two projects in parallel using a composite build
If it's just you then I guess you could do one of:
Publish to mavenLocal() and lookup from there (see publishing to maven local)
Create a composite build from two or more projects
I'd argue that even if a single developer, you should have a CI server that's constantly building and reporting test failures. So it's logical that this should be publishing to a repository too.
I wouldn't qualify it as "best" by any stretch, but I think you could "publish" your common lib to a shared drive and then have the other Gradle builds use a Flat Directory Repository to depend on it.
Good luck.
Related
I am in need of separate jar of some classes existing in a multi-module project. I need to pull those classes out of existing module so that I can create a jar for them which I can then export to some other project. What I am thinking is what's the advantage of creating separate module in existing project or altogether creating a separate project?
I can't think of possible trade-off. Can you tell me the trade offs involved.
I would suggest you to create an another module instead of a separate project.
Justification:
1) You can pack this jar and use wherever you want it.
2) You can add this module as a dependency to the other modules
3) We will be following the the Maven general rule "one primary artifact per POM"
Conceptually, you should only create a new project if the set of classes you're moving are coherently useful. If this new project you're going to create can be used to solve a problem (with a good API), I think it's a good enough reason to create a new project.
Otherwise, it's perfectly fine for a maven artifact to be shared among other projects even it is just a module of a multi-module project.
Just my $0.02
module:
- easy to manage dependencies
- easy to support shared components. For example two modules use the same
database.
- build/ci process may take longer
project:
- you can easily deploy projects separately with their own versions and so on
- more convinient in case a dedicated team works on a seprated project
- easy to manage build system
- more complicated to handle dependencies
So we a re considering Gradle instead of Maven. What I cant figure out is how to EASILY share built dependencies between completely seperate projects at a local level that will work anywhere.
So imagine I have 2 projects DBService and Middleware. Middleware depends on DBService but they are completely seperate (not sub projects nor multi modules etc...).
I make changes to the DBService and then in Maven I could have changes go to local Maven Repo (not global as i need to test them first) using:
mvn clean install
I then start coding on Middleware and import the changes by running the same command as normal (Nice!). The maven POM requires nothing special at all (besides standard ). No path to local directory containing the jar in a lib folder (nasty IMHO) or anything else. it just works (out of the box).
How can I achieve this very simple and very common scenario in Gradle. I know I can use a local Maven repo but this is this a first class citizen in Gradle? Does it not need special/ad-hoc, or even worse, environment specific setup (UGHH) in Gradle?.
I have a Maven 3 multi-module project (~50 modules) which is stored in Git. Multiple developers are working on this code and building it, and we also have automated build machines that run cold builds on every push.
Most individual changelogs alter code in a fairly small number of modules, so it's a waste of time to rebuild the entire source tree with every change. However, I still want the final result of running the parent project build to be the same as if it had built the entire codebase. And I don't want to start manually versioning modules, as this would become a nightmare of criss-crossing version updates.
What I would like to do is add a plugin which intercepts some step in build or install, and takes a hash of the module contents (ideally pulled from Git), then looks in a shared binary repository for an artifact stored under that hash. If one is found, it uses that artifact and doesn't even execute the full build. If it finds nothing in the cache it performs the build as normal, then stores its artifact in the cache. It would also be good to rebuild any modules which have dependencies (direct or transient) which themselves had a cache miss.
Is there anything out there which does anything like this already? If not, what would be the cleanest way to go about adding it to Maven? It seems like plugins might be able to accomplish it, but for a couple pieces I'm having trouble finding the right way to attach to Maven. Specifically:
How can you intercept the "install" goal to check the cache, and only invoke the module's 'native' install goal on a cache miss?
How should a plugin pass state from one module to another regarding which cache misses have occurred in order to force rebuilds of dependencies with changes?
I'm also open to completely different ways to achieve the same end result (fewer redundant builds) although the more drastic the solution the less value it has for me in the near term.
I have previously implemented a more complicated solution with artifact version manipulation and deployment to private Maven repository. However, I think this will fit your needs better and is somewhat more simple:
Split your build into multiple builds (e.g., with a single build per module using maven -pl argument).
Setup parent-child relationships between these builds. (Bamboo even has additional support for figuring out Maven dependencies, but I'm not sure how it works.)
Configure Maven settings.xml to use a different local repository location - specify a new directory inside your build working directory. See docs: https://maven.apache.org/guides/mini/guide-configuring-maven.html
Use mvn install goal to ensure newly built artifacts are added to local repository
Use Bamboo artifact sharing to expose built artifacts from local repository - you should probably filter this to include only the package(s) you're interested in
Set dependent builds to download all artifacts from parent builds and put them into proper subdirectory of local repository (which is customized to be in working directory)
This should even work for feature branch builds thanks to the way Bamboo handles parent-child relations for branch builds.
Note that this implies that Maven will redownload all other dependencies, so you should use a proxy private Maven repository on local network, such as Artifactory or Nexus.
If you want, I can also describe the more complicated scenario I've already implemented that involves modifying artifact versions and deploying to private Maven repository.
The Jenkins plugin allows you to manage/minimize dependent builds
whenever a SNAPSHOT dependency is built (determined by Maven)
after other projects are built (manually via Jenkins jobs)
And if you do a 'mvn deploy' to save the build into your corporate Maven repo then you don't have to worry about dependencies when builds run on slave Jenkins machines. The result is that no module is ever built unless it or one of its dependencies has changed.
Hopefully you can apply these principles to a solution with Bamboo.
Currently my deploy workflow involves manually (i.e. in a script) cd-ing into each maven project directory and running mvn install. The problem is for local resources, i.e. other in-house code that I've written and am actively developing/maintaining, I don't know how to tell maven to build those resources itself when they are missing. Ideally each time I need to re-package the top level application it will rebuild any libraries it depends on that have at least one file modified.
If your (multi-module) project uses other in-house resources, what you actually need might not be to rebuild all those resources all the time, but to use a local maven repository. It can be a simple repository where resources are deployed using ssh or an HTTP transport (see the deploy plugin), or a real artifact manager such as Archiva, Artifactory or Nexus.
A repository manager does more than just hold your deployed artifacts, it can also clean the obsolete snapshots once the corresponding release has been made, and serve as a local cache for other repositories, including central.
Have a parent POM which contains all your modules. When you build the parent, all the modules that are part of parent POM file will be build as well.
You can inherit many things from the parent as long as you have the parent in your child.
Consider setting up Jenkins to automatically build your code. Jenkins has a useful feature that will rebuild projects that depend on newly built artifacts. Builds can be automatically triggered by simply committing your code.
If you're using several development machines (or working in a team) combine Jenkins with Nexus (Other options:Artifactory, Archiva) to provide a common store for shared artifacts. These tools are were designed to support Maven builds.
What are the main possible reasons of breaking down a Maven project to sub-modules?
Are you looking something more than the benefits of Modularization? The sub-modules should ideally be representing a single concept/feature so that they are functionally cohesive.
Pom file inheritence
You can use the and sections of the root poms to keep consistent version numbers and configurations across all child projects. So if I have an aggregator project that lists 300 projects, all that use apache commons-io and I want to upgrade them all the the latest version of commons-io, I can just change the version in the dependencyManagement section of the root pom. None of the child projects need specify a version.
build profiles
In the above example, if I have 300 sub projects, an individual developer is probably not regularly working on all (or even many) of the 300 sub-projects. You can create a build profile that specifies only the modules you work on regularly, and if you have a continuous integration server that deploys artifacts to an artifact repository, you'll get all the changes the developers on your team make too, without having to build all 300 modules.
General organization/clarity
While waiting for an answer to my comment.
A reason to split a Java EE based maven project into sub modules is so you can build the JAR/RAR/WAR/EAR/whatever independently of eachother.
For regular Java apps, you might split out the functionality into separate JARs, again each of these could be a sub-module under the overall project and again you can build them independently, run separate goals/phases/reports etc.