Grails - How to inject bean defined in resources.groovy in integration test - grails

I have 1 bean defined in resources.groovy
cachedbean(serviceImpl) {
}
In service I am using it this way
MyService{
static transactional = false
def cachedbean
myMeth(){
cachedbean.get("cacheKey")
}
}
This works fine but when I try to test it with integration test, I get nullpointer exception on 'get'
cachedbean.get("cacheKey").
How does it work?

Instead of "new"-ing up the service instance, if you let Grails auto wire the service bean into your integration test class it should be auto wired.
class MyServiceTests extends GroovyTestCase {
def myService
void testSomething () {
// myService should already be wired up
}
}

It's unclear if you did or not based on your sample code, but you need to fully-qualify out the package and class name for "serviceImpl" in your resources.groovy unless you explicitly import the package.
You may need to add inside the scope of your declaration in resources.groovy the line bean.autowire = "byName"

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()

Getting application config in doWithSpring closure with a Grails 3 application

Grails 3 allows authors to use startup hooks similar to the ones provided to Grails 2 plugins. I'm looking at defining beans in the doWithSpring closure, and I'd like to pass values into a new bean based on some configuration values. I can't figure out, however, how to get the grailsApplication instance or the application configuration. How do you do this with Grails 3?
Your plugin should extend grails.plugins.Plugin which defines the getConfig() method. See https://github.com/grails/grails-core/blob/9f78cdf17e140de37cfb5de6671131df3606f2fe/grails-core/src/main/groovy/grails/plugins/Plugin.groovy#L65.
You should be able to just refer to the config property.
Likewise you can refer to the inherited grailsApplication property which is defined at https://github.com/grails/grails-core/blob/9f78cdf17e140de37cfb5de6671131df3606f2fe/grails-core/src/main/groovy/grails/plugins/Plugin.groovy#L47.
I hope that helps.
Under Grails 3, I took Jeff Scott Brown's advice and used GrailsApplicationAware instead:
This is how you go about setting up a configuration bean:
So in your new plugin descriptor you need to change grails 2 style def doWithSpring to a ClosureDoWithSpring as below:
Notice in Grails 2 we injected grailsApplication, in grails 3 all we do is declare the bean:
/*
def doWithSpring = {
sshConfig(SshConfig) {
grailsApplication = ref('grailsApplication')
}
}
*/
Closure doWithSpring() { {->
sshConfig(SshConfig)
}
}
Now to get your plugin configuration:
src/main/groovy/grails/plugin/remotessh/SshConfigSshConfig.groovy
package grails.plugin.remotessh
import grails.core.GrailsApplication
import grails.core.support.GrailsApplicationAware
class SshConfig implements GrailsApplicationAware {
GrailsApplication grailsApplication
public ConfigObject getConfig() {
return grailsApplication.config.remotessh ?: ''
}
}
grails.plugin.remotessh.RemoteSsh.groovy:
String Result(SshConfig ac) throws InterruptedException {
Object sshuser = ac.config.USER ?: ''
Object sshpass = ac.config.PASS ?: ''
...
This is now your configuration object being passed into your src groovy classes. The end user application would pass in the sshConfig bean like this:
class TestController {
def sshConfig
def index() {
RemoteSSH rsh = new RemoteSSH()
....
def g = rsh.Result(sshConfig)
}
Edited to add, just found this :) which is relevant or duplicate question:
http://grails.1312388.n4.nabble.com/Getting-application-config-in-doWithSpring-closure-with-a-Grails-3-application-td4659165.html

Override Grails service bean definition with plugin

I want to override a service implementation by just installing a plugin - when the plugin is installed I want the plugin-version of the service to be used and when the plugin is uninstalled I want the default version of the service to be used.
To prevent wasting time, I'll explain my problem using code. I have a "common plugin" that is shared by my main application and my "custom plugin" with the following:
public interface SimpleService {
void doProcessing();
}
I then have a "main application" that contains the following
Default implementation of service interface:
public DefaultSimpleService implements SimpleService {
void doProcessing() {
// ...
}
resource.groovy:
simpleService(DefaultSimpleService) { bean ->
bean.autowire = 'byName'
}
Controller that uses the service:
class SimpleController {
def simpleService
def index() {
simpleService.doProcessing()
}
}
So far so good. What I now want to do is to replace the implementation of SimpleService interface with a new one by just installing a plugin. I do not want to change any configuration within my application.
I have a plugin with a new implementation of the service:
public CustomSimpleService implements SimpleService {
void doProcessing() {
// ...
}
}
My first attempt was to register the custom service bean in the plugins "doWithSpring" section, but it is always overridden by the main application. Fair enough since it seems like plugins are always loaded before main application beans is registered (?)
My second attempt was to register the custom bean in "doWithApplicationContext" inside my CustomServiceGrailsPlugin.groovy:
def doWithApplicationContext = { applicationContext ->
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory()
beanFactory.registerBeanDefinition("simpleService", BeanDefinitionBuilder.rootBeanDefinition(CustomSimpleService.class.getName()).getBeanDefinition())
}
This actually works partially - When the plugin is loaded the plugins implementation of SimpleService is used, and if the plugin is uninstalled the main applications implementation of SimpleService is used. But there was a side issue: autowiring of beans is not working inside the plugin implementation that was "manually" registered...
Then I started to look at BeanPostProcessors but from what I read it looked like it wouldn't solve my problem.
So how do I solve my problem?
Regards
Tobbe
I think that your best bet is to check if the plugin is installed and don't declare the service in the application if so.
You can check the plugins installed with: org.codehaus.groovy.grails.plugins.PluginManagerHolder.pluginManager.allPlugins
And you can use this in the resources.groovy
boolean containsPlugin(String pluginName) {
def names = org.codehaus.groovy.grails.plugins.PluginManagerHolder.pluginManager.allPlugins.collect { it -> return it.name }
return(pluginName in names)
}
beans = {
if(!containsPlugin("thePlugin")) {
println "Installation not contains plugin, defining bean!"
myService(...)
}
}

How can I automatically inject Grails components declared in resources.groovy into my IntegrationSpecs?

Using the Spock (0.7) Grails (2.1.2) plugin you can write integration specifications that automatically inject Grails archetypes (like services). However, I would like to do the same thing for Spring beans declared only in my resources.groovy. For example:
beans = {
simpleBean(SimpleBean) {
// load some dependencies
}
}
Where SimpleBean is declared in the src/groovy folder. If this were a Grails service, I could write something like the following in my test/integration folder::
import grails.plugin.spock.IntegrationSpec
class SimpleBeanSpec extends IntegrationSpec {
def simpleBean
def "should"() {
when:
data = simpleBean.load()
then:
assert simpleBean
}
}
But the above throws a NullPointerException on the call to simpleBean.load(). Is there some way to get Spock/Grails to create the the simpleBean dependency so that it has all the configured depdencies from resources.groovy as you would a Grails service?
Grails automatically injects all beans into integration tests, including Spock tests. Beans declared in resources.conf should work the same as artefacts. Are your IntegrationSpecs located under test/integration?

Can't initialize Service in Grails Integration Test because of JNDI lookup

I have a service that implements InitializingBean and DisposableBean
class MyService implements InitializingBean, DisposableBean {
static transactional = false
def grailsApplication
#Override
void afterPropertiesSet() {
System.setProperty("JMS_TIMEOUT", grailsApplication.config.JMS_TIMEOUT);
// code performing a JDNI lookup
}
}
enter code here
The system properties are used to initialize some other components in the service. I have added the configs in Config.groovy.
grails.config.locations = [ "file:${basedir}/grails-app/conf/myconfig.properties" ]
This works fine when running the application. However I'm writing an integration test in test/integration that injects the service.
class MyServiceIntegrationTests extends GrailsUnitTestCase {
def myService
void testMyService() {
}
}
When running the test I get a StackTrace with the folllowing root cause:
Caused by: javax.naming.NameNotFoundException: Name [ConnectionFactory] not bound; 0 bindings: []
at javax.naming.InitialContext.lookup(InitialContext.java:354)
at com.ubs.ecredit.common.jmsclient.DefaultConnector.<init>(DefaultConnector.java:36)
Seems that the Config could not be loaded or are different in the Integration Tests. Any idea how I can change the config or code, so that these properties are also set for my integration test, before the service is instantiated?
UPDATE:
It turned out the cause was not the configurations but a JDNI lookup and a bug in Grails.
See: http://jira.grails.org/browse/GRAILS-5726
${basedir} gets different paths in different environments. As an alternative, you can use PropertiesLoaderUtils.loadProperties to load your customized configurations:
import org.springframework.core.io.support.PropertiesLoaderUtils
import org.springframework.core.io.ClassPathResource
....
void afterPropertiesSet() {
def configProperties = PropertiesLoaderUtils.loadProperties(
new ClassPathResource("myconfig.properties"))
System.setProperty("JMS_TIMEOUT", configProperties.getProperty("JMS_TIMEOUT"))
....
}
It turned out the cause was a JNDI lookup used by a library method, I have not shown in afterPropertiesSet() in my Service, which can be seen in the StackTrace.
After doing some research I found that this was a bug in Grails: http://jira.grails.org/browse/GRAILS-5726
Adding the mentioned workaround, resolved the issue for now.

Resources