Gradle: Combine jars from sub-projects - gradle

I have a multi module gradle project. The project contains two subproject, i.e. a spring-boot application server and an npm front-end ui (which is just static javascript).
I can build both sub-projects. I can define:
implementation(project(':ui'))
in the dependencies section of the spring application and I get a running jar in the server projects build folder successfully serving the frontend.
However, I want to be able not to combine the two not within the server sub-project, but rather in the enclosing project.
I thought of something like:
build.gradle:
allprojects {
group = 'com.example.webapp'
version = '0.0.1-SNAPSHOT'
}
dependencies {
implementation(project(':server'))
implementation(project(':ui'))
}
settings.gradle:
rootProject.name = 'webapp'
include 'server', 'ui'
I think, I am completely wrong. Everything I find about gradle is either completely basic, or assumes way more than what I understood about it so far.
EDIT:
With my solution approach I am getting the following error:
A problem occurred evaluating root project 'webapp'.
Could not find method implementation() for arguments [project ':server'] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
EDIT 2:
The basic idea is from https://ordina-jworks.github.io/architecture/2018/10/12/spring-boot-angular-gradle.html

The implementation not found is caused by the lack of plugins applied to your root project. The implementation configuration is created by the java plugins in Gradle.
What you are trying to achieve requires a good understanding of Gradle and all the magic provided by the Spring Boot plugin.
You are effectively trying to reproduce some of that integration in your root project, without the help of the plugins.
An approach that might be easier would be to migrate your application project to be the root project and then have the ui as a subproject.

Related

Load Gradle plugin from custom plugin, dynamically

I am developing a Gradle plugin (https://github.com/hkhc/jarbird), which apply some other plugins in the code according to different scenarios.
I can do that by putting the plugin components as implementation dependencies in my plugin project. Then apply the project with project.apply() method with plugin ID or plugin class object.
However, this means unnecessary downloads of plugin components when I don't need those plugins. So I am finding a way to resolve the plugins dynamically.
I tried to do that by adding the dependency as compileOnly in the build script of my custom plugin, and load it in project.apply() of my plugin.
val artifactoryConfiguration = project.buildscript.configurations.detachedConfiguration(
DefaultExternalModuleDependency(
"org.jfrog.buildinfo",
"build-info-extractor-gradle",
"4.23.4"
)
)
artifactoryConfiguration.resolve()
When I made the coordinate wrong intentionally, I got ModuleVersionNotFoundException. So I am sure the resolve did take place. However, project.apply(ArtifactoryPlugin::class.java) still cause ClassNotFoundException when executing the plugin. It seems Gradle cannot load the plugin from a random detached configuration.
I got stuck at this point, and don't know how to make Gradle load a plugin that I resolve dynamically in my custom plugin.
Do I get the direction wrong or I missed something that makes this approach work?

How to add a file to the spring boot jar on top level?

I am trying to add a file to the top level folder of a spring boot jar.
We have a generic pipeline which deployes artifacts (jar, war, zip) to a cloud environment (cloudfoundry). And for this pipeline to work, the artifact needs to have cloudfoundry's manifest.yml inside on top level.
So i need to have this manifest file inside the final jar of our spring boot application.
I couldn't get it work with the spring-boot-maven-plugin, as it doesn't seem to provide any fitting options.
Unfortunately I think it has to be done with this plugin, because when using the maven-resource-plugin for instance, the additional resource files will always end up inside BOOT-INF/classes.
So maybe someone has an idea how to solve this issue?
PS: We have other projects using Gradle and there it's very easy to solve using the bootJar task. But moving to Gradle won't be possible for this use case
bootJar {
from('manifest.yml') {
into '/'
}
}

Collect Gradle project's dependency constraints

I am looking for a way to collect all the dependency constraints (enforced with a regular platform and/or enforcedPlatform and/or "manually") for a given project from a custom Gradle plugin.
In Maven world, you can resolve an "artifact descriptor" that will give access to the effective list of all the managed dependencies enforced on the artifact. I couldn't find so far how this kind of info could be collected in Gradle.
Any advice? Thanks!
based on the clarification of the question - below can be a start (requires more work - for some reason my local shows configuration as default - not the compile/runtime)
allprojects {
afterEvaluate {
configurations.findAll {it.canBeResolved==true}.each { println it + "\n" ; it.allDependencies.each { println it } }
}
}
The question (appears to me) is sharing the test code across modules in a multi-module project
Short answer - No - there is direct test dependency share across modules.
To share test code between modules internally via build settings
Official gradle route https://docs.gradle.org/current/userguide/java_testing.html#sec:java_test_fixtures
Simple hack
testImplementation files(project(':core-module').sourceSets.test.output.classesDirs)
add the above line either individually where you need or in root with subprojects() with appropriate condition
*there are other possible routes as well *
ex: via configuration child.testImplementation extends parent.testImplementation (or runtime)

IntelliJ Project "JS Client and JVM Server | Gradle" does not work

when I create the stated project type with Intellij Ultimate 2019.2
and then build the project (F11)
following error appears:
However when I run the SampleJvm.kt:
Netty start and everything seems fine.
Unfortunately the code is not working correctly:
The issue seems to be that the backend cannot find the
compiled testy.js, which shall be loaded as a resource
and then added to the HTML site:
I uploaded the project for download:
https://file.io/Jj50Ow
Thank you so much for any advice,
Best Chris
The js file is generated and packaged in a jar file, but the JVM server does not have a dependency on that JAR file and therefore it generates 404.
Open the build.gradle file and scroll to the bottom, add jsJar to the dependsOn and the classpath:
task run(type: JavaExec, dependsOn: [jvmJar, jsJar]) {
group = "application"
main = "sample.SampleJvmKt"
classpath(configurations.jvmRuntimeClasspath, jvmJar, jsJar)
args = []
}
And then you can run the app with gradle.
At this time, the new project generator doesn't correctly handle multiplatform projects.
There is a working example with Ktor on the back-end and React on the front-end, including hot-reload for UI development:
https://github.com/Kotlin/kotlin-full-stack-application-demo
I was able to get it working with Kotlin Gradle DSL, with a Spring Boot back-end (including being able to debug from IDE) and hot-reload of React front-end:
https://github.com/alexoooo/sample-multiplatform-boot-react
Note that Kotlin multiplatform projects are currently experimental, and some of the details are likely to change as the new IR is introduced: https://blog.jetbrains.com/kotlin/2020/03/kotlin-1-4-m1-released/

import a project on another project with gradle on eclipse

I'm trying to use Gradle as Spring MVC project builder. I divide my project in two distinct ones, the first project will contain the Repository and service part, and the second one, the views and controllers (web part)
My problem is when I try to deploy my project, the server don't see the entities from the first project. It also doesn't deploy this first project.
I think it due to Gradle, but I don't know how to indicate to gradle to import the first project on the second one.
You have to create a multi project with the following hirarchy:
Root Project
settings.gradle
service
build.gradle
...
web
build.gradle
...
The settings.gradle has to include the following
include 'service'
include 'web'
Now the web project can use the service project with the following code in the build.gradle:
dependencies {
compile project(':service')
}

Resources