web-services - 让 ColdFusion 调用的 Web 服务与 JavaLoader 加载的对象一起工作

标签 web-services coldfusion 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);

错误:
  • 详细信息:要么没有具有指定方法名称的方法,要么
    参数类型或 setStatus 方法被参数重载
    ColdFusion 无法可靠破译的类型。冷融合 找到 0
    与提供的参数匹配的方法。如果这是一个 Java 对象
    并且您验证了该方法存在,请使用 javacast 函数
    减少歧义。
  • 消息:未找到 setStatus 方法。
  • 方法名称 setStatus

  • 即使从表面上看,该调用与用户上的方法签名匹配——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 and Parent class loader of the two objects

    鉴于 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/

    相关文章:

    windows - 如何在 Windows 中管理 PATH 变量?

    web-services - 在 SharePoint 中复制 Web 服务 for Office 365

    android - OkHttp - 启用日志

    json - 使用 ColdFusion 为 HighCharts 格式化 JSON 数据

    coldfusion - CFQueryParam 对值进行四舍五入

    dynamic - 如何根据查询名称变量动态访问 cfoutput 的查询?

    使用 jar 运行时,Java 不遵循 -cp 选项的类路径规范

    .net - 一个大型网络服务还是许多小型网络服务?

    web-services - wsdl 2 java : deploy a web service with apache cxf

    java - 可以为-classpath提供相对路径(java)