如何在Grails中仅使用嵌套映射创建ConfigObject?

时间:2014-09-28 04:00:02

标签: grails groovy dsl spring-dsl

可以将基于闭包的配置实现为地图地图吗?

grails {
  acme {
     host = 'localhost'
     poolSettings {
        timeout = 5000
     }
  }
}

以上配置是grails插件的惯例。我们正在进行迁移,由于传统的限制,我们需要动态创建配置以消除对遗留代码的影响。

我从一个简单的配置开始:

grails.acme = [host:'localhost']

这对启动时的插件工作正常,所以我添加了一个嵌套的地图:

grails.acme = [host:'localhost']
def poolProps = //do some work to get pool settings
grails.acme << [poolSettings:poolProps]

启动时我打印grails.acme

{
    "host": "locahost",
    "poolSettings": {
        "timeout": 5000
    }
}

看起来很正常,但是在acme插件失败后不久出现以下错误:

  

2014-09-27 23:27:07,460 [localhost-startStop-1]错误   context.GrailsContextLoader - 初始化应用程序时出错:否   方法签名:AcmePlugin $ _closure2_closure5_closure9 .doCall()   适用于参数类型:(grails.spring.BeanBuilder)值:   [grails.spring.BeanBuilder@7b067fd7]可能的解决方案:   doCall(java.lang.Object,java.lang.Object),call(),   call([Ljava.lang.Object;),call(java.lang.Object),   call(java.lang.Object,java.lang.Object),findAll()消息:没有   签名方法:   AcmeGrailsPlugin $ _closure2_closure5_closure9.doCall()适用   对于参数类型:(grails.spring.BeanBuilder)值:   [grails.spring.BeanBuilder@7b067 fd7]可能的解决方案:   doCall(java.lang.Object,java.lang.Object),call(),   call([Ljava.lang.Object;),call(java.lang.Object),   call(java.lang.Object,java.lang.Object)

我对此感到困惑,我认为这是不可能的,而且我不确定如何动态地处理基于闭包的约定。

2 个答案:

答案 0 :(得分:2)

您的代码的一个问题可能是配置节点结构看起来完全正常,但事实上并非如此。即某些节点是Map个实例,而不是ConfigObject个实例。

在大多数情况下,这可能不重要,但在你的情况下,似乎第三方插件失败了一些丑陋且难以理解的异常。

我无法重新创建您的问题,因此我无法确定这是您遇到的真正问题,也不是建议的解决方案是否能解决您的问题。然而,我的第一次尝试是修复类型,以便配置树中的所有节点都是ConfigObject类型。像这样:

def poolProps = [timeout: 5000] as ConfigObject // convert type to ConfigObject
grails.acme.host = 'localhost'
grails.acme << [ poolSettings : poolProps ]

请注意,如果您创建的地图(在本例中为poolProps)包含嵌套的地图元素,您也必须转换它们。

答案 1 :(得分:1)

是的,有可能,实际上

grails {
   acme {
      host = 'localhost'
      poolSettings {
         timeout = 5000
      }
   }
}

与:

相同
grails.acme.host = 'localhost'
grails.acme.poolSettings.timeout = 5000

封闭只是语法糖。您甚至可以将两种类型组合在一起:

grails.acme {
   host = 'localhost'
   poolSettings.timeout = 5000
}