获取ColdFusion调用的Web服务以使用JavaLoader负载对象 [英] Getting ColdFusion-Called Web Service to Work with JavaLoader-Loaded Objects

查看:184
本文介绍了获取ColdFusion调用的Web服务以使用JavaLoader负载对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有可能使用JavaLoader获取由CF调用的Web服务返回的对象,并且JavaLoader加载的对象是同一个类路径上下文吗?我是说,没有很多困难?

  //获取Web服务
ws = createObject(webservice,local.lms.wsurl);
//由coldfusion创建的用户
user = ws.GenerateUserObject();
/ *由java loader创建的用户状态。
**这个api提供程序要求您移动stubs
**(第一次从CF中击中wsdl时生成)
**到类路径。
**这是从中调用的存根/类之一。
* /
UserStatus = javaLoader.create(com.geolearning.geonext.webservices.Status);
//设置用户状态:classpath context clash
user.setStatus(UserStatus.Active);

错误:




  • 详细信息:没有指定方法名和
    参数类型的方法,或setStatus方法重载了参数
    ColdFusion无法可靠地解码的类型。 ColdFusion发现匹配提供的参数的0
    方法。如果这是一个Java对象
    ,并且您验证该方法存在,请使用javacast函数
    减少歧义。

  • 消息:找不到setStatus方法。

  • MethodName setStatus



即使表面上的调用匹配方法签名user - setStatus(com.geolearning.geonext.webservices.Status) - 类位于不同的类路径上下文。这是为什么我得到上面的错误。

解决方案

Jamie和我在这个离线工作, )



(对于长答案,抱歉,但我认为有些解释是为那些发现类加载器混乱像我一样如果你不感兴趣


$ b

$ b

这个问题绝对是由于多个类加载器/路径。显然CF Web服务使用动态 方法)。



解决方案:

最后我有一个疯狂的想法:不要加载任何罐子。只需使用Web服务的加载器作为 parentClassLoader 。它已经在其自己的类路径中拥有所需的一切:

  //显示web服务类装载器的类路径
dynamicLoader = webService.getClass()。getClassLoader();
dynamicClassPath = dynamicLoader.getURLS();
WriteDump(CLASS PATH:& dynamicClassPath [1] .toString());

JavaLoader将自动委派对它无法找到的类的调用 parentClassLoader - 和bingo - 一切正常。没有更多的类装入器冲突。

  webService = createObject(webservice,webserviceURL,webserviceArgs); 
javaLoader = createObject(component,javaloader.JavaLoader)。init(
loadPaths = [] // nothing
,parentClassLoader = webService.getClass()。getClassLoader $ b);

user = webService.GenerateUserObject();
userStatus = javaLoader.create(com.geolearning.geonext.webservices.Status);
user.setStatus(userStatus.Active);
WriteDump(var = user.getStatus(),label =SUCCESS:user.getStatus());


Is it possible to use JavaLoader to get objects returned by CF-called web services, and JavaLoader-loaded objects to be the same classpath context? I mean, without a lot of difficulty?

// 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);

Error:

  • Detail: Either there are no methods with the specified method name and argument types or the setStatus method is overloaded with argument types that ColdFusion cannot decipher reliably. ColdFusion found 0 methods that match the provided arguments. If this is a Java object and you verified that the method exists, use the javacast function to reduce ambiguity.
  • Message: The setStatus method was not found.
  • MethodName setStatus

Even though the call, on the surface, matches a method signature on user--setStatus(com.geolearning.geonext.webservices.Status)--the class is on a different classpath context. That's why I get the error above.

解决方案

Jamie and I worked on this off-line and came up with a creative solution :)

(Apologies for the long answer, but I thought a bit of an explanation was warranted for those who find class loaders as confusing as I do. If you are not interested in the "why" aspect, feel free to jump to the end).

Issue:

The problem is definitely due to multiple class loaders/paths. Apparently CF web services use a dynamic URLClassLoader (just like the JavaLoader). That is how it can load the generated web service classes on-the-fly, even though those classes are not in the core CF "class path".

(Based on my limited understanding...) Class loaders follow a hierarchy. When multiple class loaders are involved, they must observe certain rules or they will not play well together. One of the rules is that child class loaders can only "see" objects loaded by an ancestor (parent, grandparent, etcetera). They cannot see classes loaded by a sibling.

If you examine the object created by the JavaLoader, and the other by createObject, they are indeed siblings ie both children of the CF bootstrap class loader. So the one will not recognize objects loaded by the other, which would explain why the setStatus call failed.

Given that a child can see objects loaded by a parent, the obvious solution is to change how the objects are constructed. Structure the calls so that one of the class loaders ends up as a parent of the other. Curiously that turned out to be trickier than it sounded. I could not find a way to make that happen, despite trying a number of combinations (including using the switchThreadContextClassLoader method).

Solution:

Finally I had a crazy thought: do not load any jars. Just use the web service's loader as the parentClassLoader. It already has everything it needs in its own individual "class path":

    // display class path of web service class loader
    dynamicLoader = webService.getClass().getClassLoader();
    dynamicClassPath = dynamicLoader.getURLS();
    WriteDump("CLASS PATH: "& dynamicClassPath[1].toString() );

The JavaLoader will automatically delegate calls for classes it cannot find to parentClassLoader - and bingo - everything works. No more more class loader conflict.

    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()");

这篇关于获取ColdFusion调用的Web服务以使用JavaLoader负载对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