respond - Inyectar la configuración de la aplicación de grails en servicio
grails respond (3)
Aunque grailsApplication
se puede inyectar en los servicios, creo que los servicios no deberían tener que lidiar con la configuración porque es más difícil probar y rompe el principio de responsabilidad única . Spring, en el otro lado, puede manejar la configuración e instanciación de una manera más robusta. Grails tiene una sección dedicada en sus documentos.
Para que su ejemplo funcione con Spring, debe registrar su servicio como un bean en resources.groovy
// Resources.groovy
import com.example.ExampleApiClient
beans {
// Defines your bean, with constructor params
exampleApiClient ExampleApiClient, ''baseUrl'', ''username'', ''password''
}
Entonces podrá inyectar la dependencia en su servicio
class ExampleService {
def exampleApiClient
def relevantMethod(){
exampleApiClient.action()
}
}
Además, en su archivo Config.groovy
, puede anular cualquier propiedad de bean usando la convención de Grails sobre la sintaxis de configuración: beans.<beanName>.<property>
:
// Config.groovy
...
beans.exampleApiClient.baseUrl = ''http://example.org''
Tanto Config.groovy
como resources.groovy
admiten diferentes configuraciones de entorno.
Estoy creando un servicio de Grails que interactuará con una API REST de terceros a través de una biblioteca Java. La biblioteca Java requiere credenciales para la API REST por medio de una url, nombre de usuario y contraseña.
Me gustaría almacenar estas credenciales en la configuration/Config.groovy
, ponerlas a disposición de un servicio y garantizar que las credenciales estén disponibles para el servicio antes de que lo requiera.
Agradezco que grailsApplication.config
esté disponible para los controladores y que a través de un método de un servicio, los valores de configuración relevantes puedan ser proporcionados al servicio, como este:
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();
}
}
Siento que este enfoque es un poco defectuoso ya que depende de un controlador que llame a setCredentials()
. Tener las credenciales disponibles para el servicio automágicamente sería más sólido.
¿Es viable alguna de estas dos opciones (actualmente no estoy lo suficientemente familiarizado con Grails)?
¿Inyectar
grailsApplication.config.apiCredentials
en el servicio en el controlador cuando se crea el servicio?¿Proporciona algún tipo de contructor en el servicio que permita pasar las credenciales al servicio en el momento de creación de instancias?
Tener las credenciales inyectadas en el servicio es ideal. ¿Como se puede hacer esto?
El objeto grailsApplication
está disponible dentro de los servicios, lo que permite esto:
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();
}
}
Para contextos en los que no se puede inyectar el bean GrailsApplication (el servicio no es uno de ellos, como lo describe Jon Cram), por ejemplo, una clase auxiliar ubicada en src / groovy, puede acceder a ella utilizando la clase Holders :
def MyController {
def myAction() {
render grailsApplication == grails.util.Holders.grailsApplication
}
}