'How to build a fat jar with multi-project and Gradle?
I'm new to Gradle, and is struggling with building a multi-projects fat jar.
I'm trying to do the same as mentioned here: Gradle multiple jars from single source folder
I have three packages, the dependency is: PandaService => PandaServiceDataAccessLayer => PandaDatabaseDocker.
Now I want to build a fat jar for PandaService. However, I'm not able to get ./gradlew build work. Now it is complaining that Plugin with id 'org.springframework.boot' not found. How can I fix it?
Will also appreciate any advises on changing build.gradle to follow the best practices.
More Info
This is the settings.gradle of PandaService:
rootProject.name = "PandaService"
include "PandaService"
include "PandaDatabaseDocker"
include "PandaServiceDataAccessLayer"
This is the build.gradle of PandaService:
subprojects {
apply plugin: 'java'
}
project(':PandaDatabaseDocker') {
sourceSets {
main {
java {
srcDir '../src'
include 'PandaDatabaseDocker/**'
}
}
}
}
project(':PandaServiceDataAccessLayer') {
sourceSets {
main {
java {
srcDir '../src'
include 'PandaServiceDataAccessLayer/**'
}
}
}
dependencies {
implementation project(':PandaDatabaseDocker')
}
}
project(':PandaService') {
repositories {
mavenCentral()
}
group = 'PandaService'
version = '0.0.1'
sourceCompatibility = '11'
targetCompatibility = '11'
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
sourceSets {
main {
java {
srcDir '../src'
include 'PandaService/**'
}
}
}
dependencies {
// Add depended local modules
implementation project(':PandaServiceDataAccessLayer')
// Spring boot + Jersey
implementation 'org.springframework.boot:spring-boot-starter-parent:2.6.4'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-jersey'
compileOnly("org.springframework.boot:spring-boot-devtools")
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// Swagger
implementation 'io.swagger:swagger-jersey2-jaxrs:1.6.5'
// Lombok
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
// log
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-log4j2'
// RDS Connection
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'mysql:mysql-connector-java:8.0.27'
// AWS secretes manager
implementation 'com.amazonaws.secretsmanager:aws-secretsmanager-jdbc:1.0.6'
// JOOQ
implementation 'org.springframework.boot:spring-boot-starter-jooq'
// HikariCP
implementation 'com.zaxxer:HikariCP:5.0.1'
}
//create a fat Jar with all dependencies
jar {
duplicatesStrategy(DuplicatesStrategy.EXCLUDE)
dependsOn configurations.runtimeClasspath
from {
configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
manifest {
attributes "Main-Class": "com.PandaService.MainApplication"
}
}
configurations {
all*.exclude module: 'spring-boot-starter-logging'
all*.exclude module: "logback-classic"
compileOnly {
extendsFrom annotationProcessor
}
}
test {
useJUnitPlatform()
}
}
Solution 1:[1]
I sorted it out.
The solution is to use Gradle Composite Builds. In this way, I don't even need to have a wrapper root project.
Reference:
- https://blog.jetbrains.com/idea/2016/10/intellij-idea-2016-3-eap-gradle-composite-builds-and-android-studio-2-2/
- Gradle includeBuild vs implementation project
- https://docs.gradle.org/3.1/release-notes.html#composite-builds
- Gradle includeBuild vs implementation project
- https://blog.jetbrains.com/idea/2017/03/webinar-recording-composite-builds-with-gradle/
- https://docs.gradle.org/current/userguide/composite_builds.html#defining_composite_builds
Solution 2:[2]
@/matmul handles batches nicely, but the rules are that for 3d arrays, the first dimension is the batch, and dot is done on the last 2 dimensions, with the usual "last of A with the second to the last of B" pairing.
It took a bit of reading to decipher you description but it appears that you want the first of p to the batch, and last of vec to be the batch. That means vec needs to transformed to a (2,5,1) to work with the (2,5,5) p.
In [176]: [email protected][:,:,None]
Out[176]:
array([[[ 60],
[ 160],
[ 260],
[ 360],
[ 460]],
[[ 695],
[ 820],
[ 945],
[1070],
[1195]]])
The result is (2,5,1). We can squeeze out the the last to get (2,5), but apparently you want a (5,2)
In [179]: ([email protected][:,:,None])[...,0].T
Out[179]:
array([[ 60, 695],
[ 160, 820],
[ 260, 945],
[ 360, 1070],
[ 460, 1195]])
np.einsum('nij,jn->in', P, vec) does effectively the same, with the n as the batch dimension that is 'carried through' to the result, and sum-of-products on the shared j dimension.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Yang Liu |
| Solution 2 | hpaulj |
