Grails run-command ask for application class argument - grails

I'm using grails 3.2.9 version. And trying to create custom command. I need a command because I need to have access to spring beans. So the code is simply like this:
class MyTestCommand implements GrailsApplicationCommand {
boolean handle() {
def bean = applicationContext.getBean('myBean')
bean.doSomething()
return true
}
When I run it as
grails run-command my-test
I'm getting an error: "Missing application class name and script name arguments"
I'am able to add application class as last param and everything seems works, but the question is, why I should add it? Does grails doesn't know about its Main Application class? I did some research about and there is no answers, in each examples i se only command name without Application class. But as I understand from this source we should pass main class always. Am I missed something?

Related

grails 2.5+ Duplicate class definition error when implementing serializable on a controller

Upgrading a legacy system of grails. One of the controllers implements Serializable. This is throwing the following error in newer versions of grails:
Invalid duplicate class definition of class com.regional.ScheduleController :
The source contains at least two definitions of the class.
One of the classes is an explicit generated class using the class statement,
the other is a class generated from the script body based on the file name.
Solutions are to change the file name or to change the class name.
The solution mentioned would break (previous) grails convention. Anyone know how to handle this in grails 2.5+?
EDIT
Serializable is not the issue. I tried removing it and got the same error.
I found this explanation from another question:
IN groovy.. class B{} is a class structure and defines a class B.
Scripts are classes too.
Now you may create a B.groovy, with the content "class B{}; def b = new B()".
There would be one class named B, and a script with the very same name.
This is a conflict.
However this does not explain why it runs fine below grails 2.5 and not above it. And I can't find a def conflict like the one mentioned above in that controller.
ANSWER:
One of the imports was what was actually failing- in a way that caused groovy to generate a class definition based on the current file name. When it hit the class definition, there was already an auto generated class name to collide with.

grailsApplication not available in Domain class when running all Integration tests

I'm running into a problem when running integration tests in Grails. One of the domain classes in the project has a method that accesses the grailsApplication.config property. We have an integration test for one of our services that call this method in the domain class. When the test is run on its own using the command
grails test-app integration: com.project.MyTestSpec
The test runs fine and the domain class can access grailsApplication. However when the whole test suite is run using:
grails test-app integration
then the test fails with the error
java.lang.NullPointerException: Cannot get property 'config' on null object
When trying to access grailsApplication.config. It seems that when the tests are all run together grailsApplication is not being injected into the domain class. Has anyone come across this issue before?
From what I have read it seems to be a test pollution issue but as there is no setup happening in each integration test the problem is hard to track down.
I came across this issue with grails 3. If you are testing a Domain, you have to setup (testing with spock) at the begining of the test:
def setup() {
Holders.grailsApplication = new DefaultGrailsApplication()
Holders.grailsApplication.config.property.code = '1234'
}
I'm not sure what the issue is, but this must be a test pollution issue where yours any one of the test case is doing something with grailsApplication using meta class. Because this seems to work fine for me.
As a workaround you can avoid using injected grailsApplication and use the Holders class instead like the following:
package com
import grails.util.Holders
class User {
// def grailsApplication
String email
String name
String getTitle() {
return Holders.getConfig()["app.title.prefix"] + name
// Or
//return Holders.grailsApplication.config["app.title.prefix"] + name
}
}
This way, you are not dependent upon the dependency injection.
I had the same issue and found that my integrationstest implemented ServiceUnitTest<> which caused the problem.

Get a service bean from Grails Holders class

I'm trying to update a plugin to Grails 2.4. Thus I have to replace the deprecated ApplicationContext class by the newer Holders class.
But I'm having some problems getting a service bean from the Holders class.
Running the code below:
import grails.util.Holders;
def myService = Holders.grailsApplication.mainContext.myService
println myService
println myService.getClass()
println myService.serviceMethod()
It prints something like:
grails.plugin.my.MyService#1e5cd54d
Exception thrown
java.lang.NullPointerException
at ConsoleScript2.run(ConsoleScript2:6)
at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1270)
It throws a NullPointerException when I call both: the "getClass" method and the "serviceMethod" method.
I tryed to see what's happening by debugging from eclipse too and I can observe "myService" variable being set to an object. When I click on it I can see it's String representation just like printed above. But I can't see anything inside the object. This service' class has member variables, but I can't see them on debug. It's like uf they were'nt there.
Can someone explain me what is going wrong?
Thanks
Don't use Holders, and avoid pulling in dependencies. Use dependency injection, it's a Good Thing.
Your src/groovy class is probably called from a controller, service, Quartz job, or some other Grails artifact that supports DI, right? If so, inject this service there, and when you call your src/groovy class, pass it as a method argument, or inject it once in a constructor or a setter.
Even if it's not called from a Grails artifact it's likely easy to get access to the service. E.g. a servlet can access the ServletContext and it's simple to access the ApplicationContext from there.

Add a method to an object in Grails and have it usable globally

I am attempting to add some string utility methods to the String class by utilizing Groovy's metaclass functionality. Right now I have something like this in my init closure in my BootStrap.groovy script:
String.metaClass.upper = {
delegate.toUpperCase()
}
The problem is that this upper method is only available within the scope of the BootStrap...trying to use it anywhere else in the Grails app does not work and I get method missing errors.
Is there any way to make those methods available everywhere?
Does this happen in both testing and running contexts? There is a bug where all metaClass changes get rolled back after each unit test: http://jira.grails.org/browse/GRAILS-8596

Load application class from plugin

In a Grails 1.1 plugin, I'm trying to load a class from the main application using the following code:
class MyClass {
static Map getCustomConfig(String configName){
return new ConfigSlurper().
parse(ApplicationHolder.application.classLoader.loadClass(configName))
}
}
Where configName is the name of the class in $MAIN_APP/grails-app/conf containing the configuration info. However, when the code above runs within a unit test applicationHolder.application returns null, causing the method above to throw a NullPointerException. A Grails JIRA issue was created for this problem, but it has been marked as fixed despite the fact that problem appears to still exist.
I know that within the plugin descriptor class I can access the main application (an instance of GrailsApplication) via the implicit application variable. But the code shown above is in not in the plugin descriptor.
Is there a way that I can load a class from the main application within a plugin (but outside the plugin descriptor)?
Thanks,
Don
It turns out there are 2 possible answers.
The Right Answer
GrailsApplication is not available in unit tests, so for the code above to work it should be an integration test
The Hack that Works
Change
parse(ApplicationHolder.application.classLoader.loadClass(configName))
to
parse(MyClass.classLoader.loadClass(configName))

Resources