Search code examples
grails

How to replace Servlet Filters already defined (replacing legacy doWithWebDescriptor with doWithSpring)


I'm trying to upgrade a Grails plugin from version 2.3.4 to 4.0.11. It uses a syntax that is no longer supported to replace filters with names sitemesh and urlMapping with its own filters.

The code below uses a DSL for xml. It replaces xml nodes in the final generated web.xml.

def doWithWebDescriptor = { xml ->
    def pageFilter = xml.filter.find { it.'filter-name'.text() == 'sitemesh' }
    def urlMappingFilter = xml.filter.find { it.'filter-name'.text() == 'urlMapping' }

    def grailsVersion = GrailsUtil.grailsVersion

    // Grails 1.3.x & Grails 2.0.x
    def pageFilterClass = "org.zkoss.zk.grails.web.ZKGrailsPageFilter"
    def urlMappingFilterClass = "org.zkoss.zk.grails.web.ZULUrlMappingsFilter"

    if(grailsVersion.startsWith("2")) {
        pageFilter.'filter-class'.replaceNode {
            'filter-class'(pageFilterClass)
        }
        urlMappingFilter.'filter-class'.replaceNode {
            'filter-class'(urlMappingFilterClass)
        }

        //
        // Require a legacy config for servlet version
        //
        if(application.metadata.getServletVersion() >= '3.0') {
            pageFilter.'filter-class' + {
                'async-supported'('true')
            }
            urlMappingFilter.'filter-class' + {
                'async-supported'('true')
            }
        }
    } else {
        pageFilter.'filter-class'.replaceBody(pageFilterClass)
        urlMappingFilter.'filter-class'.replaceBody(urlMappingFilterClass)
    }
}

What I tried so far

The code below uses Grails plugin configuration to register filters with spring's FilterRegistrationBean. I'm following Grails official documentation.

Closure doWithSpring() { { ->
    boolean supportsAsync = this.grailsApplication.metadata.getServletVersion() >= "3.0"

    pageFilter(FilterRegistrationBean) {
        name = "sitemesh"
        filter = bean(org.zkoss.zk.grails.web.ZKGrailsPageFilter)
        urlPatterns = ["/*"]
        order = Ordered.HIGHEST_PRECEDENCE
        asyncSupported = supportsAsync
    }

    urlMappingFilter(FilterRegistrationBean) {
        name = "urlMapping"
        filter = bean(org.zkoss.zk.grails.web.ZULUrlMappingsFilter)
        urlPatterns = ["/*"]
        order = Ordered.HIGHEST_PRECEDENCE
        asyncSupported = supportsAsync
    }
}}

How can I replicate the legacy code with RegistrationBeans?

Also, I don't know if any of these filters got deprecated by Grails. I would like to know if there are any other replacements, if possible.

Here's the project in case anyone wants more context.


Solution

  • Debugging the older version of the plugin I came up with the following:

    pageFilter(FilterRegistrationBean) {
        name = "sitemesh"
        filter = bean(ZKGrailsPageFilter)
        urlPatterns = ["/*"]
        order = OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER + 50
        asyncSupported = supportsAsync
        dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR)
    }
    
    urlMappingFilter(FilterRegistrationBean) {
        name = "urlMapping"
        filter = bean(ZULUrlMappingsFilter)
        urlPatterns = ["/*"]
        order = OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER + 60
        asyncSupported = supportsAsync
        dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD)
    }
    

    Added the dispatcherTypes and changed the order assuming these would be the last filters where the 'pageFilter' should be placed before the 'urlMappingFilter' in the filter chain.