Jam*_*son 4 coldfusion web-services classpath coldfusion-9 javaloader
是否可以使用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);
Run Code Online (Sandbox Code Playgroud)
错误:
即使表面上的调用与user-setStatus(com.geolearning.geonext.webservices.Status)上的方法签名匹配,该类也位于不同的类路径上下文中.这就是我得到上述错误的原因.
杰米和我在这个离线工作,并提出了一个创造性的解决方案:)
(对于长期答案道歉,但我认为对于那些发现类加载器像我一样令人困惑的人来说,有必要作出一些解释.如果你对"为什么"方面不感兴趣,请随意跳到最后).
问题:
问题肯定是由于多个类加载器/路径.显然,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() );
Run Code Online (Sandbox Code Playgroud)
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()");
Run Code Online (Sandbox Code Playgroud)