Search code examples
grailsintegration-testinggrails3grails3.2.0

Grails 3 : overriding service in doWithSpring


In grails 2, overriding a bean in a XPlugin.groovy just required to redefine the service in the doWithSpring() method:

def doWithSpring = {
    tokenStorageService(TokenStorageProxyService) { it.autowire = 'byName' }
}

I started programming in Grails 3, already having an experience with Grails 2 and tried the same kind of overriding in a new plugin, as I'm creating a Grails 3 version of some of my existing Grails 2 plugins:

Closure doWithSpring() { {->
    tokenStorageService(TokenStorageProxyService) {
        it.autowire = 'byName'
    }
} }

I made some integration tests:

@Integration
class SecurityServiceIntegrationSpec extends Specification {

    SecurityService securityService
    TokenStorageProxyService tokenStorageService
...
}

When running the tests, I get the error:

org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'grails.plugin.springsecurity.rest.token.storage.jwt.JwtTokenStorageService' to required type 'com.b2boost.grails3.auth.client.TokenStorageProxyService' for property 'tokenStorageService'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'grails.plugin.springsecurity.rest.token.storage.jwt.JwtTokenStorageService' to required type 'com.b2boost.grails3.auth.client.TokenStorageProxyService' for property 'tokenStorageService': no matching editors or conversion strategy found
at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:605)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1620)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:400)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:119)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
...
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: Cannot convert value of type 'grails.plugin.springsecurity.rest.token.storage.jwt.JwtTokenStorageService' to required type 'com.b2boost.grails3.auth.client.TokenStorageProxyService' for property 'tokenStorageService': no matching editors or conversion strategy found 
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:306)
at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:590)
... 37 more

It seems that the default JwtTokenStorageService has not been overrided by my TokenStorageProxyService, resulting in a ConversionNotSupportedException when the service is wired into the integration test. How can I override the service in my plugin?


Solution

  • After some investigation, it seems that my custom module was loaded after Spring security rest. The tokenStorageService from SSR thus overrided my service while the converse should have happened:

    Configuring MyModule...

    ... finished configuring MyModule

    Configuring Spring Security Core ...

    ... finished configuring Spring Security Core

    Configuring Spring Security REST 2.0.0.M2...

    ... finished configuring Spring Security REST

    Adding the following line in the MyModuleGrailsPlugin.groovy ensured the modules loaded in the right order:

    def loadAfter = [
        'springSecurityRest'
    ]