Gradle workflow with project dependencies

I’m wondering how people develop day-to-day with Gradle and how they manage in-house dependencies.

Let’s say we have a main project with the following in-house dependencies:

proj depends on dep1
proj depends on dep2
proj depends on dep3

Now, these dependencies also may depend on one another:

dep1 depends on dep2, dep3

I want to be able to basically develop them simultaneously, where I
have a main project(proj) and all it’s depencies (dep1, dep2, dep3) open
in, say, IntelliJ or some other IDE. That way, when code in one project
changes, I can tell the IDE to build and run and it will take care of
building the dependencies for me. Also, the code is evolving rather
rapidly and this allows me to immediately see where I’ve made certain
errors between projects.

Right now, in the build.gradle file for proj, I have something like the following for dependencies:

dependencies {
    compile project('ext:dep1')
    compile project('ext:dep2')
    compile project('ext:dep3')
    compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.3'
    compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.3'
    testCompile group: 'junit', name: 'junit', version: '4.11'

where the other dependent projects are checked out from source
control into $proj/ext/dep[1…3]. This is great and all, but then I have
to worry about dep1 and its dependencies. Now I could do the same kind
of thing recursively where dep1 would also have dep2 and dep3 checked
out into $proj/ext/dep1/ext/dep[2…3], but then dep1 would not be
updated when I update $proj/ext/dep[2…3].

I feel like this could be something that is fixed maybe with a
symlink or something, but I’m wondering if I’m just way off the mark on
how day-to-day development should go.

This could also be solved by having a binary repository (Archiva,
Nexus, etc.), but I feel like the process of building a dependency,
pushing to the repository, then having Gradle download it during the
build process is too complex for what it is. Not to mention this would
involve having a separate IntelliJ window open for every project and
dependency, whereas with the scenario described above, it’s 1 window
with dependency projects open. I also don’t get the benefit of knowing
immediately when I have an issue.

I want to keep this as generic as possible so that any other
developer could clone this repo and instantly be ready to go without
having to make sure the paths line up relative to their situation.
Anyone else have this problem?

I think there is no simple answer to it. We basically have individual projects for those things you call dep1, dep2, and dep3. During our official build process, artefacts from those projects get deployed to an artefact repository like Sonatype Nexus (think of it as your own private Maven Central).

Of course that’s fine if you just work on one of your projects and want to get the changes your colleagues have done. Things get more tricky if you do changes on all of them simultaneously. We basically have 2 different approaches for it:

  1. You build dep1 locally and deploy it locally to your $HOME/.m2 repository using the gradle maven plugin. In any project, you make sure that mavenLocal() is the first repository in the list of your repositories gradle should query. I’m not yet fully sure if that really works correctly, but I believe so.
  2. Another developer has set up his IDE to overwrite the gradle dependencies for own deps and point them to the outcome of other projects. This seems to work fine, but is very manual in terms of IDE setup.

I would be interested in the solution you come up, so please share when you got a solution.

1 Like

Part of this motivation is that I would like to have instant integration, meaning if I make a change that creates errors between project and dependency, I want to know about it as soon as possible. Ideally, this means that whichever IDE I am using knows where the source is for both project and dependency and knows the relationship between them.

IntelliJ seems to work great with the “compile project(‘ext:dep1’)”, but it sort of falters when you get to a situation where a project and a dependency both share another project dependency. In that case it may make sense to symlink the shared dependency so that when you change that shared dependency, then both projects are aware of the change immediately.

The more I think about this, I feel it may be the way to go. I just wanted to hear from others if there was another way to knock it out of the park.

You might find this stack overflow question and answer useful