web-dev-qa-db-fra.com

Injecter la configuration de l'application Grails dans le service

Je crée un service Grails qui interagira avec une tierce partie REST API via une bibliothèque Java. Le Java La bibliothèque requiert des informations d'identification pour l'API REST au moyen d'une URL, d'un nom d'utilisateur et d'un mot de passe.

Je souhaite stocker ces informations d'identification dans configuration/Config.groovy, Les mettre à la disposition d'un service et m'assurer que les informations d'identification sont disponibles pour le service avant qu'il ne les nécessite.

J'apprécie que grailsApplication.config Soit disponible pour les contrôleurs et que grâce à une méthode de service, les valeurs de configuration pertinentes puissent être fournies au service, comme ceci:

package example

class ExampleController {

    def exampleService

    def index = { }

    def process = {
        exampleService.setCredentials(grailsApplication.config.apiCredentials)
        exampleService.relevantMethod()
    }
}


package example

import com.example.ExampleApiClient;

class ExampleService {

    def credentials

    def setCredentials(credentials) {
        this.credentials = credentials
    }

    def relevantMethod() {

        def client = new ExampleApiClient(
            credentials.baseUrl,
            credentials.username,
            credentials.password
        )

        return client.action();
    }
}

Je pense que cette approche est légèrement défectueuse car elle dépend d'un contrôleur appelant setCredentials(). La mise à disposition automatique des informations d'identification au service serait plus robuste.

L'une ou l'autre de ces deux options est-elle viable (je ne connais pas assez bien les grails actuellement):

  1. Injecter grailsApplication.config.apiCredentials Dans le service dans le contrôleur lorsque le service est créé?

  2. Fournir une forme de constructeur sur le service qui permet de transmettre les informations d'identification au service au moment de l'instanciation?

Il est idéal d'avoir les informations d'identification injectées dans le service. Comment cela pourrait-il être fait?

38
Jon Cram

L'objet grailsApplication est disponible dans les services, ce qui permet:

package example

import com.example.ExampleApiClient;

class ExampleService {

    def grailsApplication

    def relevantMethod() {

        def client = new ExampleApiClient(
            grailsApplication.config.apiCredentials.baseUrl
            grailsApplication.config.apiCredentials.username,
            grailsApplication.config.apiCredentials.password
        )

        return client.action();
    }
}
79
Jon Cram

Même si grailsApplication peut être injecté dans les services, je pense que les services ne devraient pas avoir à gérer la configuration car il est plus difficile de tester et casse le principe de responsabilité unique . Le ressort, de l'autre côté, peut gérer la configuration et l'instanciation de manière plus robuste. Les Grails ont ne section dédiée dans ses documents.

Pour que votre exemple fonctionne avec Spring, vous devez enregistrer votre service en tant que bean dans resources.groovy

// Resources.groovy
import com.example.ExampleApiClient

beans {
    // Defines your bean, with constructor params
    exampleApiClient ExampleApiClient, 'baseUrl', 'username', 'password'
}

Vous pourrez ensuite injecter la dépendance dans votre service

class ExampleService {
    def exampleApiClient

    def relevantMethod(){
        exampleApiClient.action()
    }
}

De plus, dans votre Config.groovyfile, vous pouvez remplacer n'importe quelle propriété de bean en utilisant la convention Grails sur la syntaxe de configuration: beans.<beanName>.<property>:

// Config.groovy
...
beans.exampleApiClient.baseUrl = 'http://example.org'

Tous les deux Config.groovy et resources.groovy prend en charge différentes configurations d'environnement.

11
César

Pour les contextes où vous ne pouvez pas injecter le bean grailsApplication (le service n'est pas de ceux, comme décrit par Jon Cram), par exemple une classe d'assistance située dans src/groovy, vous pouvez y accéder en utilisant Holders = classe:

def MyController {
   def myAction() {
      render grailsApplication == grails.util.Holders.grailsApplication
   }
}
4
Deigote