【问题标题】:Coldfusion - Component undefinedColdfusion - 组件未定义
【发布时间】:2018-12-21 14:45:49
【问题描述】:

我在我的 ColdFusion 应用程序中广泛使用组件,并且经常遇到我的组件未定义的错误,尽管它们确实已定义。

我在我的 Application.cfc 文件中定义组件。

 <cfset cfcList = "component1,component2,component3">
 <cfloop list="#cfcList#" index="local.thisCfcName">
      <cfset application.cfc[local.thisCfcName] = createObject(
        "component",
        "#application.cfcPath##local.thisCfcName#"
      )>
  </cfloop>

我已经能够确定:在我的 onRequestStart 函数中,我在遇到“init”url 变量时重新启动应用程序:

<cfif structKeyExists(url, "init")>
  <cfset onApplicationStart()>
</cfif>

似乎在应用程序重新初始化时,任何其他尝试访问该组件的用户都会收到以下错误(失败的组件可能会有所不同)。

[diag]=元素 CFC.COMPONENT1 在类 [Ljava.lang.String; 类型的 Java 对象中未定义;引用为 ''

我在这里做错了什么可以解决这个问题吗?我每天都会遇到几次这些错误,并且必须有解决方案,但我无法找到有关此特定问题的任何信息。

【问题讨论】:

  • 你为什么要频繁重启应用程序?
  • 这可能不是你想要的。您可能想要onSessionStartonRequestStart。如果您对应用程序进行频繁的代码更改,因此这是一个问题,您还应该重新考虑您的代码交付管道
  • "我见过的每个示例应用程序都这样做。"出于好奇,您在哪里看到这些示例?它们真的被用于你认为它们被使用的东西吗?频繁的应用程序开始接收新代码,听起来您要么过于频繁地部署到生产环境,要么是在生产环境中开发!>。
  • 我从未见过 cf 应用程序在每次用户执行某项操作时都会刷新它的缓存组件。我见过很多网站通过在 onRequestStart() 中调用 onApplicationStart() 来允许某种形式的应用程序刷新,但它通常很少由管理员/开发人员触发。为什么生产环境中的代码更改如此频繁,以至于您让普通用户触发应用刷新?
  • 您应该注意的另一个问题是,如果我自动调用大量 https://yourwebsite.com?init,那么我可以轻松地 DOS 您的站点。我建议,如果您需要该功能,可以进行一些严格的速率限制检查,甚至更好的方法只允许管理员用户使用它。

标签: coldfusion components


【解决方案1】:

要回答您的问题,您几乎肯定会遇到race conditions。 CF只在application first starts时锁定应用范围:

在 ColdFusion 收到应用程序中的第一个页面请求时运行

之后,如果你显式调用OnApplicationStart()

... ColdFusion 不启动应用程序;它确实执行 方法代码,但 不锁定应用程序范围,而该方法 执行

因此,任何其他尝试从应用程序范围读取的线程/请求都可能出错,因为第一个线程同时仍在修改范围。您需要一个 exclusive application cflock 来防止任何其他线程访问范围,直到修改完成。

顺便说一句,虽然它不会完全消除竞争条件的可能性,但使用单独的变量进行初始化并仅在完成时分配,会减少发生冲突的机会窗口:

 <cfloop ...> 
     <cfset local.someVariable[key] = ....>
 </cfloop>

 <cfset application.someVariable = local.someVariable>

说了这么多,我同意你绝对不想如此频繁地刷新应用程序范围。

【讨论】:

  • 我认为applicationStop() 会导致onApplicationStart() 的常规行为触发,因为它会停止应用程序然后使其正常重新启动。不过我不确定。我需要测试。
  • 虽然常规行为可能除了重新填充应用程序范围之外还包括其他内容......
  • 我认为onApplicationStart() 不仅仅是一个函数。所以直接调用它只会调用函数内部的任何内容。而调用applicationStop() 实际上会停止应用程序,然后下一次调用实质上会重新启动应用程序。所以在onApplicationStart() 之前发生的任何魔法仍然会触发,然后是onApplicationStart()。我认为通过停止它并让它自行重新启动它应该是线程安全的。应用引擎的乐趣,对吧? :-)
  • 是的,我正在考虑类似的事情(惊喜,惊喜)。我的意思是,应该记住这样做可能会触发除刷新应用程序范围之外的其他任务/魔法。这不是问题,只是需要注意的一点,即它可能比调用 onApplication start 做的更多
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多