Looking for recommended approach for filtering the jars that get embedded into my war in a multi-project build


(Doug Lethin) #1

I’ll try to reduce my problem to a simple example to illustrate what I’m looking to do.

Let’s say I have a multi-project build:

myproject/

library/

webapp/

My library has a dependency on hibernate:

// library build.gradle snip
apply plugin: 'java'
  dependencies {
  compile "org.hibernate:hibernate-core:${hibernateVersion}"
}

And my webapp project has a dependency on my library:

// webapp build.gradle snip
  apply plugin: 'war'
  dependencies {
  compile project(':library')
}

By default, the war task is going to package up my library.jar, hibernate-core, and any of its transient dependencies into my webapp war file.

But I’m looking to customize this in the following way. I want to to conditionally build my war file differently depending on the application container I’m targeting deployment to (which might be passed to the build as system or project property) In one case,the default behavior might be fine, but in another case, where I’m deploying my war file into an application container that already has hibernate and its transient dependencies in a shared classloader, then I don’t want hibernate or it’s transient dependencies packaged in the jar war file.

The only thing the war plugin explictly provides for customizing this behavior is:

  1. you can call the war task’s ‘classpath’ to add additional jars 2. You can take advantage of the war tasks’ additional configurations – providedCompile & providedRuntime to restrict certain dependencies from being included in the war.

However, I’m not sure either of these help me in what I’m looking to do. I think what I might have to do is possibly supply an ‘afterEvaluate’ closure in my webapp to somehow manipulate the dependency model. Ideally in this closure I would have a list of module-names (for example – hibernate-core), and it would some how iterate through the current dependencies, find any modules that match the supplied list and then both mark them to be excluded, and then re-add them as either providedCompile or providedRuntime dependencies to the webapp project.

Does this sound like the right approach? And if so, any clues you could provide on how to construct that afterEvaluate closure? Or is there a different way?

Thanks in advance for any help you can provide.


(Doug Lethin) #2

I’ve found a way to do what I want to do at this point. Doing something like below. It seems to work, but I’ll continue to play around and refine it.

configurations {
     // TODO need to flesh out these details a bit more
  if (shouldFilterHibernate()) {
    println "Excluding transitive dependencies already in supplied by container"
    all*.exclude group: 'org.hibernate'
  }
}
  dependencies {
     // TODO need to flesh out these details a bit more
  if (shouldFilterHibernate()) {
    providedRuntime "org.hibernate:hibernate-core:${hibernateVersion}"
    providedRuntime "org.hibernate:hibernate-annotations:${hibernateVersion}"
    providedRuntime "org.hibernate:hibernate-entitymanager:${hibernateEntityManagerVersion"
  }