Showing posts with label grails-link-generator. Show all posts
Showing posts with label grails-link-generator. Show all posts

Monday, October 23, 2017

Grails Link Generator | Generate Links Outside Controllers or Tag Libraries | Using grailsLinkGenerator to generate link | Custom Link Generator

Grails Link Generator | Generate Links Outside Controllers or Tag Libraries | Using grailsLinkGenerator to generate link | Custom Link Generator

It's easy, just need to follow below steps:
First create a properties file named "application.properties" under web-app/WEB-INF as follows:


configs.serverURL=http://localhost:8033/custom-link-generator-bean


Now create a Groovy file named "ConfigurationProperties.groovy" with below contents:


package com.link

import grails.util.Environment

/**
 * Created by pritom on 23/10/2017.
 */
class ConfigurationProperties {
    public static final String DEV_DIR = "web-app/WEB-INF"
    private static Properties ppt

    static getProperty(String name, def defaultV = null) {
        if (ppt == null) {
            ppt = new Properties()
            loadProperties("application.properties")
        }

        def result = ppt.getProperty(name, defaultV?.toString())
        return result == "" ? defaultV : result
    }

    static loadProperties(String fileName) {
        URL url = ConfigurationProperties.class.getResource("ConfigurationProperties.class")
        String thisPath = url.getPath(), path
        if(Environment.current == Environment.DEVELOPMENT || Environment.current == Environment.TEST) {
            path = "file://" + thisPath.substring(0, thisPath.lastIndexOf("target")) + "${DEV_DIR}/${fileName}"
        }
        else {
            path = "file://" + thisPath.substring(0, thisPath.lastIndexOf("classes")) + fileName
        }

        new File(path.toURI()).getCanonicalFile().withInputStream { InputStream stream ->
            ppt.load(stream)
        }
    }
}


Now create a Groovy file named "MyLinkGenerator.groovy" with below contents:


package com.link

import org.codehaus.groovy.grails.web.mapping.DefaultLinkGenerator
import org.codehaus.groovy.grails.web.mapping.LinkGenerator
/**
 * Created by pritom on 23/10/2017.
 */
class MyLinkGenerator extends DefaultLinkGenerator implements LinkGenerator {
    MyLinkGenerator(String serverBaseURL, String contextPath) {
        super(serverBaseURL, contextPath)
    }

    MyLinkGenerator(String serverBaseURL) {
        super(serverBaseURL)
    }

    String makeServerURL() {
        return ConfigurationProperties.getProperty("configs.serverURL")
    }

    String link(Map attrs, String encoding = 'UTF-8') {
        String cp = super.getContextPath()
        String url = super.link(attrs, encoding)
        if (cp) {
            if (cp != null && url.startsWith(cp)) url = url.substring(cp.length())
            if (url.startsWith("/")) url = url.substring(1)
            return makeServerURL() + "/" + url
        }
        return url
    }
}


Now add below lines to BootStrap.groovy


import com.link.MyLinkGenerator
import grails.spring.BeanBuilder
import org.codehaus.groovy.grails.commons.GrailsApplication

import javax.servlet.ServletContext

class BootStrap {
    ServletContext servletContext
    GrailsApplication grailsApplication

    def init = { servletContext ->
        grailsApplication.mainContext.removeBeanDefinition("grailsLinkGenerator")
        BeanBuilder bb = new BeanBuilder()
        bb.beans {
            grailsLinkGenerator(MyLinkGenerator, null)
        }
        bb.registerBeans(grailsApplication.mainContext)
    }

    def destroy = {

    }
}


And create another Groovy file named "AsyncManager.groovy" with below contents to check it in thread:


package com.link

/**
 * Created by pritom on 23/10/2017.
 */
class AsyncManager {
    static void run(Closure closure) {
        TimerTask task = new TimerTask() {
            @Override
            void run() {
                try {
                    closure.call()
                }
                catch (Exception e) {
                    e.printStackTrace()
                }
            }
        }
        new Timer().schedule(task, 1000L)
    }
}


And finally add a controller with below contents:


package com.link

class CustomLinkController {
    def grailsLinkGenerator

    def index() {
        println "In-request"
        println "Generator=${grailsLinkGenerator.class}"
        println "Base-url=${grailsLinkGenerator.serverBaseURL}"
        println "Controller-url=${grailsLinkGenerator.link(controller: "customLink", action: "index", params: [id: 2, name: "Pritom Kumar"])}"

        AsyncManager.run {
            println ""
            println "In-non-request"
            println "Generator=${grailsLinkGenerator.class}"
            println "Base-url=${grailsLinkGenerator.serverBaseURL}"
            println "Controller-url=${grailsLinkGenerator.link(controller: "customLink", action: "index", params: [id: 2, name: "Pritom Kumar"])}"
        }
        render ""
    }
}


Output would be as follows:


--------------WITHOUT CUSTOM LINK GENERATOR-----------------------
In-request
Generator=class asset.pipeline.grails.CachingLinkGenerator
Base-url=http://localhost:8033/custom-link-generator-bean
Controller-url=/custom-link-generator-bean/customLink/index/2?name=Pritom+Kumar

In-non-request
Generator=class asset.pipeline.grails.CachingLinkGenerator
Base-url=http://localhost:8080/custom-link-generator-bean
Controller-url=/custom-link-generator-bean/customLink/index/2?name=Pritom+Kumar


--------------WITH CUSTOM LINK GENERATOR-----------------------
In-request
Generator=class com.link.MyLinkGenerator
Base-url=http://localhost:8033/custom-link-generator-bean
Controller-url=http://localhost:8033/custom-link-generator-bean/customLink/index/2?name=Pritom+Kumar

In-non-request
Generator=class com.link.MyLinkGenerator
Base-url=http://localhost:8033/custom-link-generator-bean
Controller-url=http://localhost:8033/custom-link-generator-bean/customLink/index/2?name=Pritom+Kumar