I have an application extension which is built using ANT. It is loaded and executed by Third party app written in Java. Each extension can use the libraries provided with the app and does not need to include them in the jar. Any other libraries used by the extension must be included in the jar. In addition it has a set of resources that need to be within the package of the extension not at the root. With ANT the resources are included automatically and the additional libraries required are included using zipfast.
Using Gradle I have compiled and created the jar but it does not have the additional libraries nor the resources.
Can anyone suggest which plugin/tasks I should use to add the libraries and resources to the jar?
Thanks, the resources unfortunately can not sit in main, as I said they have to be within the package of the extension, i.e com.moneydance.modules.features..resources. Using a ‘non standard’ source dir is straight forward what I need is the mechanism to specify the output dir in the jar.
As far as the ‘bad practice’ jar is concerned the users of this app do not know about maven/gradle or any other repository and therefore the developer of an extension has to provide the libraries not supplied by the main app.
I have tried shadow plugin and it included all of the dependencies which included the main app libraries, my jar went to 76mb. I guess I need a way of filtering the dependencies.
Thanks, the resources unfortunately can not sit in main
But that’s what you want.
You said in the jar, so that means in the main source set.
as I said they have to be within the package of the extension, i.e com.moneydance.modules.features…resources
So what?
Put them into src/main/resources/com/moneydance/modules/features/resources then.
Everything below src/main/resources is packed as is into the jar.
and therefore the developer of an extension has to provide the libraries not supplied by the main app.
Yeah, that’s fine. And it can be done in good ways. The Minecraft way (or whatever your host software with the same non-sense is) is imho not. You can do the plugin mechanism for example so that the whole jars are packed in the plugin jar and a custom class loader reads them like it is also done with Spring Boot good-practice fat jars. Or you can make it able that plugins are packaged as ZIP with the dependency jars inside that are then unpacked to some directory. So many ways to do it properly. Requiring shaded fat jars is none of them. See https://fatjar.net/ for some quotes about them.
tasks.withType<Jar> {
val rootDir=rootProject.projectDir
archiveFileName.set("$rootDir/dist/mrbutil.jar")
from("$projectDir/src/main/java") {
include ("com/moneydance/modules/features/mrbutil/resources/*.*")
include ("com/moneydance/modules/features/mrbutil/strings/*.*")
}
}
Yeah, that’s fine. And it can be done in good ways. The Minecraft way (or whatever your host software with the same non-sense is) is imho not. You can do the plugin mechanism for example so that the whole jars are packed in the plugin jar and a custom class loader reads them like it is also done with Spring Boot good-practice fat jars. Or you can make it able that plugins are packaged as ZIP with the dependency jars inside that are then unpacked to some directory. So many ways to do it properly. Requiring shaded fat jars is none of them. See https://fatjar.net/ for some quotes about them.
The main app uses a separate classloader to load extensions to protect itself from extension failures. It sets the classpath of the extension to include its own libraries and its dependents. Any extra dependents that an extension needs must be included in the jar.
I am loath to restructure my work to match what Gradle wants as these extensions are in production and being used by over 1000 people world wide.
Sure thing, you don’t need to.
It is just the easiest and cleanest to follow established conventions.
But you can always configure it like you want / need.
This is what worked:
You should maybe instead configure the processResources task, so that they are also taken by other consumers of the resources. Like you have it, only all tasks of type Jar include them. Besides that it might not be a good idea anyway to do this (and setting the name) on all tasks of type Jar, like also javadocJar, sourcesJar, …
The main app uses a separate classloader to load extensions to protect itself from extension failures. It sets the classpath of the extension to include its own libraries and its dependents. Any extra dependents that an extension needs must be included in the jar.
Yes, bad practice as I said.
They could for example have a class loader that loads classes from jar files present within the extension jar in a libs directory. This way extensions could still deliver their exclusive dependencies without the need to build a bad-practice fat jar.