是否可以使用 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);
错误:
参数类型或 setStatus 方法被参数重载
ColdFusion 无法可靠破译的类型。冷融合 找到 0
与提供的参数匹配的方法。如果这是一个 Java 对象
并且您验证了该方法存在,请使用 javacast 函数
减少歧义。
即使从表面上看,该调用与用户上的方法签名匹配——setStatus(com.geolearning.geonext.webservices.Status)——该类位于不同的类路径上下文中。这就是为什么我得到上面的错误。
最佳答案
Jamie 和我在此离线工作并提出了一个创造性的解决方案 :)
(对于冗长的答案表示歉意,但我认为对于那些发现类加载器和我一样令人困惑的人来说,有必要进行一些解释。如果您对“为什么”方面不感兴趣,请随意跳到最后)。
问题:
问题肯定是由于多个类加载器/路径。显然 CF Web 服务使用动态 URLClassLoader (就像 JavaLoader 一样)。这就是它可以即时加载生成的 Web 服务类的方式,即使这些类不在核心 CF“class path”中。
(基于我有限的理解...)Class loaders遵循等级制度。当涉及多个类加载器时,它们必须遵守一定的规则,否则它们将无法很好地协同工作。规则之一是子类加载器只能“看到”由祖先( parent 、祖 parent 等)加载的对象。他们看不到 sibling 加载的类。
如果您检查由 JavaLoader 创建的对象,另一个由 createObject
创建,它们确实是 sibling ,即 CF 引导类加载器的两个 child 。所以一个不会识别另一个加载的对象,这可以解释为什么 setStatus
通话失败。
鉴于 child 可以看到 parent 加载的对象,显而易见的解决方案是更改对象的构造方式。对调用进行结构化,以便其中一个类加载器最终成为另一个类加载器的父级。奇怪的是,事实证明这比听起来更棘手。尽管尝试了多种组合(包括使用 switchThreadContextClassLoader 方法),但我找不到实现这一目标的方法。
解决方案:
最后我有一个疯狂的想法:不要加载任何 jar 。只需将 Web 服务的加载器用作 parentClassLoader
.它已经在自己的“类路径”中拥有所需的一切:
// display class path of web service class loader
dynamicLoader = webService.getClass().getClassLoader();
dynamicClassPath = dynamicLoader.getURLS();
WriteDump("CLASS PATH: "& dynamicClassPath[1].toString() );
JavaLoader 会自动将它找不到的类的调用委托(delegate)给
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()");
关于web-services - 让 ColdFusion 调用的 Web 服务与 JavaLoader 加载的对象一起工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15506237/