Applying Groovy extensions in Grails creates a MissingMethodException for the string # toBoolean ()

Background

Groovy has the function of adding methods to existing classes , and I found some interesting ones .

Then I found that I needed to configure Grails loading to load, so I add:

def init = { servletContext -> addExtensionModules() } def addExtensionModules() { Map<CachedClass, List<MetaMethod>> map = [:] ClassLoader classLoader = Thread.currentThread().contextClassLoader try { Enumeration<URL> resources = classLoader.getResources(MetaClassRegistryImpl.MODULE_META_INF_FILE) for (URL url in resources) { if (url.path.contains('groovy-all')) { // already registered continue } Properties properties = new Properties() InputStream inStream try { inStream = url.openStream() properties.load(inStream) GroovySystem.metaClassRegistry.registerExtensionModuleFromProperties(properties, classLoader, map) } catch (IOException e) { throw new GroovyRuntimeException("Unable to load module META-INF descriptor", e) } finally { inStream?.close() } } } catch (IOException ignored) {} map.each { CachedClass cls, List<MetaMethod> methods -> cls.setNewMopMethods(methods) } } 

And I add to my BuildConfig.groovy

 compile ('ca.redtoad:groovy-crypto-extensions:0.2') { excludes 'groovy-all' } 

Question

The problem is that now I can not use the toBoolean() Groovy String method:

groovy.lang.MissingMethodException: No method signature: java.lang.String.toBoolean () is applicable for argument types :() values: [] Possible solutions: asBoolean (), asBoolean (), toFloat (), toDouble ()

Since Groovy is already registered, why is this method missing? I am using Grails 2.2.4.

EDIT

Tested in the Groovy 2.0.8 console, and the code works, maybe something related to Grails.

 @Grab('ca.redtoad:groovy-crypto-extensions:0.2') @GrabExclude('org.codehaus.groovy:groovy-all') addExtensionModules() //same method of BootStrap, ommited to make shorter. def key = "password".toKey() def ciphertext = "some plaintext".bytes.encrypt(key: key) def x = new String(ciphertext.decrypt(key: key)).toBoolean() println "S".toBoolean() 
+6
source share
1 answer

Replace

 map.each { CachedClass cls, List<MetaMethod> methods -> cls.setNewMopMethods(methods) } 

with

 map.each { CachedClass cls, List<MetaMethod> methods -> //Add new MOP methods instead of set them as new cls.addNewMopMethods(methods) } 

When the new meta method is set to CachedClass , existing extensions / meta methods are overridden only by the extension provided from the extension module. In this case, groovy-crypto-extension uses the following extension methods for the String class

 class java.lang.String= [public static javax.crypto.spec.SecretKeySpec ca.redtoad.groovy.extensions.crypto.CryptoExtensionMethods.toKey(java.lang.String), public static javax.crypto.spec.SecretKeySpec ca.redtoad.groovy.extensions.crypto.CryptoExtensionMethods.toKey(java.lang.String,java.util.Map) ] 

If these methods are set to CachedClass, existing methods are destroyed. Therefore, you need to replace it by adding them to the CachedClass. Therefore, creating toBoolean available for the String class.

The call is accepted and executed. You have to treat me. (Gift card is also acceptable) .;)

+6
source

Source: https://habr.com/ru/post/956636/


All Articles