TaskExecutionException when attempting to use java mutli-project structure with sourceSet to aberrate from expected directory structure


(buzz chopra) #1

Hello - I am relatively new to gradle - so I might be doing something “wrong” but I think I’ve come across a problem:

If I use a java multi-project structure with build.gradle files in each sub-project (and the root project), while specifying a different ‘srcDir’ than what is conventional, my build fails due to missing symbols that I think should be resolved as part of the dependency resolution that has been explicitly listed in each build.gradle file.

I think this is a problem because:

If I use the conventional structure with the source files in ‘$project/src/main/java’ (instead of ‘$project/src’), and no ‘sourceSets’ block the build is successful.

dependencies are as such: Service --> Api Client --> Service Client --> Api

output from tree:

.
├── Api
│   ├── src
│   │   └── com
│   │  
   └── test
│   │  
       └── api
│   │  
           ├── ApiOne.java
│   │  
           └── ApiTwo.java
│   └── build.gradle
├── Client
│   ├── src
│   │   └── com
│   │  
   └── test
│   │  
       └── client
│   │  
           └── Client.java
│   └── build.gradle
├── Service
│   ├── src
│   │   └── com
│   │  
   └── test
│   │  
       └── service
│   │  
           ├── ServiceOne.java
│   │  
           └── ServiceTwo.java
│   └── build.gradle
├── build.gradle
└── settings.gradle

Also here is the content of build.gradle in the Services project:

sourceSets {
   service {
      java {
         srcDir 'src'
      }
   }
}
  dependencies {
   serviceCompile project( path: ':Api' )
}

Is this a problem or am I doing something incorrectly?

Thanks in advance!


(Eric Berry) #2

Could you post your root project’s build.gradle and settings.gradle files, as well as the actual error you’re getting?

Few things I can see without those though, is that I believe your Service/build.gradle file should be more like this:

apply plugin: "java"
  sourceSets {
 main {
  java {
   srcDir 'src'
  }
 }
}
  dependencies {
 compile project(":Api")
}

Note that your sourceSet closure should be “main” / java, not “service” / java, and in your dependencies, it should just be “compile” not “serviceCompile”, you also don’t need the “path:” attribute.

Also note that you don’t necessarily have to define the plugin and sourceSets in each sub project. If they all follow the [project]/src convention, you could define this in your [root]/build.gradle file:

subprojects {
 apply plugin: "java"
    sourceSets {
  main {
   java {
    srcDir 'src'
   }
  }
 }
}

(buzz chopra) #3

elberry, Your suggestion of modifying the default (i.e. ‘main’) source set worked as you had expected. Thank you!

For some reason after reading [section 23.7.2 of the user guide] (http://gradle.org/docs/current/userguide/userguide_single.html#N12275) - I thought I had to define a new source set. In this case doing so was not required. However, I believe there will be situations where it would be useful to define new ‘sourceSets’ while still resolving symbols defined in other subprojects. The issue I was runnning into was that the classpath associated with ‘service’ sourceSet in my original post did not contain a reference to classes compiled as a result of the explicit dependency declared against ‘project (":Api")’.

Is there a trick to making that work (perhaps a better post for the “Questions” topic) ?

I’m including the artifacts you requested just in case: # root level build.gradle:

subprojects {
   apply plugin: 'java'
   apply plugin: 'eclipse'
     version = '0.1'
     repositories {
      mavenCentral()
   }
}

settings.gradle

include "Service", \
        "Api", \
        "Client"

(Eric Berry) #4

Ah, in that case, I believe you need to modify the compile configuration.

configurations {
 compile.extendsFrom serviceCompile
}

This tells gradle to use the serviceCompile classpath when doing a ‘build’.

Also, I believe you have to still define the main/java source set as part of your custom source set:

sourceSets {
 service {
  main {
   java {
    srcDir 'src'
   }
  }
 }
}
dependencies {
 serviceCompile project(":Api")
}