Grails : How do you make services available inside services? - grails

I am currently running into an issue where I am attempting to use a service within a service however the service is null
class ApplicationService{
def someService
def someMethod(){
someService.method()//null on someService
}
}
Is there additional wiring that I need to perform for this to work? Thanks in advance for your help.

I was able to do this by using the grailsApplication and loading the service.
if(!someService){
someService = grailsApplication.classLoader.loadClass("org.company.SomeService").newInstance()
}

The most possible explanation i here is, the class behind SomeService is not a Grails service artefact thus you cannot just inject it like that.
Double check on the source code whether that class is really a service or just a Groovy class in src/groovy. The framework will treat these two differently.
Also do not attempt to inject service with manually creating the instance like your answer, that is not the correct way to do dependency injection in Grails (or in Spring).

Related

Grails 3.X Inject service into Custom Listener

i wonder if someone knows hot to inject a service into a custom listener in Grails 3.X. I'm working with spring secuirty plugin in order to avoid brut force attacks. There is one answer but for Grails 2.0. Thanks in advance.
UPDATE !
Just for those who can use it . I tried Autowired and it works. Something like:
#Autowired
public LoginAttemptService loginAttemptService
The LoginAttemptService is already declared as a Bean
As shown here
Declare it like your injection:
MyService myService
Then when needed
def ctx = Holders.applicationContext
myService= ctx.myService
Alternatively
def myService = Holders.grailsApplication.mainContext.getBean('myService')
The alternate method is particulary useful for src/main/groovy calls if required to a service
Think their both the same thing in different ways

Grails access domain data during service initialization

I am trying to implement a search service where i want to do some initial data caching when the service is created. The service implements the spring framework InitializingBean interface, but when I try to use the afterPropertiesSet method to get data from my domains, I get an error stating that GORM is not ready for use. Is there any way to have domain objects available for use in the afterPropertiesSet method? Grails 2.5.0.
I'm not aware of an event or something similar to notify when domain classes have been initialized, but it does happen before BootStrap runs. For cases like this where afterPropertiesSet is too early to do something, you can dependency-inject the service in BootStrap and call your own init method, e.g.
class BootStrap {
def myService
def init = {
myService.init()
}
}

Symfony2 dependencies in class

I try to create a class to manage some part of my app
but I need to access the configuration in resources/config.yml
I tryed to extends my class with containerAware as a controler
But he container is not set...
I would like to be able to do something like that:
class MyClass extends ContainerAware
{
public function myFunciton()
{
$em = $this->get('Doctrine')->getEntityManager();
}
}
any suggestion is welcome
Extending ContainerAware does not automatically grant access to the service container - you would need to inject the container into your class. There are two ways to do that:
If your class is registered as a service, you can inject #service_container
If your class is not a service, but is being accessed from a class that does have access to the container (like a controller), you can explicitly call setContainer()
That being said, you should not inject the container into your classes. This makes it harder to test your classes. There are a few exceptions to this, but they don't come up often.
Instead, you should only inject services you need. In the case of the entity manager, you would inject #doctrine.orm.default_entity_manager.
In regards to accessing data from a config.yml, I would suggest including the file (which can be done when defining a service) and parsing the yml using either Symfony\Component\Yaml\Parser or Symfony\Component\Yaml\Yaml. The parsers converts a yml string to a PHP variable that you can then easily work with.

Using resources.groovy to define services

