Omitted dependency from war in a multi-project project


(Ian) #1

Hi There,

I have a multi-project build script that is omitting a required jar file from the final WAR (validation-api jar file)…

Project A: Builds the GWT Project Project B: Builds the Server Project Project C: Builds the Web-app, Copies the project A output (not dependencies though) and all PROJECT B output & Dependencies and builds the final war file.

So far everything has worked great and all is well however i started getting an issue with missing classes (the validation api) so thinking it would be a very simple case of adding the validation-api as a runtime dependency of the server(projectB) & it would appear in the final war artifact - however, it never gets placed into the war - note; any other dependency I define as a runtime dependency in projectB will get placed into the war file, just not the validation-api jar file!!

The reason I believe that the validation-api is not being placed into the final war file is that i have excluded

providedCompile project(':projectA')

from the artifact & copy the contents in directly;

war {
    from project(':projectA').tasks.compileGwt.outputs.files, 'src/resources'
    }

However validation-api is a dependency of a jar file in ProjectA (the gwt-user jar file) , so even if i put it as a dependency of ProjectB, it doesn’t get copied in & all I need from ProjectA is the compiled output…

So - question is; can I explicitly tell gradle to include the validation-api in the war file even though it thinks I don’t need it??

Thanks,

Ian.

PS - Sorry if the question is a tad confusing but i’ve tried my best to simplify what i’m doing…


(Szczepan Faber) #2

I’m not sure why you needed to configure projectA as ‘provided’ dependency (firstly, I would look into that). It seems to me that projectA contains some runtime dependencies that really need to be on the classpath of the consumers of projectA. If you need to keep you ‘providedCompile’ setting I suggest to declare a new configuration in projectA. This configuration should include all runtime stuff that the consumers need (e.g. validation-api, or other friends). Then, you can declare in your war:

dependencies {
  runtimeStuff project(":projectA")
}

You can also put validation-api as runtime dependency of the war project.

Hope that helps!


(Ian) #3

Hi Szczepan,

Firstly, thanks for getting back to me but i’m still struggling to get the validation-api artifact into the war file! To answer a few of your questions;

“I’m not sure why you needed to configure projectA as ‘provided’ dependency” - This is to stop the .java output & all the gwt jar files going into the final war as with GWT we only need the.js files it generates & nothing else. You are correct in that validation-api, being a dependency of the gwt-user artifact is a runtime dependency

To get the JS files in I simply have the following;

war {
    from project(':projectA').tasks.compileGwt.outputs.files, 'src/resources'
    exclude 'WEB-INF/deploy/*'
}

“You can also put validation-api as runtime dependency of the war project.” tried that but it won’t copy the validation-api jar across into the war file…

However, If I remove change

providedCompile project(':projectA')

to

compile project(':projectA')

in the war web-app project then the Validation-API DOES get copied across to the war file however along with all the other GWT jar files & java class files that I do not want in the end war artifact.

So it seems that

providedCompile project(':projectA')

is stopping the validation-api jar file being copied in even when I explicitly add it as a runtime dependency of projectC (gradle is copying all other runtime dependencies that I refer in projectC to the war file, just not the validation-api)…

I’ve tried in getting a new configration in projectA but that doesn’t seem to have worked either :frowning:

Would you have any more thoughts on this? ?

Thanks in advance,

Ian.


(Szczepan Faber) #4

I would suggest to avoid reaching out to the other project model, and model the dependency explicitly eg:

//instead of:
from project(':projectA').tasks.compileGwt.outputs.files
  //do this:
configuration {
  gwtOutput
    gwtRuntime
}
  dependencies {
  gwtOutput project(path: ":projectA", configuration: "gwtOutput")
  gwtRuntime project(path: ":projectA", configuration: "gwtRuntime")
}
  war {
  from configurations.gwtOutput
  classpath configurations.gwtRuntime
}
  //in projectA:
configuration {
  gwtOutput
  gwtRuntime
}
  dependencies {
  gwtOutput compileGwt.outputs.files
  gwtRuntime 'validation-api' //use proper notation
  }

Hope the above puts you on the right track. I’m not an expert on the GWT so I made up the names of the configurations - please fix them so that they describe the problem better.

I haven’t tested above so please pardon any typos :slight_smile:


(Ian) #5

Hey,

Thanks & I see the approach you are taking & like it - just can’t seem to get the

dependencies{
......
gwtOutput compileGwt.outputs.files
}

results in;

No such property: compileGwt for class: org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler

Note the task to execute the GWT compiler is;

task compileGwt(dependsOn: classes, type: JavaExec) {
  .......
}

Any thoughts?


(Szczepan Faber) #6

Use ‘tasks.compileGwt’ instead of ‘compileGwt’. Referring the task by name without qualifying it with the ‘tasks’ container works in most places, apparently, it’s not working within the dependencies {} section.

Hope that helps!


(Ian) #7

Hi Szczepan,

Yea, tried that earlier but same error appeared (with the tasks prefix within the dependencies) :frowning:

Thanks though, Appreciate it…


(Szczepan Faber) #8

Not possible :slight_smile: The root cause might be different, then. For example, perhaps the compileGwt task is declared after you specify the dependencies section? I just checked and it is possible to refer to tasks just by name (omitting the container) within the dependencies section.