I have Java EE application. I need to deploy it to both Weblogic and JBoss application servers. For that reason, I have two versions of web.xml files for both servers. And my main goal is to change this configuration when I build project for specific servers. I have idea that I can keep one web.xml file in some directory {project}/files and for example when I build gradle for JBoss I replace an existing web.xml file with file from {project}/files. So I need to create some gradle task for this. I am new in gradle, so please give me some approximate solution how I can do that.
If it were me I'd follow the Gradle naming conventions and store the files at
src/weblogic/webapp/WEB-INF/web.xml
src/jboss/webapp/WEB-INF/web.xml
This structure would allow custom java classes and resources in future per servlet container if needed
Then you could create two extra tasks in build.gradle
apply plugin: 'war'
dependencies { ... }
task weblogicWar(type: Zip) {
dependsOn war
from zipTree(war.archivePath).matching {
exclude 'WEB-INF/web.xml'
}
from 'src/weblogic/webapp'
archiveName = "my-app-weblogic-${version}.war"
}
task jbossWar(type: Zip) {
dependsOn war
from zipTree(war.archivePath).matching {
exclude 'WEB-INF/web.xml'
}
from 'src/jboss/webapp'
archiveName = "my-app-jboss-${version}.war"
}
// wire the tasks into the DAG
assemble.dependsOn weblogicWar
assemble.dependsOn jbossWar
You could also do this in a loop eg:
['jboss', 'weblogic'].each { container ->
task "${container}War"(type: Zip) {
dependsOn war
from zipTree(war.archivePath).matching {
exclude 'WEB-INF/web.xml'
}
from "src/${container}/webapp"
archiveName = "my-app-${container}-${version}.war"
}
assemble.dependsOn "${container}War"
}
Related
I have started on gradle today itself. So I am trying out random things. I have below build.gradle file:
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter-api:5.4.2')
testRuntime('org.junit.jupiter:junit-jupiter-engine:5.4.2')
compile 'com.googlecode.json-simple:json-simple:1.1.1'
}
test {
useJUnitPlatform()
}
jar {
manifest {
attributes(
'Main-Class': 'src.main.java.demo.Hello'
)
}
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it)}
}
}
I have read somewhere that the method that I am using inside from block will create fat jar, which is not a good practice. As I am fairly new to this, I humbly want to ask the alternative to this. Is it adding classpath to manifest or something else??
The primary purpose is to bundle third party dependency jar files that will be used on runtime.
Thank You!
You could put all your dependencies into a ZIP file together with your own JAR and possibly external resources, or build an installer, or (if you're building a web app) build a WAR or EAR file. Gradle will take care of the manifest for you in any case.
(Also, there is nothing really wrong with fat JARs, they are fairly common these days and they do work.)
After I started using the spring boot gradle plugin in my gradle.build file, the build fails on jenkins.
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.2.RELEASE")
Things work fine locally including build, test and webapp runs fine with Jetty. The only problem is the build fails on Jenkins in the task artifactoryPublish. It says:
File '/var/lib/jenkins/jobs/release-my-project/workspace/build/libs/workspace-0.2.1-SNAPSHOT.jar' does not exists, and need to be published!
Not sure what's going with the gradle artifactoryPublish task. I think the task comes from Jenkins.
Before using the spring boot gradle plugin, my jar task in gradle.build is as follows:
jar {
baseName = 'my-project'
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
configurations.runtime.collect {
it.isDirectory() ? it : zipTree(it)
}
}
manifest {
attributes 'Main-Class':'com.example.Application'
}
// Exclude manifest signature files
exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/LICENSE'
}
Since the spring boot gradle plugin disables the jar task, and replaces it with the bootJar task, so I configured the bootjar task as follows:
bootJar {
baseName = 'my-project'
mainClassName = 'com.example.Application'
// Exclude manifest signature files
exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/LICENSE'
}
One thing I noticed from jenkins log is that it says the file workspace-0.2.1-SNAPSHOT.jar does not exist. Seems like it is looking for the wrong file. Previously, it looked for the correct file my-project-0.2.1-SNAPSHOT.jar. When I built locally, this jar file was created. Not sure what made jenkins look for workspace-0.2.1-SNAPSHOT.jar. It is supposed to be my-project as I did define baseName inside the bootJar task.
Any idea what's wrong here? Thanks.
Unless you explicitly define the name of the project, Gradle will use the directory name as the project name. On Jenkins, the project directory is called "workspace". artifactoryPublish is presumably using the project name to determine the name of the JAR file to publish. That's not good practice if that's the case.
Anyway, you really should set the name of your project. You won't have to explicitly set baseName on the Jar tasks then. Simply add a settings.gradle file in the root of the project, i.e. next to the build.gradle file, and set its content to:
rootProject.name = "my-project"
That should hopefully fix the problem, although it really depends on what the artifactoryPublish task is doing.
I would want to extend Peter's answer, it is recommended by the authors of Gradle that we should use settings.gradle
Define the root project name in the settings file: The ´rootProject.name´ effectively assigns a name to the build as a whole, which is used in reports like build scans. If the root project name is not set, the name will be the container directory name, which can be unstable (i.e. you can check out your project to any directory).
I have a huge legacy EAR project. Current build process uses Ant and I'm trying to convert to gradle.
The old Ant build uses a single source folder and everything is in there (EJB and WAR code together); then Ant uses different tasks to build EJB-JAR and WAR artifacts filtering by the package of interest (my.web.* for the WAR and my.ejb.* for the EJB).
It goes without saying that EJB and WAR heavily reference each other and I guess that's why they are compiled together even though separate artifacts are generated.
I have tried creating a parent EAR project, then separating my.ejb.* in an EJB subproject as well as my.web.* in a WAR subproject but gradle immediately complained about circular dependency and I haven't found a way around.
If above is not possible, then I am looking for recommendations on how to generate the EJB-JAR and WAR artifacts off the same codebase that would be compiled altogether, then include them in the EAR file as 'deploy' dependencies.
I have googled around but I am not very bright at gradle (obviously). Any help will be greatly appreciated.
I think you are falling into the trap that many of us have when trying to convert an existing ant project to Gradle for the first time - you are thinking of things the same 'ol ant way.
Instead, let Gradle do the work for you and it will be easier and the resulting build.gradle file much smaller and more concise.
Thinking in terms of having a parent ear project and a separate war project is good thinking however. But, you should take advantage of the plugins Gradle has to offer to simplify the task of constructing the archives.
Use the 'ear plugin':
https://docs.gradle.org/current/userguide/war_plugin.html
For example:
apply plugin: 'ear'
apply plugin: 'java'
repositories { mavenCentral() }
dependencies {
// The following dependencies will be the ear modules and
// will be placed in the ear root
deploy project(':war')
// The following dependencies will become ear libs and will
// be placed in a dir configured via the libDirName property
earlib group: 'log4j', name: 'log4j', version: '1.2.15', ext: 'jar'
}
ear {
appDirName 'src/main/app' // use application metadata found in this folder
// put dependent libraries into APP-INF/lib inside the generated EAR
libDirName 'APP-INF/lib'
deploymentDescriptor { // custom entries for application.xml:
// fileName = "application.xml" // same as the default value
// version = "6" // same as the default value
applicationName = "customear"
initializeInOrder = true
displayName = "Custom Ear" // defaults to project.name
// defaults to project.description if not set
description = "My customized EAR for the Gradle documentation"
// libraryDirectory = "APP-INF/lib" // not needed, above libDirName setting does this
// module("my.jar", "java") // won't deploy as my.jar isn't deploy dependency
// webModule("my.war", "/") // won't deploy as my.war isn't deploy dependency
securityRole "admin"
securityRole "superadmin"
withXml { provider -> // add a custom node to the XML
provider.asNode().appendNode("data-source", "my/data/source")
}
}
}
Then for your war, use the 'war plugin'. You can create the war as a separate project:
configurations {
moreLibs
}
repositories {
flatDir { dirs "lib" }
mavenCentral()
}
dependencies {
compile module(":compile:1.0") {
dependency ":compile-transitive-1.0#jar"
dependency ":providedCompile-transitive:1.0#jar"
}
providedCompile "javax.servlet:servlet-api:2.5"
providedCompile module(":providedCompile:1.0") {
dependency ":providedCompile-transitive:1.0#jar"
}
runtime ":runtime:1.0"
providedRuntime ":providedRuntime:1.0#jar"
testCompile "junit:junit:4.12"
moreLibs ":otherLib:1.0"
}
war {
from 'src/rootContent' // adds a file-set to the root of the archive
webInf { from 'src/additionalWebInf' } // adds a file-set to the WEB-INF dir.
classpath fileTree('additionalLibs') // adds a file-set to the WEB-INF/lib dir.
classpath configurations.moreLibs // adds a configuration to the WEB-INF/lib dir.
webXml = file('src/someWeb.xml') // copies a file to WEB-INF/web.xml
}
There is another helpful post on creating them as a single project, but that's definitely a bit more 'dicey':
https://discuss.gradle.org/t/single-project-with-jar-ejb-war-and-ear/5874
Until now I created runnable JAR files via the Eclipse "Export..." functionallity but now I switched to IntelliJ IDEA and Gradle for build automation.
Some articles here suggest the "application" plugin, but this does not entirely lead to the result I expected (just a JAR, no start scripts or anything like this).
How can I achieve the same result Eclipse does with the "Export..." dialog?
An executable jar file is just a jar file containing a Main-Class entry in its manifest. So you just need to configure the jar task in order to add this entry in its manifest:
jar {
manifest {
attributes 'Main-Class': 'com.foo.bar.MainClass'
}
}
You might also need to add classpath entries in the manifest, but that would be done the same way.
See http://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html
If you already have defined an application context, you can re-use the definition rather than duplicate it:
application {
// Define the main class for the application.
mainClass = 'com.foo.bar.MainClass'
}
jar {
manifest {
attributes 'Main-Class': application.mainClass
}
}
Both JB Nizet and Jorge_B's answers are correct.
In its simplest form, creating an executable JAR with Gradle is just a matter of adding the appropriate entries to the manifest. However, it's much more common to have dependencies that need to be included on the classpath, making this approach tricky in practice.
The application plugin provides an alternate approach; instead of creating an executable JAR, it provides:
a run task to facilitate easily running the application directly from the build
an installDist task that generates a directory structure including the built JAR, all of the JARs that it depends on, and a startup script that pulls it all together into a program you can run
distZip and distTar tasks that create archives containing a complete application distribution (startup scripts and JARs)
A third approach is to create a so-called "fat JAR" which is an executable JAR that includes not only your component's code, but also all of its dependencies. There are a few different plugins that use this approach. I've included links to a few that I'm aware of; I'm sure there are more.
shadow
one-jar
spring-boot
capsule
Least effort solution for me was to make use of the gradle-shadow-plugin
Besides applying the plugin all that needs to be done is:
Configure the jar task to put your Main class into manifest
jar {
manifest {
attributes 'Main-Class': 'com.my.app.Main'
}
}
Run the gradle task
./gradlew shadowJar
Take the app-version-all.jar from build/libs/
And finally execute it via:
java -jar app-version-all.jar
As others have noted, in order for a jar file to be executable, the application's entry point must be set in the Main-Class attribute of the manifest file. If the dependency class files are not collocated, then they need to be set in the Class-Path entry of the manifest file.
I have tried all kinds of plugin combinations and what not for the simple task of creating an executable jar and somehow someway, include the dependencies. All plugins seem to be lacking one way or another, but finally I got it like I wanted. No mysterious scripts, not a million different mini files polluting the build directory, a pretty clean build script file, and above all: not a million foreign third party class files merged into my jar archive.
The following is a copy-paste from here for your convenience..
[How-to] create a distribution zip file with dependency jars in subdirectory /lib and add all dependencies to Class-Path entry in the manifest file:
apply plugin: 'java'
apply plugin: 'java-library-distribution'
repositories {
mavenCentral()
}
dependencies {
compile 'org.apache.commons:commons-lang3:3.3.2'
}
// Task "distZip" added by plugin "java-library-distribution":
distZip.shouldRunAfter(build)
jar {
// Keep jar clean:
exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.MF'
manifest {
attributes 'Main-Class': 'com.somepackage.MainClass',
'Class-Path': configurations.runtime.files.collect { "lib/$it.name" }.join(' ')
}
// How-to add class path:
// https://stackoverflow.com/questions/22659463/add-classpath-in-manifest-using-gradle
// https://gist.github.com/simon04/6865179
}
Hosted as a gist here.
The result can be found in build/distributions and the unzipped contents look like this:
lib/commons-lang3-3.3.2.jar
MyJarFile.jar
Contents of MyJarFile.jar#META-INF/MANIFEST.mf:
Manifest-Version: 1.0
Main-Class: com.somepackage.MainClass
Class-Path: lib/commons-lang3-3.3.2.jar
This is for Kotlin DSL (build.gradle.kts).
Method 1 (no need for application or other plugins)
tasks.jar {
manifest.attributes["Main-Class"] = "com.example.MyMainClass"
// OR another notation
// manifest {
// attributes["Main-Class"] = "com.example.MyMainClass"
// }
}
If you use any external libraries, use below code. Copy library JARs in libs sub-directory of where you put your result JAR. Make sure your library JAR files do not contain space in their file name.
tasks.jar {
manifest.attributes["Main-Class"] = "com.example.MyMainClass"
manifest.attributes["Class-Path"] = configurations
.runtimeClasspath
.get()
.joinToString(separator = " ") { file ->
"libs/${file.name}"
}
}
Note that Java requires us to use relative URLs for the Class-Path attribute. So, we cannot use the absolute path of Gradle dependencies (which is also prone to being changed and not available on other systems). If you want to use absolute paths, maybe this workaround will work.
Create the JAR with the following command:
./gradlew jar
The result JAR will be created in build/libs/ directory by default.
Method 2: Embedding libraries (if any) in the result JAR (fat or uber JAR)
tasks.jar {
manifest.attributes["Main-Class"] = "com.example.MyMainClass"
val dependencies = configurations
.runtimeClasspath
.get()
.map(::zipTree) // OR .map { zipTree(it) }
from(dependencies)
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
Creating the JAR is exactly the same as the previous method.
Method 3: Using the Shadow plugin (to create a fat or uber JAR)
plugins {
id("com.github.johnrengelman.shadow") version "6.0.0"
}
// Shadow task depends on Jar task, so these will be reflected for Shadow as well
tasks.jar {
manifest.attributes["Main-Class"] = "org.example.MainKt"
}
Create the JAR with this command:
./gradlew shadowJar
See Shadow documentations for more information about configuring the plugin.
Running the created JAR
java -jar my-artifact.jar
The above solutions were tested with:
Java 17
Gradle 7.1 (which uses Kotlin 1.4.31 for .kts build scripts)
See the official Gradle documentation for creating uber (fat) JARs.
For more information about manifests, see Oracle Java Documentation: Working with Manifest files.
Note that your resource files will be included in the JAR file automatically (assuming they were placed in /src/main/resources/ directory or any custom directory set as resources root in the build file). To access a resource file in your application, use this code (note the / at the start of names):
Kotlin
val vegetables = MyClass::class.java.getResource("/vegetables.txt").readText()
// Alternative ways:
// val vegetables = object{}.javaClass.getResource("/vegetables.txt").readText()
// val vegetables = MyClass::class.java.getResourceAsStream("/vegetables.txt").reader().readText()
// val vegetables = object{}.javaClass.getResourceAsStream("/vegetables.txt").reader().readText()
Java
var stream = MyClass.class.getResource("/vegetables.txt").openStream();
// OR var stream = MyClass.class.getResourceAsStream("/vegetables.txt");
var reader = new BufferedReader(new InputStreamReader(stream));
var vegetables = reader.lines().collect(Collectors.joining("\n"));
You can use the SpringBoot plugin:
plugins {
id "org.springframework.boot" version "2.2.2.RELEASE"
}
Create the jar
gradle assemble
And then run it
java -jar build/libs/*.jar
Note: your project does NOT need to be a SpringBoot project to use this plugin.
Have you tried the 'installApp' task? Does it not create a full directory with a set of start scripts?
http://www.gradle.org/docs/current/userguide/application_plugin.html
Thank you Konstantin, it worked like a charm with few nuances. For some reason, specifying main class as part of jar manifest did not quite work and it wanted the mainClassName attribute instead. Here is a snippet from build.gradle that includes everything to make it work:
plugins {
id 'java'
id 'com.github.johnrengelman.shadow' version '1.2.2'
}
...
...
apply plugin: 'application'
apply plugin: 'com.github.johnrengelman.shadow'
...
...
mainClassName = 'com.acme.myapp.MyClassMain'
...
...
...
shadowJar {
baseName = 'myapp'
}
After running gradle shadowJar you get myapp-{version}-all.jar in your build folder which can be run as java -jar myapp-{version}-all.jar.
You can define a jar artifact in the module settings (or project structure).
Right click the module > Open module settings > Artifacts > + > JAR > from modules with dependencies.
Set the main class.
Making a jar is then as easy as clicking "Build artifact..." from the Build menu. As a bonus, you can package all the dependencies into a single jar.
Tested on IntelliJ IDEA 14 Ultimate.
I checked quite some links for the solution, finally did the below mentioned steps to get it working. I am using Gradle 2.9.
Make the following changes in your build,gradle file :
Mention plugin:
apply plugin: 'eu.appsatori.fatjar'
Provide the Buildscript:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "eu.appsatori:gradle-fatjar-plugin:0.3"
}
}
Provide the Main Class:
fatJar {
classifier 'fat'
manifest {
attributes 'Main-Class': 'my.project.core.MyMainClass'
}
exclude 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.SF'
}
Create the fatjar:
./gradlew clean fatjar
Run the fatjar from /build/libs/ :
java -jar MyFatJar.jar
Here is the solution I tried with Gradle 6.7
Runnable fat Jar (with all dependent libraries copied to the jar)
task fatJar(type: Jar) {
manifest {
attributes 'Main-Class': 'com.example.gradle.App'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
} with jar
}
Runnable jar with all dependencies copied to a directory and adding the classpath to the manifest
def dependsDir = "${buildDir}/libs/dependencies/"
task copyDependencies(type: Copy) {
from configurations.compile
into "${dependsDir}"
}
task createJar(dependsOn: copyDependencies, type: Jar) {
manifest {
attributes('Main-Class': 'com.example.gradle.App',
'Class-Path': configurations.compile.collect { 'dependencies/' + it.getName() }.join(' ')
)
}
with jar
}
How to use ?
Add the above tasks to build.gradle
Execute gradle fatJar //create fatJar
Execute gradle createJar // create jar with dependencies copied.
More details : https://jafarmlp.medium.com/a-simple-java-project-with-gradle-2c323ae0e43d
Configure Main Class to your Manifest
If you are using gradle project, just add the following into your build.gradle
jar {
manifest {
attributes(
'Main-Class': 'pokerhandscorer.PokerHandScorer'
)
}
}
Where 'pokerhandscorer' is the name of the package name,
and PokerHandScorer is the main class name
This creates a jar file into your \build\libs{jarFilename}.jar
Run jar file using java -jar /{path}/{jarFileName.jar}
java -jar /{path}/{jarFileName.jar}
As for now we have a project structure with single source folder named src, which contains source code for three modules. What I want to do is:
1) Compile source code. This is easily done with sourceSets definition:
sourceSets {
main {
java {
srcDir 'src'
}
}
}
2) Put compilation results into three jars. I am doing this via three 'jar' type tasks:
I am doing this now via three separate tasks:
util.jar
task utilJar(type: Jar) {
from(sourceSets.main.output) {
include "my/util/package/**"
}
}
client.jar
task clientJar(type: Jar) {
from(sourceSets.main.output) {
include "my/client/package/**"
}
}
server.jar
task serverJar(type: Jar) {
from(sourceSets.main.output) {
include "**"
}
excludes.addAll(utilJar.includes)
excludes.addAll(clientJar.includes)
}
The thing is that server.jar should contain all classes that are not contained within client.jar and util.jar. In ant build script we solve this problem by using difference ant task. How this can be done in gradle (my current approach doesn't work)?
Maybe my approach is completely wrong. Please advice.
P.S. as for now we CAN NOT change the project source code folder structure.
I will post my working solution here as an answer (I've got a hint on gradle's forum).
The scopes in gradle are very strange thing :) I thought that every task definition creates an object of some 'Task' class, which is something like 'JarTask' in this particular case. Then I can access any property of the class from anywhere in my build.gradle script. However, I found the only place where I can see the patterns, which are included in jar file - inside a from block of a task. So my working solution for now is to:
1) Define a project-level collection to contain patterns to be excluded from server.jar
2) Exclude all patterns in from block of serverJar task.
Please see final version below
sourceSets {
main {
java {
srcDir 'src'
}
}
}
// holds classes included into client.jar and util.jar, so they are to be excluded from server.jar
ext.serverExcludes = []
// util.jar
task utilJar(type: Jar) {
from(sourceSets.main.output) {
include "my/util/package/**"
project.ext.serverExcludes.addAll(includes)
}
}
// client.jar
task clientJar(type: Jar) {
from(sourceSets.main.output) {
include "my/client/package/**"
project.ext.serverExcludes.addAll(includes)
}
}
// server.jar
task serverJar(type: Jar) {
from(sourceSets.main.output) {
exclude project.ext.serverExcludes
}
}
I think the approach is wrong. I recommend making a project with 3 sub projects.
project
- util
- server (depends on util)
- client (depends on util)
If for some reason you cannot change the class structure use this kind of build files:
settings.gradle
include 'util', 'client', 'server'
build.gradle
subprojects {
apply plugin: 'java'
}
project(':util') {
sourceSets {
main {
java {
srcDir '../src'
include 'util/**'
}
}
}
}
project(':server') {
sourceSets {
main {
java {
srcDir '../src'
include 'server/**'
}
}
}
dependencies {
compile project(':util')
}
}
project(':client') {
sourceSets {
main {
java {
srcDir '../src'
include 'client/**'
}
}
}
dependencies {
compile project(':util')
}
}
You still need directories for subprojects but the sources are in one place as you wanted.
When you run gradle assemble you will have 3 jars with separate set of classes. The advantage of this solution is that we make a proper Gradle multi module project with correct dependencies, not just tasks for building jars.
Please read Multi-Project Builds.
We have the same problem at my company, ie. legacy code that is difficult to migrate into a "good" project structure, and the need to build several jars from the same codebase. We decided to define different sourceSets and build each of the sourceSets using standard Gradle.
We then use iterators to add jar- and javadoc-tasks for each sourceSet:
sourceSets.all { SourceSet sourceSet ->
Task jarTask = tasks.create("jar" + sourceSet.name, Jar.class)
jarTask.from(sourceSet.output)
// Configure other jar task properties: group, description, manifest etc
Task javadocTask = tasks.create("javadoc" + sourceSet.name, Javadoc.class)
javadocTask.setClasspath(sourceSet.output + sourceSet.compileClasspath)
javadocTask.setSource(sourceSet.allJava)
// Extra config for the javadoc task: group, description etc
Task javadocJarTask = tasks.create("javadocJar" + sourceSet.name, Jar.class)
javadocJarTask.setClassifier("javadoc") // adds "-javadoc" to the name of the jar
javadocJarTask.from(javadocTask.outputs)
// Add extra config: group, description, manifest etc
}
I agree in principal with the accepted answer too.
I found a project where the client requires two JAR essentially of the same file except the Manifest is different only by the Class-Path key.
jar {
manifest {
attributes(
"Main-Class": platformMainClass,
"Implementation-Title": platformDisplayName,
"Implementation-Description": platformDescription,
"Platform-Version": platformVersion,
"Implementation-Version": version,
"Build-Assembly-User": System.getProperty("user.name"),
"Build-Assembly-Date": new java.util.Date().toString(),
"Class-Path": configurations.compile.collect { "lib/"+it.getName() }.join(' ')
)
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
exclude( [ 'log4j*.properties', 'uk/gov/acme/secret/product/server/**' ])
}
The same manifest and the source code then is:
task applicationClientJar(type: Jar, description: "Creates the Application Client JAR file.") {
dependsOn compileJava
manifest {
attributes(
"Main-Class": platformMainClass,
"Implementation-Title": platformDisplayName,
"Implementation-Description": platformDescription,
"Platform-Version": platformVersion,
"Implementation-Version": version,
"Assembly-Date": new java.util.Date().toString()
)
}
archiveName = "acme-client-${platformVersion}.jar"
destinationDir = file("${buildDir}/libs")
from sourceSets.main.output
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
exclude( [ 'log4j*.properties', 'uk/gov/acme/secret/product/server/**' }
So Grzegorz notation is correct, because the Gradle should know there are two different JAR with GAVs. Multi-module is the preferred option.
compile "uk.gov.acme.secret:acme:1.0" // CORE
compile "uk.gov.acme.secret:acme-client:1.0"
The only way to configure for this is to use the Multi-Module Gradle project and then add a compile and/or deploy dependency to the core / main project.
project(':common:acme-micro-service-webapp') {
dependencies {
compile project(':common:acme-core')
}
}
Inside the 'acme-micro-service-webapp' project, this ensures that the dependent 'common:acme-core' is compiled first.
PS: I am still trying to figure out a better solution.
PS PS: If you are using Maven as well as, it may be possible to hook on the `install' task.