it-swarm-ru.tech

Внедрить конфигурацию приложения Grails в сервис

Я создаю службу grails, которая будет взаимодействовать с сторонним API REST через библиотеку Java. Для библиотеки Java требуются учетные данные для API REST с помощью URL-адреса, имени пользователя и пароля.

Я хотел бы сохранить эти учетные данные в configuration/Config.groovy, сделать их доступными для службы и убедиться, что учетные данные доступны службе, прежде чем они потребуются.

Я ценю, что grailsApplication.config доступен для контроллеров и что с помощью метода службы соответствующие значения конфигурации могут быть предоставлены службе, такой как эта:

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

Я чувствую, что этот подход немного ошибочен, так как зависит от контроллера, вызывающего setCredentials(). Наличие учетных данных, автоматически предоставляемых службе, было бы более надежным.

Является ли любой из этих двух вариантов жизнеспособным (я в настоящее время недостаточно знаком с Grails):

  1. Внедрить grailsApplication.config.apiCredentials в службу в контроллере при создании службы?

  2. Предоставить некоторую форму конструктора в службе, которая позволяет передавать учетные данные в службу во время создания экземпляра?

Внедрение учетных данных в сервис идеально. Как это можно сделать?

37
Jon Cram

В сервисах доступен объект grailsApplication, что позволяет:

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

Несмотря на то, что grailsApplication может быть введено в сервисы, я думаю, сервисам не нужно иметь дело с конфигурацией, потому что это сложнее в тестировании и нарушает принцип единой ответственности . Spring, с другой стороны, может обрабатывать конфигурацию и реализацию более надежным способом. Grails имеет специальный раздел в своих документах.

Чтобы ваш пример работал с использованием Spring, вы должны зарегистрировать свой сервис как бин в resources.groovy

// Resources.groovy
import com.example.ExampleApiClient

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

Тогда вы сможете внедрить зависимость в ваш сервис

class ExampleService {
    def exampleApiClient

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

Кроме того, в вашем файле Config.groovy вы можете переопределить любое свойство компонента, используя соглашение Grails по синтаксису конфигурации: beans.<beanName>.<property>:

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

И Config.groovy, и resources.groovy поддерживают разные конфигурации среды.

11
César

Для контекстов, где вы не можете внедрить bean-компонент grailsApplication (служба не относится к числу тех, которые описаны Jon Cram), например, вспомогательный класс, расположенный в src/groovy, вы можете получить к нему доступ с помощью Holders = класс:

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