我创建了以下Groovy脚本来使用Java库转换JSON文档。但不知何故,我无法从我需要的罐子加载类。我总是得到java.lang.ClassNotFoundException: de.is24.gis.geotools.CoordinateTransformer
Jar文件与groovy脚本位于同一目录中。我无法编辑我称之为groovy脚本的方式。它由河流自动调用。
import groovy.json.JsonSlurper
geo = new GeoTransformer()
geo.transform(ctx.document)
class GeoTransformer {
void transform(doc) {
this.getClass().classLoader.addURL(new File("gis-geotools-1.9.0.jar").toURL())
def CoordinateTransformer = Class.forName("de.is24.gis.geotools.CoordinateTransformer").newInstance();
def x = doc.realEstateCommonData.locationDto.geoCoordinateDto.xCoordinate;
def y = doc.realEstateCommonData.locationDto.geoCoordinateDto.yCoordinate;
def coords = CoordinateTransformer.transformFromLambertEuToWgs84(x,z)
println coords.getLatitude()
println coords.getLongitude()
def jsonObj = new JsonSlurper().parseText( '{"type" : "Point", "coordinates" : [' + coords.getLatitude() + ',' + coords.getLongitude() + ']}' )
doc.location = jsonObj
}
}
答案 0 :(得分:0)
不确定为什么你无法访问rooLoader,它必须与Groovy脚本的执行方式有关。
你可以尝试这个(显然未经测试)
class GeoTransformer {
void transform( doc ) {
def urlLoader = new GroovyClassLoader()
urlLoader.addURL( new File("gis-geotools-1.9.0.jar").toURL() )
def coordTransformer = Class.forName( "de.is24.gis.geotools.CoordinateTransformer",
true,
urlLoader ).newInstance()
def x = doc.realEstateCommonData.locationDto.geoCoordinateDto.xCoordinate;
def y = doc.realEstateCommonData.locationDto.geoCoordinateDto.yCoordinate;
def coords = coordTransformer.transformFromLambertEuToWgs84( x, z )
println coords.latitude
println coords.longitude
doc.location = [ type:'Point',
coordinates:[ coords.latitude, coords.longitude ] ]
}
}
我摆脱了底部的JsonSlurper
位,直接创建了地图(我假设doc.location
需要是地图)?
这适用于Groovy控制台:
def jar = new File( '/path/to/commons-collections-3.2.1.jar' )
def loader = new GroovyClassLoader()
loader.addURL( jar.toURL() )
def bag = Class.forName( 'org.apache.commons.collections.bag.HashBag',
true,
loader ).newInstance()
bag.add( 'tim' )
println bag
println bag.getClass().name
并打印:
[tim]
org.apache.commons.collections.bag.HashBag
答案 1 :(得分:0)
通过GroovyShell从java运行groovy时遇到了同样的问题。 这个解决方案对我有用,并解决了MeiSign在tim_yates解决方案中提到的依赖加载问题。说明如下:
def thisLoader = this.class.classLoader
// try the "proper" way to find the root classloader
def rootLoader = DefaultGroovyMethods.getRootLoader(thisLoader)
if (rootLoader == null) {
// Root classloader is not a groovy RootLoader, but we still need it,
// so walk up the hierarchy and get the top one (whose parent is null)
// When running from Java this is sun.misc.Launcher.ExtClassLoader
rootLoader = thisLoader
ClassLoader parentLoader = rootLoader.getParent()
while (parentLoader != null) {
rootLoader = parentLoader
parentLoader = parentLoader.getParent()
}
}
rootLoader.addURL(new File("gis-geotools-1.9.0.jar").toURL())
def CoordinateTransformer =
Class.forName("de.is24.gis.geotools.CoordinateTransformer",
true,
rootLoader).newInstance();
使用groovy.lang.GroovyShell.main从java运行groovy时,this.classLoader是GroovyClassLoader.InnerLoader
从命令行groovy.bat运行groovy时,类加载器为org.codehaus.groovy.tools.RootLoader
当您致电getRootLoader
时,它会使用getParent()
向上移动类加载器层次结构 - 直到找到RootLoade
r的实例。如果它没有找到null。 (这个问题标题中的NPE
)
问题在于,当从Java运行时,heirarchy在sun.misc.Launcher.ExtClassLoader
处于顶部,这显然不是一个常规类,更不用说常规的RootLoader了。
具体来说,分层结构是:
GroovyClassLoader.InnerLoader
--> GroovyClassLoader
---> sun.misc.Launcher.AppClassLoader
----> sun.misc.Launcher.ExtClassLoader
------> null
在GroovyMain
中如何以这种方式结束是非常模糊的(但是如果你真的想自己设置它是一个带有ClassLoader的GroovyShell
构造函数)。
无论如何,Tim的解决方案并没有深入开展,因为您正在创建的新ClassLoader仅用于加载该类而不是后续类。您确实需要将类路径条目添加到 root 类路径中。 因此,当groovy root失败时,我只使用了真正的root。
以下是org.codehaus.groovy.runtime.DefaultGroovyMethodsSupport
/**
* Iterates through the classloader parents until it finds a loader with a class
* named "org.codehaus.groovy.tools.RootLoader". If there is no such class
* <code>null</code> will be returned. The name is used for comparison because
* a direct comparison using == may fail as the class may be loaded through
* different classloaders.
*
* @param self a ClassLoader
* @return the rootLoader for the ClassLoader
* @see org.codehaus.groovy.tools.RootLoader
* @since 1.5.0
*/
public static ClassLoader getRootLoader(ClassLoader self) {
while (true) {
if (self == null) return null;
if (isRootLoaderClassOrSubClass(self)) return self;
self = self.getParent();
}
}
private static boolean isRootLoaderClassOrSubClass(ClassLoader self) {
Class current = self.getClass();
while(!current.getName().equals(Object.class.getName())) {
if(current.getName().equals(RootLoader.class.getName())) return true;
current = current.getSuperclass();
}
return false;
}