In a grails project I have added a custom ivy resolver per the reference docs, http://www.grails.org/doc/latest/guide/single.html#12.2%20Plugin%20Repositories .
However, this resolver requires jsch and and some other jars. How can I put them on the project's build classpath so that ivy will use them?
This is my BuildConfig.groovy
grails.project.class.dir = "target/classes"
grails.project.test.class.dir = "target/test-classes"
grails.project.test.reports.dir = "target/test-reports"
grails.project.war.file = "target/${appName}-${appVersion}.war"
//Configure resolver
def sshResolver = new org.apache.ivy.plugins.resolver.SshResolver()
['libraries', 'builds'].each {
sshResolver.addArtifactPattern("/home/ivy/[organisation]/[revision]/[artifact].[ext]")
sshResolver.addIvyPattern("/home/ivy/[organisation]/[revision]/[artifact].[ext]")
}
sshResolver.name = "ssh"
sshResolver.settings = ivySettings
resolver sshResolver
grails.project.dependency.resolution = {
// inherit Grails' default dependencies
inherits("global") {
}
log "warn"
repositories {
grailsPlugins()
grailsHome()
grailsCentral()
ssh()
}
dependencies {
compile 'someorg:somejar:1.0'
runtime 'mysql:mysql-connector-java:5.1.13'
}
}
I had the same problem and got this answer from the Ian Roberts on the Grails user list which works for me:
def myCL = new URLClassLoader([new File(
"${basedir}/lib/the.jar"
).toURI().toURL()] as URL[],
org.apache.ivy.plugins.repository.AbstractRepository.classLoader)
resolver myCL.loadClass('com.whatever.MyResolver').newInstance()
Passing the class loader that loaded Ivy as the parent is important so that it can resolve Ivy classes.
If you need to load multiple jars (because the class you are loading depends on them), then put all the files in the list like so:
def myCL = new URLClassLoader([
"${basedir}/lib/jar1",
"${basedir}/lib/jar2", // etc.
].collect { new File(it).toURI().toURL() } as URL[],
org.apache.ivy.plugins.repository.AbstractRepository.classLoader)
resolver myCL.loadClass('com.whatever.MyResolver').newInstance()
Another option that seems to work is to use @Grab. Something like:
@Grab(group="com.jcraft",module="jsch",version="0.1.42")
import org.apache.ivy.plugins.resolver.SshResolver
def sshResolver = new SshResolver()
['libraries', 'builds'].each {
sshResolver.addArtifactPattern("/home/ivy/[organisation]/[revision]/[artifact].[ext]")
sshResolver.addIvyPattern("/home/ivy/[organisation]/[revision]/[artifact].[ext]")
}
sshResolver.name = "ssh"
sshResolver.settings = ivySettings
resolver sshResolver
If your jar isn't in a public repository, it may be a little trickier.
Grails uses ivy to implement it's dependency management. All you should need to do is declare the extra libraries you need. Have you tried something like this:
dependencies {
..
compile 'com.jcraft:jsch:0.1.42'
..
}
Apparently
grails -cp ./lib/jsch.jar
was the answer, not the -classpath or --classpath that I had initially tried.
If anyone has a better answer I will certainly accept it over mine.
I tried placing the jar in grails/lib but it gets loaded after the resolvers are processed.
I tried this in PreInit.groovy but no luck there either.
grails.compiler.dependencies = { fileset(file:'${basedir}/lib/jsch.jar') }