2

I'm using the javax.mail library to send emails that may or may not contain attachments.

I'm also using Groovy 2.0.6 for writing this script and am developing it in Eclipse and running unit tests using Gradle 1.5. The script I'm writing will be deployed in a jar to many different locations in the future. Therefore, the javax.mail needs to be referenced to from my script and not just manually added to the machine's classpath.

To do this, I am using the following statements in my script:

@GrabConfig(systemClassLoader=true)
@Grab(group='javax.mail', module='mail', version='1.4.7')

My issue is that I am unable to run unit tests with Gradle while the @GrabConfig statement is included. It runs fine with just the @Grab statement but fails when the @GrabConfig is in there. The error message I'm receiving is:

:compileJava UP-TO-DATE
:compileGroovy
startup failed:

General error during conversion: No suitable ClassLoader found for grab

java.lang.RuntimeException: No suitable ClassLoader found for grab
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:77)
        at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:102)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:57)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:182)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:190)
        at groovy.grape.GrapeIvy.chooseClassLoader(GrapeIvy.groovy:181)
        at groovy.grape.GrapeIvy$chooseClassLoader.callCurrent(Unknown Source)
        at groovy.grape.GrapeIvy.grab(GrapeIvy.groovy:247)
        at groovy.grape.Grape.grab(Grape.java:141)
        at groovy.grape.GrabAnnotationTransformation.visit(GrabAnnotationTransformation.java:312)
        at org.codehaus.groovy.transform.ASTTransformationVisitor$3.call(ASTTransformationVisitor.java:319)
        at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:903)
        at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:566)
        at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:542)
        at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:519)
        at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:498)
        at org.gradle.api.internal.tasks.compile.ApiGroovyCompiler.execute(ApiGroovyCompiler.java:118)
        at org.gradle.api.internal.tasks.compile.ApiGroovyCompiler.execute(ApiGroovyCompiler.java:39)
        at org.gradle.api.internal.tasks.compile.daemon.CompilerDaemonServer.execute(CompilerDaemonServer.java:52)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
            at java.lang.reflect.Method.invoke(Method.java:597)
            at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
            at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
            at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:355)
            at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:66)
            at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
            at java.lang.Thread.run(Thread.java:662)

    1 error

    :compileGroovy FAILED

    FAILURE: Build failed with an exception.

According to No suitable classloader found for grab , @GrabConfig makes code untestable.

Is there any alternative to @GrabConfig for my situation?

mkobit
  • 43,979
  • 12
  • 156
  • 150
twbbas
  • 407
  • 3
  • 9
  • 19
  • Add the mail jar to the classpath? – tim_yates May 09 '13 at 21:11
  • @tim_yates As stated in the question, this is not an option for my situation because the jar will be automatically deployed to different machines and I need the javax.mail jar to be referenced and used without any manual steps. – twbbas May 09 '13 at 21:15

2 Answers2

2

You can use the gradle-one-jar plugin to package your own and third-party code into a single executable Jar. Alternatively, you can use Gradle's application plugin to create a Zip distribution with start scripts.

Peter Niederwieser
  • 121,412
  • 21
  • 324
  • 259
2

You can disable grapes in build.gradle like so:

test {                                        
  systemProperty 'groovy.grape.enable', 'false'  
}

compileGroovy {
  groovyOptions.forkOptions.jvmArgs = [ '-Dgroovy.grape.enable=false' ]
}
compileTestGroovy {
  groovyOptions.forkOptions.jvmArgs = [ '-Dgroovy.grape.enable=false' ]
}
Rob Smith
  • 434
  • 4
  • 3