I'm using the resources.groovy to declare a service e.g.
aService(com.foo.OrganizationService)
so that I can tie aService to my controllers instead of using organizationService which could change in the future.
I've noticed that the OrganizationService doesn't get treated special like other services "not" declared in the resources.groovy. For example it doesn't get injected with grailsApplication, and likely a hibernateSession etc and other things I've not hit yet....
Now, I know I can manually wire in stuff to my service but I'd rather not have to maintain that...
Is there a special way to declare a service in the resources.groovy so that gets treated like another service that grails loads up?
TIA
The short answer to your question is "no".
Under the covers, Grails services are driven by some intelligent code that is referencing a specific location and expecting certain properties.
Viewing the source code (especially around the ServicesGrailsPlugin.groovy) is a good way to see the "magic" in how these are wired together.
Is there a reason you wouldn't want to use a bonafide Grails service to solve your problem? If you are expecting things like a grailsApplication, it seems like that use is pretty specific to Grails and would be a good candidate for porting over to a "true" Grails service.
Good luck!
So I've come full circle on this. This is a timing problem. Where services haven't been grails initialized yet.
Basically when you use the resources.groovy to do service wiring you run the risk of using a Service that might initialize itself e.g. afterPropertiesSet method or static initializers that use grails services (log, hibernate session, ..) that haven't been injected yet.
So... What I've turned to instead is to create my own BeanBuilder in a BootStrap.groovy file.
BeanBuilder builder = new BeanBuilder(grailsApplication.parentContext)
def bb = builder.beans {
LoginListener(com.foo.LoginListener) {
springSecurityService = ref("springSecurityService")
userService = ref("userService")
}
}
bb.registerBeans(grailsApplication.mainContext)

How to separate interface from implementation in Grails services?

I was wondering if it's possible to create a service interface on Grails and I can't find a proper way of doing it.
This explanation isn't satisfactory, since it seems to mix Java and Groovy:
http://www.grails.org/doc/latest/guide/8.%20The%20Service%20Layer.html
It seems to me like a bad design flaw of the framework, given that the interface mechanism is one of the best features of Java (and most OO languages).
Any idea to clarify this issue?
Thanks!
Mulone
You can have an interface, but actually you don't need one. If I understand you correctly you would like to have two implementations of a service and be able to choose which one to use.
Simply implement two services named for example MyService1 and MyService2, then in grails-app/conf/spring/resource.groovy you can specify:
beans = {
...
// syntax is beanId(implementingClassName) { properties }
myService(MyService1)
...
}
or even:
beans = {
...
if (someConfigurationOption) {
myService(MyService1)
} else {
myService(MyService2)
}
}
This is how you tell Spring which service to actually inject for myService. Now you will be able to use myService like:
public MyController {
def myService
...
}
and Spring will auto wire a proper implementation. This allows you to configure which service implementation to use based for example on some configuration.
Define the service interface in a class com.mycompany.mypackage.MyInterface.groovy stored under src/groovy
Define the service implementation stored under grails-app/services
class MyService implements MyInterface {
// service implementation goes here
}
Its not a design flaw. Groovy is different than java in that it is a dynamic language that uses 'duck-typing'. Whats interesting in groovy is that there are also interfaces. So if you follow #don's suggestion, you can make sure that your service conforms to the interface, but the way you do DI with grails is to just specify the service implementation. i.e. you do not get the compile time check where you use the service implementation, like you do in java.
Note that there is no tight coupling here. Coupling implies that something is bound to a type. But with groovy's loose typing system, types are essentially dynamic creatures. So in java, if you declare a type to be a specific implementation, the code might not compile if you change the type later. In groovy, the code will always compile if you use the 'def'...(I think this is correct)
The best solution I found for this is using Spring bean aliases. Basically you need to:
1) Create an interface in src/groovy ( MyService.groovy )
2) Inject your service wherever you need it:
class MyController {
MyService myService
}
3) Create your regular services implementing that interface ( ImplOneService.groovy, ImplTwoService.groovy )
4) Add an entry to resources.groovy where you define which implementation to use (eventually, testing for environment, or anything else you need):
beans = {
if (...development, useFTP, etc...) {
springConfig.addAlias 'myService', 'ImplOneService'
} else {
springConfig.addAlias 'myService', 'ImplTwoService'
}
}
Complete sources here
My comments: Using interfaces in groovy really seems like some kind of "I want to stick with some java stuff I'm more comfortable with". In this case, strong-typing. But it's exactly the nice part of groovy saying "No worries, you can keep the java way if you want".

Resources