Artifact Dependency: Use JAR when both WAR and JAR artifact present


(David Le Brun) #1

I have two Gradle apps, one, appA, is a SpringBoot app deployed as a WAR to a maven repository, the other, appB, is run as build step for a CI flow. appB is configured to use a mainClass from appA during its run phase via

//appB
apply plugin: 'application'

mainClassName = 'com.appA.package.AppAMainClass'

The problem I run into is that when appA is published as a WAR artifact, the mainClass cannot be found, so cd $APPB_PATH && gradle run
returns:
> Task :run Error: Could not find or load main class com.com.appA.package.AppAMainClass

When I publish appA as a JAR (and clean the maven repository to only include the JAR-packaged artifact), however, I’m able to run appB without a hitch.

Unfortunately I can’t only package and publish appA as a JAR. So in appA I’ve added this to its build.gradle to build both a JAR and WAR:

//appA
	publications {
		mavenWar(MavenPublication) {
			from components.web
		}

		mavenJar(MavenPublication) {
			from components.java
			artifact sourceJar
		}
	}
}

task sourceJar(type: Jar) {
	classifier 'sources'
	from sourceSets.main.allSource
}

This publishes both JAR and WAR artifact of appA to my maven repo when running gradle clean publishToMavenLocal

However, with this config in appA, I try to run appB, the same Could not find or load main class is present, indicating that the WAR of appA is always being used. I’ve tried swapping the order of the entries in the publications{ } clause to no avail (in case it was a time-created issue? idk), so in appB, I added this extra config to my dependencies clause:

//appB
dependencies{
    compile (group:'com.appA.package',name:'appA-app',version:'0.5.0') {
        artifact {
            name = 'appA-app'
            type = 'jar'
        }
    }
}

When running appB with this, I am able to get past the Could not find or load main class, but then other java.lang.NoClassDefFoundError exceptions are raised on the classes that appA and its mainClass depend upon (I’m assuming this is because the artifact{} clause is cherry-picking only the appA-app JAR without any of its dependencies).

SO my question is, how can I publish a WAR and JAR version of an app (appA) and choose the JAR as a dependency in another (appB)?


(David Le Brun) #2

For posterity, I seem to have resolved this issue for now by using the following in the configs for appA and appB to publish the JAR as a separately-named artifact (appA-app-jar) (solution inspired by:
https://docs.gradle.org/current/userguide/publishing_maven.html#sec:identity_values_in_the_generated_pom):

//appA
	publications {
		mavenWar(MavenPublication) {
			from components.web
		}

		mavenJar(MavenPublication) {
			groupId 'com.appA.package'
			artifactId 'appA-app-jar'
			version '0.5.0'
			from components.java
			artifact sourceJar
		}
	}

and

//appB
dependencies{
    compile (group:'com.appB.package',name:'appB-app-jar',version:'0.5.0') 
}

If there are other or better solutions, I’d be happy to know!