Grails Dependency Injection Problem - grails

I am having problems when using dependency injection with Services in Grails.
class ExampleService{
def example2Service
def example3Service
def method1(){
def result = example2Service.method2()
}
}
class ExampleService{
def example3Service
def method2(){
def result = example3Service.method3()
return result
}
}
class Example3Service{
def method3(){
return true
}
}
Basically in Example2Service, I am getting a Null Pointer Exception when trying to call method3 in Example3Service.
I would appreciate any help than anybody can give me with this issue
thanks

Dependency Injection needs to be initialized. (The same applies to other kinds of runtime meta programming, like augmenting Domain classes with their save() and validate() methods.)
A Grails application will be initialized when
being run from the grails run-app command
being run after having been deployed to a web server
being run from the grails test-app command (integration tests, only; unit tests do not trigger initialization).
Involved classes are not initialized when
executing a single Groovy file (i.e., by using groovy, groovysh, or groovyConsole)
or when executing a unit test.
The following as an integration test should work:
class Test2ServiceTests extends GroovyTestCase {
def test2Service
void testMethod2() {
assert test2Service.method2() == true
}
}

Related

NullPointerException when calling service methode in a domain class methode

According to Grails it should be possible to use a service within a domain class. But when I run the following simple example, the grails run-app fails with a NullPointerException: "Cannot invoke method test() on null object"
To reproduce use the following code pieces:
Bootstrap.groovy:
class BootStrap {
def init = { servletContext ->
new Test().test()
}
def destroy = {
}
}
with the service:
#Transactional
class TestService {
def test() {
}
}
and the domain class:
class Test {
def testService
def test() {
testService.test()
}
}
This happens with Grails 3.2.9 and 3.3.0. Is this a Grails error or a GORM failure, not auto injecting the service into domain classes ?
SOLUTION:
For all wondering what the solution is (see answer from erichelgeson) using "static mapping = { autowire true }". But testing both solutions, I found that "static mapping ..." works in Grails 3.3.0 and in 3.2.9, hence setting it globally in application.yml did only work for Grails 3.2.9 but not in Grails 3.3.0 thou.
Recent versions of Grails (3.2.9+) have disabled autowire by default on domain classes for performance reasons. You can re-enable it:
per domain:
static mapping = {
autowire true
}
or globally in application.yml/groovy
grails.gorm.autowire = true
See more # http://gorm.grails.org/6.1.x/hibernate/manual/index.html
Section 1.2.9
You could reenable autowiring per the previous suggestion, but there are performance implications to your whole application for that. It may be worth it, if this is a common situation.
If this is a rare situation for you, you can also access a service as so, in a domain class:
Holders.applicationContext.serviceName.methodName()

Grails 2.4 Command objects nullable constraint and dependency injection

we are preparing for Grails 2.4 upgrade. One of the issues we face is that
most of the command object unit tests fails because of injected properties, like
services, are required to be not null during validation.
Is there any suggested way how to test this? Should we mock all properties although some are not needed for test? or is there a way to do this differently?
After my question is answered by Jeff, I share links with more information about new functionalities:
doWithSpring and doWithConfig are shortly described in What's new in 2.4: http://grails.org/doc/latest/guide/introduction.html#whatsNew24 in Unit Testing improvements section
There is also a JIRA issue with example: https://jira.grails.org/browse/GRAILS-11003
Most unit tests don't want or need the application context all spun up and populated. Unit tests can add whatever they want (or nothing) to the application context. In recent versions of Grails you can do something like this...
A controller and command object:
// grails-app/controllers/demo/DemoController.groovy
package demo
class DemoController {
def processName(SomeCommand co) {
render co.someValue
}
}
class SomeCommand {
String name
def helperService
def getSomeValue() {
helperService.processValue(name)
}
}
A service:
// grails-app/services/demo/HelperService
package demo
class HelperService {
def processValue(String originalValue) {
"__${originalValue}__"
}
}
A unit test:
// grails-app/test/unit/demo/DemoControllerSpec.groovy
package demo
import grails.test.mixin.TestFor
import spock.lang.Specification
#TestFor(DemoController)
class DemoControllerSpec extends Specification {
def doWithSpring = {
helperService HelperService
}
void 'process name'() {
when:
params.name = 'Jeff'
controller.processName()
then:
response.contentAsString == '__Jeff__'
}
}
That test will pass with Grails 2.4.2.
I hope that helps.

Exposing a configuration property via getter in a quartz job

