Post dependency injection in Grails Services

Problem Statement:

There are scenarios when we need to use default singleton feature of Grails services to hold some data by reading from configuration. 

For example: Needs to store some third party API credential from Config.groovy and store it as a global variable in the grails service.

Solution 1st:

A simplest approach for this is to call a service method from Bootstrap.groovy file which reads & stores the data in the service scope.

Example: Bootstrap.groovy

class Bootstrap {
    def myService

    def init = { servelContext ->
        service.initialize()
    }
}

MyService.groovy

class MyService {

    String FACEBOOK_KEY

    def grailsApplication

    void initialize() {
        // Some long key
        FACEBOOK_KEY= grailsApplication.config.thidparty.facebook.key
    }

    void authFb() {
        // Use this key
    }
}

This approach works fine on production server, but this is a very painful while development. As we change something in the service FACEBOOK_KEY will set to null & we again need to restart the app.

One can try calling the method in service constructor, but that will throw NPE since, grailsApplication will not be available while booting up server(creating new instance of service).

Solution 2nd:

You could write a simple grails plugin which will triggers common method of all services & register a watcher (only on development) to watch for changes in service.

Solution 3rd (Recommended & Simplest):

Best solution to this problem is to use Java’s PostConstruct annotation in Grails service. This method is automatically being called after all dependency gets successfully injected. Now the modified code will be something like this:

Bootstrap.groovy

class Bootstrap {

    def init = { servelContext ->
    }
}

MyService.groovy

class MyService {

    String FACEBOOK_KEY

    def grailsApplication

    @PostConstruct
    void initialize() {
        // Some long key
            FACEBOOK_KEY= grailsApplication.config.thidparty.facebook.key
    }

    void authFb() {
        // Use this key
    }
}

Make sure, return type of initialize() method is void. This annotation is a contract which ensures that this method will only be called once in whole app lifecycle until and unless that service is instantiated multiple times by the grails app.

About CauseCode: We are a technology company specializing in Healthtech related Web and Mobile application development. We collaborate with passionate companies looking to change health and wellness tech for good. If you are a startup, enterprise or generally interested in digital health, we would love to hear from you! Let's connect at bootstrap@causecode.com

Leave a Reply

Your email address will not be published. Required fields are marked *

STAY UPDATED!

Do you want to get articles like these in your inbox?

Email *

Interested groups *
Healthtech
Business
Technical articles

Archives