Reputation: 29507
Grails 2.4.5 here. I did a grails create-service com.example.service.Simple
which created a SimpleService
for me, which I then modified to look like so:
class SimlpeService {
SimpleClient simpleClient
Buzz doSomething(String derp) {
// ...
Fizz fizz = simpleClient.doSomething(derp)
// ...
fizz.asBuzz()
}
}
I can now "inject" controllers with SimpleService
like so:
class MyController {
SimpleService simpleService
def index() {
// etc...
}
}
But how do I configure/wire SimpleService
with the correct SimpleClient
instance. Let's pretend SimpleClient
is typically built like so:
SimpleClient simpleClient = SimpleClientBuilder
.withURL('http://simpleclientdev.example.com/simple')
.withAuth('luggageCombo', '12345')
.isOptimized(true)
.build()
Depending on what environment I'm in, I may want my SimpleClient
instance to connect to simpleclientdev.example.com
, simpleclientqa.example.com
, or even simpleclient.example.com
. Also, I may use different auth credentials, and I might/might not want it to be "optimized", etc. The point is: How do I inject the SimpleService
with a SimpleClient
instance?
Upvotes: 1
Views: 66
Reputation: 25797
You can use the Java's PostConstruct annotation on one of your method in your service to do the stuff you want. From the docs:
The PostConstruct annotation is used on a method that needs to be executed after dependency injection is done to perform any initialization.
SimpleService.groovy
import javax.annotation.PostConstruct
class SimlpeService {
private SimpleClient simpleClient
def grailsApplication
@PostConstruct
void postConstruct() {
def config = grailsApplication.config.client.data
SimpleClient simpleClient = SimpleClientBuilder
.withURL(config.url)
.withAuth('luggageCombo', config.username)
.isOptimized(config.optimized)
.build()
}
Buzz doSomething(String derp) {
// ...
Fizz fizz = simpleClient.doSomething(derp)
// ...
fizz.asBuzz()
}
}
So, Grails or Spring will call this method postConstruct()
automatically when all the dependencies (in this case grailsApplication
) for this service are resolved and any of the service method is invoked.
This has been taken care that that method must invoke before you access any field member or method of the SimpleService
.
Now, everything is already configured like you mentioned that you may need to call different URL with different credential, just you have to define them in your Config.groovy
as:
environments {
development {
client {
data {
url = "simpleclientdev.example.com"
username = "test"
optimized = false
}
}
}
production {
client {
data {
url = "simpleclient.example.com"
username = "johndoe"
optimized = true
}
}
}
}
Now when you do run-app
with development mode and calling simpleService.doSomething()
in your example controller will automatically hit the simpleclientdev.example.com
URL with test credential and when you deploy it using production environment, the same simpleService.doSomething()
method will hit simpleclient.example.com
with optimized
set to true
.
Update
The key point here based on your question is that we will not be injecting different instances of SimpleService
since services are singleton by default. Instead we are changing the value's associated with the service based on the environment.
Upvotes: 1
Reputation: 602
Sounds like you need to understand a bit more about how to leverage Spring maybe? Grails Spring Docs
You can also do things like so in your Service class
@PostConstruct
void init() {
//configure variables, etc here ...
log.debug("Initialised some Service...")
}
Upvotes: 0