29 votes

Injecter la configuration de l'application Grails dans le service

Je suis en train de créer un service grails qui va interagir avec une API REST tierce via une bibliothèque Java. La bibliothèque Java 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.

J'aimerais stocker ces informations d'identification dans le fichier configuration/Config.groovy Les informations d'identification peuvent être utilisées par un service et garantissent que les informations d'identification sont disponibles pour le service avant qu'il n'en ait besoin.

J'apprécie cela grailsApplication.config est disponible pour les contrôleurs et que, par l'intermédiaire d'une méthode d'un service, les valeurs de configuration pertinentes peuvent ê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 imparfaite car elle dépend d'un contrôleur appelant setCredentials() . La mise à disposition automatique des informations d'identification au service serait plus robuste.

Est-ce que l'une ou l'autre de ces deux options est viable (je ne suis pas assez familier avec grails) :

  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 permette de transmettre les informations d'identification au service au moment de l'instanciation ?

L'idéal est d'injecter les informations d'identification dans le service. Comment cela pourrait-il se faire ?

66voto

Jon Cram Points 5950

Les grailsApplication est disponible dans les services, ce qui permet de le faire :

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();
    }
}

7voto

César Points 541

Même si grailsApplication peut être injecté dans les services, je pense que les services ne devraient pas avoir à s'occuper de la configuration parce que c'est plus difficile à tester et que cela rompt l'intégrité du service. Principe de responsabilité unique . Spring, quant à lui, peut gérer la configuration et l'instanciation de manière plus robuste. Grails a une section dédiée dans sa documentation.

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

// Resources.groovy
import com.example.ExampleApiClient

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

Vous pourrez alors injecter la dépendance dans votre service

class ExampleService {
    def exampleApiClient

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

En outre, dans votre Config.groovy vous pouvez surcharger n'importe quelle propriété du bean en utilisant la convention Grails sur la syntaxe de configuration : beans.<beanName>.<property> :

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

Les deux Config.groovy y resources.groovy prend en charge différentes configurations d'environnement.

3voto

Deigote Points 152

Pour les contextes où vous ne pouvez pas injecter le bean grailsApplication (le service n'en fait pas partie, comme décrit par Jon Cram), par exemple une classe d'aide située dans src/groovy, vous pouvez y accéder en utilisant la méthode Supports classe :

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

0voto

Cléssio Mendes Points 79

Les meilleures options sont (à partir de docs grails ):

1 - Utilisation de Spring @Value annotation

import org.springframework.beans.factory.annotation.Value

class WidgetService {

    int area

    @Value('${widget.width}')
    int width

    def someServiceMethod() {
        // this method may use the width property...
    }
}

2 - Faire en sorte que votre classe mette en œuvre GrailsConfigurationAware

import grails.config.Config
import grails.core.support.GrailsConfigurationAware

class WidgetService implements GrailsConfigurationAware {

    int area

    def someServiceMethod() {
        // this method may use the area property...
    }

    @Override
    void setConfiguration(Config co) {
        int width = co.getProperty('widget.width', Integer, 10)
        int height = co.getProperty('widget.height', Integer, 10)
        area = width * height
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X