web-dev-qa-db-ja.com

Grailsアプリケーション構成をサービスに注入する

サードパーティとやり取りするGrailsサービスを作成していますREST API =Javaライブラリを介して。Javaライブラリには、URL、ユーザー名、パスワードを使用してREST APIの認証情報が必要です。

これらの資格情報を_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()を呼び出すことに依存しているため、少し欠点があるように感じます。資格情報をサービスで自動的に利用できるようにすると、より堅牢になります。

これらの2つのオプションのいずれかが実行可能ですか(私は現在、Grailsについて十分に詳しくありません)。

  1. サービスの作成時に_grailsApplication.config.apiCredentials_をコントローラーのサービスに挿入しますか?

  2. インスタンス化時に資格情報をサービスに渡すことができるように、サービスに何らかの形式のコンストラクタを提供しますか?

資格情報をサービスに挿入するのが理想的です。これはどのように行うことができますか?

38
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を使用してサンプルを機能させるには、サービスをBeanとして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の構成構文の規則を使用して、任意のBeanプロパティをオーバーライドできます:beans.<beanName>.<property>

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

Config.groovyresources.groovyは、どちらも異なる環境設定をサポートしています。

11
César

GrailsApplication Beanを注入できないコンテキスト(サービスはJon Cramの説明にあるものではありません)の場合、たとえばsrc/groovyにあるヘルパークラスには、Holdersを使用してアクセスできます。 =クラス:

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