Classpath hell - SoapUI and Gradle API logging conflicts

I’ve been trying to create a SoapUI plugin for Gradle for an age, but I keep hitting classpath issues and getting discouraged. At the moment I keep getting the following error:

* What went wrong:
Execution failed for task ':mockServiceRunner'.
> org.apache.log4j.ConsoleAppender.setWriter(Ljava/io/Writer;)V

or more specifically:

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':mockServiceRunner'.
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
	at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
	at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
	at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
	at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:42)
	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
	at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
	at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:310)
	at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.executeTask(AbstractTaskPlanExecutor.java:79)
	at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:63)
	at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:51)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:23)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:88)
	at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
	at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
	at org.gradle.execution.DefaultBuildExecuter.access$200(DefaultBuildExecuter.java:23)
	at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:68)
	at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
	at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
	at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:55)
	at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:149)
	at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:106)
	at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:86)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:117)
	at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:55)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:34)
	at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:40)
	at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:169)
	at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:237)
	at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:210)
	at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:35)
	at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24)
	at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:206)
	at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:169)
	at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)
	at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)
	at org.gradle.launcher.Main.doAction(Main.java:33)
	at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)
	at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:54)
	at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:35)
	at org.gradle.launcher.GradleMain.main(GradleMain.java:23)
	at org.gradle.wrapper.BootstrapMainStarter.start(BootstrapMainStarter.java:30)
	at org.gradle.wrapper.WrapperExecutor.execute(WrapperExecutor.java:127)
	at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)
Caused by: java.lang.NoSuchMethodError: org.apache.log4j.ConsoleAppender.setWriter(Ljava/io/Writer;)V
	at com.eviware.soapui.tools.AbstractSoapUIRunner.initGroovyLog(AbstractSoapUIRunner.java:75)
	at com.eviware.soapui.tools.SoapUIMockServiceRunner.runRunner(SoapUIMockServiceRunner.java:96)
	at com.eviware.soapui.tools.AbstractSoapUIRunner.run(AbstractSoapUIRunner.java:158)
	at com.eviware.soapui.tools.AbstractSoapUIRunner$run$0.call(Unknown Source)
	at build_26aioq0jxku8qz95jg2bloizv$_run_closure3_closure6.doCall(/Users/willis7/batcave/soapui-api-example/build.gradle:45)
	at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:558)
	at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:539)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
	... 47 more

The build script I have is as follows:

buildscript{
    repositories {
        mavenCentral()
        maven { url 'http://www.eviware.com/repository/maven2/' }
    }

    dependencies {
        classpath ('eviware:maven-soapui-plugin:4.5.1') {
            exclude( module: 'jtidy' )
            exclude( module: 'jms' )
        }
    }
}

ext {
    projectFile = "calculator-soapui-project.xml"
}

import com.eviware.soapui.tools.SoapUITestCaseRunner
import com.eviware.soapui.tools.SoapUIMockServiceRunner

task testCaseRunner(description: 'Run SoapUITestCaseRunner', group: 'SoapUI') {
    inputs.property('projectFile', projectFile)

    doLast {
        SoapUITestCaseRunner testCaseRunner = new SoapUITestCaseRunner()

        try{
            testCaseRunner.setProjectFile(projectFile)
            testCaseRunner.run()
        } catch (Exception e) {
            throw new GradleException(e.message)
        }
    }
}

task mockServiceRunner(description: 'Run SoapUIMockServiceRunner', group: 'SoapUI') {
    inputs.property('projectFile', projectFile)

    doLast {
        SoapUIMockServiceRunner mockServiceRunner = new SoapUIMockServiceRunner()

        try{
            mockServiceRunner.setProjectFile(projectFile)
            mockServiceRunner.run()
        } catch (Exception e) {
            throw new GradleException(e.message)
        }
    }
}

wrapper {
    gradleVersion = "2.4-20150326230024+0000"
}

If you want to try this script you can download the SoapUI project file from, here.

I’m fairly confident this is a classpath issue because I have simply reused the source code you can see in this Github example.

Is there anything bleedingly obvious that I am missing?

Seems like your soapui code depends on a particular version of log4j, but something else is pulling in a different version. You’ll need to run with “–debug” to see what jars are being referenced.

Sorry for the delayed reply. I believe the conflict is with the gradle API itself. The example that I included on github doesnt include the Gradle Api and does not appear to have the same issue.

You’re basically running into the same sort of problem as this topic: Dealing with plugin classpath conflicts and Classpath / classloader conflicts with other plugins in the buildscript

The issue here is the dependency comes through gradleApi() and there’s not a way to override it. We include a log4j-over-slf4j dependency that contains those same classes.

For your particular case, I think it might make sense to make your Soap related tasks JavaExec’s and fork a separate process rather than run that code within the Gradle process.

Thanks Sterling.

JavaExec’s don’t feel like the right option for this scenario as I want to extend the plugin and work with the API.

It’s a shame the classpath isolation issue isn’t higher on the priority list. We typically create plugins to make our lives easier, but in my case the path of least resistance is to not use Gradle. :confused:

Ah, sorry. I thought it was just a custom test runner.

You could extend SoapUIMockServiceRunner and override the initGroovyLog() method to do nothing (or at least, something different). That might get you past this and see if there are any other runtime problems.

2 Likes

Is this a similar problem to what I hit with this SO posting? I was able to manually exclude the problematic jar from my build and runtime (although I had to do them both separately).

Sterling, you are a star!

That did the trick! It opened another can of worms elsewhere :stuck_out_tongue: but, for all intents and purposes that solved original problem.

Thank you!