1

I have a (very very large) Spring Boot application. This is a large legacy application. Assume that I have dozens of Controllers and routes.

I want to do limited test deployments. Also, for licensing reasons, I want to package and deploy 5 controllers and remove the rest (not just disable, but remove).

Is this possible to do using some Gradle/Spring magic ? Can I select just 5 controllers to be packaged as part of the jar and the rest 30 should not even be present in the output ? I would not like to ship the code for the other controllers.

I can force each controller to be in a different package. So I can say that I want package a, b,c to be in the JAR file...but remove d,e,f. Or some other way ?

Sandeep
  • 1,745
  • 3
  • 20
  • 30
  • https://stackoverflow.com/questions/30023509/i-wish-to-exclude-some-class-files-from-my-jar-i-am-using-maven-assembly-plugin – Rana_S Oct 09 '22 at 06:30

1 Answers1

3

From the Spring Boot Gradle Plugin Reference Guide:

The BootJar and BootWar tasks are subclasses of Gradle’s Jar and War tasks respectively. As a result, all of the standard configuration options that are available when packaging a jar or war are also available when packaging an executable jar or war.

Based on the above this should work:

bootJar {
  excludes = [
    'com/acme/controller/NotPaidForController.class',
    'com/acme/controller/shoppingcart/*.class',
    'com/acme/controller/**/*Delete.class'
    // etc.
  ]
}

If it does work then I'd assume a similar solution using the bootWar task if your legacy application is packaged as such.

Note that physically excluding classes from the jar/war might cause severe runtime errors, i.e. Spring might still look for them when initializing the application context. In order to avoid this, I recommend using Spring @Profiles or @Conditional components instead. Using these techniques the controller classes would be still part of the deployment, they would just not be considered as candidates during the initialization of the application context which as you mentioned might not be what you want.

Attila T
  • 577
  • 1
  • 4
  • 18
  • Agree with using 「@Conditional @Profile」 if you are able to modify legacy code, only use boot jar exclude if that’s not in your option. – Gary Liao Oct 10 '22 at 01:41
  • @attila/@gary thanks for answering. genuine question - why would excluding controller class cause an issue ? i mean is it a case where one controller is calling the other ? from my understanding controller classes are pretty much leaf nodes in the compiler graph. excluding them ought to be pretty clean right ? is there a way to make this safe ? im happy to play with the initialization to make this possible – Sandeep Oct 11 '22 at 12:25
  • @Sandeep I wouldn't call controller methods directly from anywhere therefore I agree with the sentiment that removing controllers *should* be safe. OTOH, you mentioned that this is a legacy application and in my experience there's always a considerable amount of "magic" in legacy applications. If you choose to use `@Profile`s or `@Conditional` beans you can run various tests which makes these options the safest imo. – Attila T Oct 11 '22 at 20:03
  • @AttilaT one follow up question - can this exclusion be done via code ? i want to build a gradle plugin that does this kind of stripping out – Sandeep Nov 01 '22 at 15:40
  • @Sandeep Not sure what you mean. The solution based on `bootJar`/`bootWar` is already doing the "stripping", i.e. the excluded classes won't be part of the deployment. Though there's no "stripping" when using `@Profile`/`@Conditional`, the annotated components won't be part of the application context. Both solutions can give you what you wanted. Neither of them requires to develop a plug-in. – Attila T Nov 02 '22 at 02:44