Relating to Accessing grails application config from a quartz job:
Apparently, DI doesn't happen prior to the creation of a job. I'm guessing this is the same with other grails artefacts (couldn't spot relevant documentation).
In my particular case, I was aiming to load a property from config and expose that property from the job class. In general though, it seems a valid use-case to me, that artefacts will load configuration, and then return those properties via API.
I'm wondering then, how could this be achieved when a class cannot rely on access to grailsApplication.config at construction.
Thanks
Try with:
import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH
class MyJob {
def execute() {
def myConfigVar = CH.flatConfig.get('my.var.setup.in.config.groovy')
...
}
}
OR
import grails.util.Holders
class MyJob {
def execute() {
def myConfigVar = Holders.config.my.var.setup.in.config.groovy
...
}
}

Grails 2.3 IntegrationSpec cannot be transactional false

I upgrade to Grails 2.3 recently and try to migrate all old tests to spock integration test. But it fails at cleanup because my test is non-transactional. The Grails doc says test can be non-transactional, but we need to handle it manually, but it seems not quite right here. as I am getting this error in every integration test extending IntegrationSpec
java.lang.IllegalStateException: Cannot deactivate transaction synchronization - not active
at grails.test.spock.IntegrationSpec.cleanup(IntegrationSpec.groovy:72)
A simple test like this would throw that error:
import grails.test.spock.IntegrationSpec
public class DummySpec extends IntegrationSpec {
static transactional = false
def setup() {
}
def cleanup() {
}
def testDummy() {
expect:
1 == 1
}
}
I ran into this too! Pretty sure its a grails bug... I submitted a jira and a patch.
The error is thrown because the code in grails.test.spock.IntegrationSpec does not check for interceptor.isTransactional() before calling interceptor.destroy()
def cleanup() {
perMethodRequestEnvironmentInterceptor?.destroy()
perMethodTransactionInterceptor?.destroy() //breaks :(
}
...
private GrailsTestTransactionInterceptor initTransaction() {
def interceptor = new GrailsTestTransactionInterceptor(applicationContext)
if (interceptor.isTransactional(this)) interceptor.init() //also need for destroy()
interceptor
}
My fix was to add this code:
def cleanup() {
perMethodRequestEnvironmentInterceptor?.destroy()
destroyTransaction(perMethodTransactionInterceptor)
}
...
private void destroyTransaction(GrailsTestTransactionInterceptor interceptor){
if (interceptor?.isTransactional(this)) interceptor.destroy()
}
To work around for now, you can just create your own com.myname.IntegrationSpec with the patched code and extend that instead of grails.test.spock.IntegrationSpec. Not ideal... but it works :)
Grails 2.3 ships by default with Spock. Just remove your own defined spock dependency make sure to import grails.test.spock.IntegrationSpec and it should work.

NullPointerException for Service-in-Service Injection during test-app

Recently came across with a weird scenario, that dependency injection for a service within a service, threw NPE while running test-app
Reason for service-in-service injection is to make the GORM/criteriaBuilder as DRY as possible. So following are my two services.
Following class SearchService1.groovy is implemented to provide search capability.
class SearchService1{
def search = { ...//Calls to local closures to build a dynamic criteria }
...
}
Class SearchService2.groovy uses the search closure of SearchService1 class
class SearchService2{
def searchService1
...
def searchEntity(){
searchService1.search()
}
}
Now, the above stated code works pretty well in run-app mode.
But for Integration test written for SearchService2 throws NPE as follows :
Cannot invoke method searchEntity() on null object
java.lang.NullPointerException: Cannot invoke method search() on null object
at com.myapp.service.SearchService2.searchEntity(SearchService2.groovy:326)
at com.myapp.service.SearchService2$searchEntity$0.callCurrent(Unknown Source)
at com.myapp.service.SearchService2.searchEntity(SearchService2.groovy:295)
at com.myapp.service.SearchService2$searchEntity.call(Unknown Source)
at com.myapp.integration.SearchService2Tests.testWhenSearch(SearchService2Tests.groovy:125)
Am I missing something very basic here ? Any thoughts are greatly appreciated. Many Thnx :)
Snippet from TestClass :
class SearchService2Tests extends GroovyTestCase{
...
def searchService2
...
void testWhenSearch(){
def resultSet = searchService2.searchEntity() //This is the line throwing NPE
...
}
}
Woah ! Got rid of this stupid error by this workaround.
To TestClass, inject the searchService1 to searchService2 object like this :
def searchService2
def searchService2.searchService1 = new SearchService1()
But come on ! Is this the right way to do it ? Can anyone explain the above error by the way, that why a Service-in-Service is not instantiated while running test-app.
try this:
class SearchService2Tests extends GroovyTestCase {
...
def searchService1
def searchService2
...
void testWhenSearch(){
def resultSet = searchService2.searchEntity()
...
}
}
but use standard Grails service naming convention and placement

Resources