是否可以使用JavaLoader使CF调用的web服务返回的对象和JavaLoader加载的对象成为相同的类路径上下文?我是说,没有很多困难?
// get a web service
ws = createObject("webservice", local.lms.wsurl);
// user created by coldfusion
user = ws.GenerateUserObject();
/* user status created by java loader.
** this api provider requires that you move the stubs
** (generated when hitting the wsdl from CF for the first time)
** to the classpath.
** this is one of the stubs/classes that gets called from that.
*/
UserStatus = javaLoader.create("com.geolearning.geonext.webservices.Status");
// set user status: classpath context clash
user.setStatus(UserStatus.Active);错误:
尽管表面上的调用匹配user--setStatus(com.geolearning.geonext.webservices.Status)--the类上的方法签名,但它位于不同的类路径上下文中。这就是为什么我得到了上面的错误。
发布于 2013-03-23 21:10:08
杰米和我做了这方面的工作,并想出了一个创造性的解决方案:)
(对冗长的答案表示歉意,但我认为,对于那些像我一样觉得类加载器令人困惑的人来说,有一点解释是应该的。如果你对“为什么”方面不感兴趣,可以自由地跳到最后。
发行:
这个问题肯定是由多个类加载器/路径造成的。显然,CF web服务使用动态URLClassLoader (就像JavaLoader一样)。这就是它如何能够动态加载生成的web服务类,即使这些类不在核心CF "类路径“中。
(根据我有限的理解.) 类装入器遵循层次结构。当涉及多个类加载器时,它们必须遵守某些规则,否则它们将不能很好地合作。其中一条规则是,子类加载器只能“看到”由祖先加载的对象(父类、祖父母等)。它们无法看到由同级加载的类。
如果您检查由JavaLoader创建的对象,以及由createObject创建的另一个对象,那么它们确实是CF引导类加载器的两个子级。因此,其中一个将无法识别由另一个加载的对象,这将解释为什么setStatus调用失败。

考虑到子对象可以看到父对象加载的对象,显而易见的解决方案是更改对象的构造方式。构造调用,以便其中一个类加载器最终成为另一个类加载器的父类。奇怪的是,事实证明,这比听起来更棘手。尽管我尝试了许多组合(包括使用switchThreadContextClassLoader方法),但我还是找不到实现这一目标的方法。
解决方案:
最后,我有了一个疯狂的想法:不要加载任何罐子。只需使用web服务的加载程序作为parentClassLoader。在它自己的“类路径”中,它已经拥有了它所需要的一切:
// display class path of web service class loader
dynamicLoader = webService.getClass().getClassLoader();
dynamicClassPath = dynamicLoader.getURLS();
WriteDump("CLASS PATH: "& dynamicClassPath[1].toString() );JavaLoader将自动将对它找不到的类的调用委托给parentClassLoader,并且一切都正常。不再有类加载器冲突。
webService = createObject("webservice", webserviceURL, webserviceArgs);
javaLoader = createObject("component", "javaloader.JavaLoader").init(
loadPaths = [] // nothing
, parentClassLoader=webService.getClass().getClassLoader()
);
user = webService.GenerateUserObject();
userStatus = javaLoader.create("com.geolearning.geonext.webservices.Status");
user.setStatus(userStatus.Active);
WriteDump(var=user.getStatus(), label="SUCCESS: user.getStatus()");https://stackoverflow.com/questions/15506237
复制相似问题