Multiple Java API provider dependencies in tests


(Jordan Gigov) #1

To start off, I’m not big on the build-system side of programming and typically rely on my IDE for that.

What I’m making is a little plugin for Hibernate that loads along-side it via standard ServiceLoader mechanics, but it requires another third-party API implementing JSR-353, a.k.a. a javax.json provider. I want it to be useful with any JSON provider, not just Glassfish, but I can’t seem to make tests load each of them.

So far, the test I have to verify which provider is loaded contains this:

@Test
public void findProvider() {
	JsonProvider jp = JsonProvider.provider();
	String expected = System.getProperty("expect.provider");
	assertEquals("Wrong provider", expected, jp.getClass().getCanonicalName());
}

And this is what I came-up with for my build.gradle.

dependencies {
	compile group: 'org.hibernate', name: 'hibernate-core', version: '5.1.0.Final'
	compile group: 'javax.json', name: 'javax.json-api', version: '1.0'
    testCompile group: 'junit', name: 'junit', version: '4.10'
}

task compile
compile.dependsOn compileJava, processResources, compileTestJava, processTestResources

task testProviderGlassfish(type:Test, dependsOn: compile) {
	systemProperty 'expect.provider', 'org.glassfish.json.JsonProviderImpl'
	dependencies {
		testRuntime group: 'org.glassfish', name: 'javax.json', version: '1.0.4'
	}
}

task testProviderJohnzon(type:Test, dependsOn: compile) {
	systemProperty 'expect.provider', 'org.apache.johnzon.core.JsonProviderImpl'
	dependencies {
		testRuntime group: 'org.apache.johnzon', name: 'johnzon-core', version: '0.9.5'
	}
}

task testProviderJackson(type:Test, dependsOn: compile) {
	systemProperty 'expect.provider', 'org.apache.johnzon.core.JsonProviderImpl'
	dependencies {
		testRuntime group: 'com.github.pgelinas', name: 'jackson-javax-json', version: '0.9.0'
	}
}

test.dependsOn testProviderGlassfish, testProviderJohnzon, testProviderJackson

The problem is that in all three test tasks, the only loaded dependency is the last one jackson-javax-json.
I knew I couldn’t get this to work on Maven, but I thought It should work if I move to Gradle.

I don’t know if I’m simply doing it wrong, or if I’m looking for a non-existing feature, or I’ve run into a bug of some sorts, but my understanding is that the dependencies per task shouldn’t conflict with each-other like that.


(Alexander Volanis) #2

I am not sure where you found the notion that dependencies can be per task but from what I know of Gradle dependencies is a representation of the Project.getDependencies() method which is a DependencyHandler interface instance.

Having said that here is how you can do exactly what you want with Gradle

configurations {
    glassfish
    johnzon
    jackson
}
dependencies {
    glassfish group: 'org.glassfish', name: 'javax.json', version: '1.0.4'
    johnzon group: 'org.apache.johnzon', name: 'johnzon-core', version: '0.9.5'
    jackson group: 'com.github.pgelinas', name: 'jackson-javax-json', version: '0.9.0'
}

testProviderGlassfish(type:Test, dependsOn: compile) {
    systemProperty 'expect.provider', 'org.glassfish.json.JsonProviderImpl'
    classpath = classpath + configurations.glassfish.files
}

testProviderJohnzon(type:Test, dependsOn: compile) {
    systemProperty 'expect.provider', 'org.apache.johnzon.core.JsonProviderImpl'
    classpath = classpath + configurations.johnzon.files
}

task testProviderJackson(type:Test, dependsOn: compile) {
    // This line is wrong in your example and I do not have time to find the answer 
    // for you, it should be the jackson provider class
    systemProperty 'expect.provider', 'org.apache.johnzon.core.JsonProviderImpl'
    classpath = classpath + configurations.jackson.files
}

(Jordan Gigov) #3

Thanks for trying, but that doesn’t work either, because of whatever constructor being missing. It never reaches the tests.

And yes, it looks like I’ve pasted the wrong thing on the Jackson provider.
It’s actually com.github.pgelinas.jackson.javax.json.spi.JacksonProvider.
However they’ve neglected to provide the proper file in META-INF/services, so that one will fail either way.

edit: I managed to get it working with this

task testProviderGlassfish(type:Test, dependsOn: compile) {
	systemProperty 'expect.provider', 'org.glassfish.json.JsonProviderImpl'
	classpath = classpath + configurations.glassfish
}

task testProviderJohnzon(type:Test, dependsOn: compile) {
	systemProperty 'expect.provider', 'org.apache.johnzon.core.JsonProviderImpl'
	classpath = classpath + configurations.johnzon
}

test.dependsOn testProviderGlassfish, testProviderJohnzon
test.actions = []

Had to override the actions, because it then tried running with no implementation.
But thanks again. I was looking in the wrong place, trying to modify the dependencies of each task, instead of the classpath.