compileOnly not useable for excluding jars from WAR?

Recently I changed our build scripts from a self defined configuration named “provided” which we used for excluding unwanted dependencies going into the WAR and used instead the new ‘compileOnly’. I was surprised that this did not give me what I expected. Dependencies marked with 'compileOnly showed up in WEB-INF/lib .

I have the suspicion this is due to the fact that subprojects which are included into the WAR do not declare these unwanted dependencies as ‘compileOnly’, but use them as ‘compile’ dependencies. Therefore, declaring ‘compileOnly’ dependencies in the subproject which is responsible for the WAR has not the effect I hoped it had.

Question: does this explain why the WAR contains those unwanted dependencies?

I found a solution working for me in “How can I exlude files from WAR when using WAR plugin against default or webAppDirName location”, where user ‘Daz’ pointed to something like this:

war {
rootSpec.exclude("**/slf4j*.jar")
,
}

Yes. Since they exist in the compile configuration as a result of other dependencies they will get included in the WAR. The dependencies in compileOnly are not removed from the WAR, the are omitted. If the same dependency sneaks its way in by another means it will still be included. You will have to explicitly exclude these JARs, either as you have done (at the packaging level) or from the compile configuration itself.

configurations.compile.exclude module: 'slf4j'

Okay, I understand.

Another option I tried and which didn’t work either was an exclude closure in the WAR task. In my understanding excludes declared at WAR level always should lead to the desired result. But it doesn’t work. Can you please explain this also?

Thanks.

Basically the CopySpec for the web-inf is isolated in that task. To do this you would have to do something like filter the files out of the task’s classpath.

war {
    classpath = classpath.filter { !it.name.contains('slf4j') }
}

Excluding from the configuration is really the better option, in my opinion.

I am trying to understand what is the difference between compileOnly and runtime from the perspective of a war file. @mark_vieira, your explanation,

The dependencies in compileOnly are not removed from the WAR, the are omitted.

I have a couple of subprojects, both integrated with a parent project. The parent creates a war file with dependencies from all three gradle scripts. I have runtime dependencies and compileOnly dependencies. I believe the compileOnly dependencies in the sub projects are needed so that the jars will build with those dependencies. If runtime dependencies used in the subprojects then those would be excluded from the jars and parent project war file. The war file obtains a subproject’s created jar but does not include the compileOnly dependencies.

Is this correct?