gradle war vs gradle assemble (Grails 3.2.6 and Se

2020-04-28 06:48发布

问题:

I am having really hard time figuring this one out. I have an app which works fine in intellij and as a standalone war (created with gradlew assemble). But when I am trying to deploy this war (created with gradlew assemble but with tomcat starter set as provided in build.gradle file) in the tomcat 8.5, I am getting this exception. But if I generate a war using gradlew war then I do not see this exception and tomcat is deployed alright. But in that case my app is giving all kind of crap errors on the front end related to gsps and g: namespace.

Caused by: java.lang.NullPointerException
    at grails.plugin.springsecurity.web.access.intercept.AnnotationFilterInvocationDefinition.findActionRoles(AnnotationFilterInvocationDefinition.groovy:458)
    at grails.plugin.springsecurity.web.access.intercept.AnnotationFilterInvocationDefinition.findAnnotations(AnnotationFilterInvocationDefinition.groovy:425)
    at grails.plugin.springsecurity.web.access.intercept.AnnotationFilterInvocationDefinition.findAnnotations(AnnotationFilterInvocationDefinition.groovy)
    at grails.plugin.springsecurity.web.access.intercept.AnnotationFilterInvocationDefinition.findControllerAnnotations(AnnotationFilterInvocationDefinition.groovy:382)
    at grails.plugin.springsecurity.web.access.intercept.AnnotationFilterInvocationDefinition.initialize(AnnotationFilterInvocationDefinition.groovy:223)
    at grails.plugin.springsecurity.web.access.intercept.AnnotationFilterInvocationDefinition$initialize.call(Unknown Source)
    at grails.plugin.springsecurity.SpringSecurityCoreGrailsPlugin.initializeFromAnnotations(SpringSecurityCoreGrailsPlugin.groovy:770)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:210)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:59)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:166)
    at grails.plugin.springsecurity.SpringSecurityCoreGrailsPlugin.doWithApplicationContext(SpringSecurityCoreGrailsPlugin.groovy:651)
    at org.grails.plugins.DefaultGrailsPlugin.doWithApplicationContext(DefaultGrailsPlugin.java:523)
    at org.grails.plugins.AbstractGrailsPluginManager.doPostProcessing(AbstractGrailsPluginManager.java:224)
    at grails.boot.config.GrailsApplicationPostProcessor.onApplicationEvent(GrailsApplicationPostProcessor.groovy:246)
    at grails.boot.config.GrailsApplicationPostProcessor.onApplicationEvent(GrailsApplicationPostProcessor.groovy)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:167)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:383)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:389)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:337)
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:882)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:144)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:545)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:762)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:372)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
    at grails.boot.GrailsApp.run(GrailsApp.groovy:83)
    at org.springframework.boot.web.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:151)
    at org.grails.boot.context.web.GrailsAppServletInitializer.createRootApplicationContext(GrailsAppServletInitializer.groovy:57)
    at org.springframework.boot.web.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:86)
    at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:169)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5205)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

I am really unable to why this is happening ? This is my application.groovy file (security related configuration)

grails.plugin.springsecurity.userLookup.userDomainClassName = 'my.domain.Person'
grails.plugin.springsecurity.authority.className = 'my.domain.Role'
grails.plugin.springsecurity.securityConfigType = 'Annotation' //"InterceptUrlMap"
grails.plugin.springsecurity.password.algorithm = 'MD5'
grails.plugin.springsecurity.useSecurityEventListener = true
grails.plugin.springsecurity.useSessionFixationPrevention = true
grails.plugin.springsecurity.rejectIfNoRule = true
grails.plugin.springsecurity.fii.rejectPublicInvocations = false // make this true only in dev mode. XXX
/**
 * Salting a password is a good strategy from security point of view.
 * @see  https://grails-plugins.github.io/grails-spring-security-core/v3/#salt
 */
grails.plugin.springsecurity.dao.reflectionSaltSourceProperty = 'username'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
        [pattern: '/', access: ['permitAll']],
        [pattern: '/error/**', access: ['permitAll']],
        [pattern: '/index', access: ['permitAll']],
        [pattern: '/index.gsp', access: ['permitAll']],
        [pattern: '/shutdown', access: ['permitAll']],
        [pattern: '/assets/**', access: ['permitAll']],
        [pattern: '/**/js/**', access: ['permitAll']],
        [pattern: '/**/css/**', access: ['permitAll']],
        [pattern: '/**/images/**', access: ['permitAll']],
        [pattern: '/**/favicon.ico', access: ['permitAll']],
        [pattern: '/installrep/**', access: ['permitAll']],
        [pattern: '/status/**', access: ['permitAll']],
        [pattern: '/upgradeRepository/**', access: ['permitAll']],
        [pattern: '/patchUpgradeRepository/**', access: ['permitAll']],
        [pattern: '/log/**', access: ['permitAll']],
        [pattern: '/help/**', access: ['permitAll']],
        [pattern: '/login/**', access: ['permitAll']],
        [pattern: '/logout/**', access: ['permitAll']]
]

grails.plugin.springsecurity.filterChain.chainMap = [
        [pattern: '/assets*', filters: 'none'],
        [pattern: 'js*', filters: 'none'],
        [pattern: 'css*', filters: 'none'],
        [pattern: 'images*', filters: 'none'],
        [pattern: 'favicon.ico', filters: 'none'],
        [pattern: '/endpoints*', filters: 'JOINED_FILTERS,-filterInvocationInterceptor'],
        [pattern: '/services*', filters: 'JOINED_FILTERS,-filterInvocationInterceptor'],
        [pattern: '/**', filters: 'JOINED_FILTERS']
]

Can somebody please help me understand what is going on ?

回答1:

Finally, I tracked down the code. First of all, the difference between grails run-app vs running a war owes it to two implementations of AbstractGrailsApplication class in grails-core. For war, DefaultGrailsApplication is used and for intellij and others, it uses StandaloneGrailsApplication.

And the problem in this case arises out of this function in DefaultGrailsApplication calls.

public GrailsClass getArtefact(String artefactType, String name) {
    ArtefactInfo info = getArtefactInfo(artefactType);
    return info == null ? null : info.getGrailsClass(name);
}

Apparently the artifact is being looked into cache. In case of tomcat, I had been seeing the warnings as mentioned in this post here. And taking hints from that post, I used this answer and that does solve this issue here for me. I did not try by disabling the cache in tomcat. That probably might help as well. Let me know if you try that option out.

Hope this helps someone. I had been after this for more then a week now.

Update and solution

Move the cfx dependency in gradle file above spring security plugin and then you should see spring security being configured once only. See this question.