Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non Spring modules should not be bootJars also should not be asociated to the framework context #269

Closed
3 tasks done
dgallego58 opened this issue Jun 17, 2022 · 3 comments
Milestone

Comments

@dgallego58
Copy link

dgallego58 commented Jun 17, 2022

Is your feature request related to a problem? Please describe.

At the moment the plugin is related to spring framework, but every submodule (subproject) is not always an executable bootJar, since its deployable jar is related to the module which has the MainApplication (default is :app-service module) and this module ends up in a Fat/uber Jar with every module sharing spring-context dependency.

Considerations:

  • The spring-boot-gradle-plugin plataform asociates implicitly the boot dependencies to core dependencies (dependency starter manager), which is not ideal but works for an hexagonal architecture.
  • Since the core(domain) should be dependency agnostic also must stays in DRY principle.
  • This is related to the main app module to create 2 jars, plain jar and bootJar.
  • As a developer ideally we must have our dependency versions centralized in a single module (parent build.gradle for example)

Describe the solution you'd like

  • dependency centralized can be achieved in the build.gradle:

apply false so we can delegate our own jars in isolation check isolation plugin config

buildscript {
	ext {
        cleanArchitectureVersion = '2.4.1'
        springBootVersion = '2.7.0'
        springCloudVersion = '2021.0.3'
        sonarVersion = '3.3'
    }
}

plugins {
        id 'co.com.bancolombia.cleanArchitecture' version "${cleanArchitectureVersion}"
	id 'org.springframework.boot' version "${springBootVersion}" apply false 
        id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'org.sonarqube' version "${sonarVersion}"
	id 'jacoco'  // beware jacoco is automated by gradle plugin central itself
        id 'java'
        id 'java-library'
}
  • asociate every submodule to a jar or bootJar in case a module is a deployable single unit.
    example:

in the subprojects declaration since its a closure is possible to do the following:

//main.gradle

subprojects{ subProject -> 

    apply plugin: 'idea'
    apply plugin: 'java-library'

    if (subProject != project(':app-service')) {//app-service mainClassModule should be a bootJar
        bootJar {
            enabled = false //disables bootjar task for non spring boot starters
        }
        jar {
            enabled = true
        }
    } else {
        bootJar {
            enabled = true
        }
        jar {
            enabled = false
        }
    }
}
  • the Domain/Core module shall not be use third party libs (except utilery common use, remember DRY)

it can be achieved by the following, ex:

// main.gradle
subprojects{ subProject -> 

    apply plugin: 'java-library' //this is important so we can share the :model and :usecase modules via `api project(':model')` declaration

    if (subProject != project(':model') || subProject != project(':usecase') ) { //app-service mainClassModule should be a bootJar
        dependencies{
           implementation 'org.apache.commons:commons-lang3:3.12.0'
        }

    } else {
        apply plugin: 'io.spring.dependency-management'
        apply plugin: 'org.springframework.boot'
        dependencies{
            implementation 'org.springframework.boot:spring-boot-starter-webflux'
            implementation 'org.springframework.cloud:spring-cloud-starter-sleuth'
        }
        dependencyManagement {
              imports {
                  mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
              }
          }
    }
}

this change reduces the size of jars since every module does not share dependencies also reduces the amount of jars to be zipped in the final uber jar

Consideration

this is just an idea, if not it can be added as a configuration alternative to README.md
this approach also can be focused to a non spring project, ex: Quarkus or Micronaut

EDIT: spelling

@juancgalvis
Copy link
Contributor

Hi @dgallego58, sorry for late reply, I like your idea because infrastructure modules are not bootJar executables. We will evaluate the inclusion of this settings in the next spring boot 3 based project.

@juancgalvis juancgalvis added this to the Spring Boot 3 milestone Feb 9, 2023
@juancgalvis
Copy link
Contributor

@dgallego58 we have been doing the changes, but we does not evidence a size reduction on jars, do you have some test source code where the size is considerably reduced?

@dgallego58
Copy link
Author

@dgallego58 we have been doing the changes, but we does not evidence a size reduction on jars, do you have some test source code where the size is considerably reduced?

Sorry, not atm, but for package rellocation, this helps for duplicated classes in classpath, it is based on shade maven plugin: https://github.com/johnrengelman/shadow but for gradle

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants