Grails 2.4.2 - Local class in controller's action - grails

Just out of curiosity I tried to place a local class within one of my controller's actions, e.g.:
def index() {
class TestClass {
TestClass() {
// do something
}
doSomething() { ... }
}
TestClass test = new TestClass()
test.doSomething()
respond anything
}
However, compilation always fails giving me an error like this:
Error Compilation error: startup failed: class TestClass ...
^
Have you got any ideas?

You can't define classes inside methods
Move it outside the method

Related

Is it possible to have a private constructor in dart?

I'm able to do something like the following in TypeScript
class Foo {
private constructor () {}
}
so this constructor is accessible only from inside the class itself.
How to achieve the same functionality in Dart?
Just create a named constructor that starts with _
class Foo {
Foo._() {}
}
then the constructor Foo._() will be accessible only from its class (and library).
A method without any code must be something like this
class Foo {
Foo._();
}
Yes, It is possible, wanna add more information around it.
A constructor can be made private by using (_) underscore operator which means private in dart.
So a class can be declared as
class Foo {
Foo._() {}
}
so now, The class Foo doesn't have a default constructor
Foo foo = Foo(); // It will give compile time error
The same theory applied while extending class also, It's also impossible to call the private constructor if it declares in a separate file.
class FooBar extends Foo {
FooBar() : super._(); // This will give compile time error.
}
But both above functionality works if we use them in the same class or file respectively.
Foo foo = Foo._(); // It will work as calling from the same class
and
class FooBar extends Foo {
FooBar() : super._(); // This will work as both Foo and FooBar are declared in same file.
}
you can create following class in order to get a singleton instance
class Sample{
factory Sample() => _this ??= Sample._();
Sample._(); // you can add your custom code here
static Sample _this;
}
Now in the main function you can call the sample constructor
void main(){
/// this will return the _this instace from sample class
Sample sample = Sample();
}
just use abstract class.
Because you can't instantiate abstract class

How to test whether an instance method is called from within another instance method in Grails 3 using Spock

Using Grails 3.2.8 and the Spock framework for testing, given the following controller class:
class SomeController {
def doSomething() {
// do a few things, then:
someOtherMethod()
}
protected void someOtherMethod() {
// do something here, but I don't care
}
}
How can I test the doSomething() method to make sure someOtherMethod() is called exactly once?
This is my attempt that failed:
#TestFor(SomeController)
class SomeControllerSpec extends Specification {
void "Test that someOtherMethod() is called once inside doSomething()"() {
when:
controller.doSomething()
then:
1 * controller.someOtherMethod(_)
}
}
Error message:
Too few invocations for:
1 * controller.someOtherMethod(_) (0 invocations)
Note: Imports have been omitted to focus on the problem at hand
You can't do that as controller is not a mocked object. Instead, you need to use metaclass like this:
#TestFor(SomeController)
class SomeControllerSpec extends Specification {
void "Test that someOtherMethod() is called once inside doSomething()"() {
given:
Integer callsToSomeOtherMethod = 0
controller.metaClass.someOtherMethod = {
callsToSomeOtherMethod++
}
when:
controller.doSomething()
then:
callsToSomeOtherMethod == 1
}
}

Groovy metaclass, mocking a service method that has throws clause

I have an abstract service:
abstract class ParentService {
abstract Map someMethod() throws NumberFormatException
}
And another service that extends above class:
class ChildService extends ParentService {
#Override
Map someMethod() throws NumberFormatException {
//Business Logic
}
}
I want to mock someMethod() using groovy metaClass. I need to mock this method for writing test cases for ChildService. This is what I have done for mocking:
ChildService.metaClass.someMethod = { -> "Mocked method" }
But this is not working and the call always executes actual method from the service. What needs to be done here? Am I missing something?
Please Note that I have to mock just one method not the entire service.
Maybe you could just mock method on instance?
def child = new ChildService()
child.metaClass.someMethod = { -> "Mocked method" }

Grails 3 - assign controller's variable in interceptor

I'm upgrading by Grails 2.5.1 web-app to grails 3, but I'm stuck with this problem: in my controllers I was using beforeInterceptors to pre-calculate a set of variables to be used in their action methods.
class MyController {
def myVar
def beforeInterceptor = {
myVar = calculateMyVarFromParams(params)
}
def index() {
/* myVar is already initialized */
}
}
Now that with Grails 3 interceptors are more powerful and on separate files, how can I achieve the same result? To avoid using request-scope variables, I tried with the following code
class MyInterceptor {
boolean before() {
MyController.myVar = calculateMyVarFromParams(params)
MyController.myVar != null // also block execution if myVar is still null
}
boolean after() { true }
void afterView() { /* nothing */ }
}
class MyController {
def myVar
def index() {
println('myVar: '+myVar)
}
}
but I get
ERROR org.grails.web.errors.GrailsExceptionResolver - MissingPropertyException occurred when processing request: [GET] /my/index
No such property: myVar for class: com.usablenet.utest.MyController
Possible solutions: myVar. Stacktrace follows:
groovy.lang.MissingPropertyException: No such property: myVar for class: com.usablenet.utest.MyController
Possible solutions: myVar
at com.usablenet.utest.MyInterceptor.before(MyInterceptor.groovy:15) ~[main/:na]
I assumed (wrongly, apparently) that this would be feasible. Is there a solution? Thanks in advance!
Note: in my case MyController is an abstract class extended by all other controllers
What I was missing is to declare myVar as static, as simple as that!
Update
If for any reason you cannot define the variable as static, you can set it as attribute on request object in the interceptor, and read it from there in the controller
// Interceptor
request.setAttribute('myVar', calculateMyVarFromParams(params))
// Controller
request.getAttribute('myVar')

Why does using an action name that is the same as a configured SpringBean name result in a ClassCastException?

To reproduce this problem use the following steps.
Create a new Grails application.
Create a new controller called FooController
Add an action "bar" to FooController
In src/groovy, create a new class called Bar
In resources.groovy configure a SpringBean called bar
bar(Bar) {bean ->
bean.autowire = 'byName'
}
Start the application and navigate to http:localhost:8080/[appContext]/foo/bar
You should get a stacktrace similar to this:
java.lang.ClassCastException: Bar cannot be cast to groovy.lang.Closure
at org.grails.plugin.resource.DevModeSanityFilter.doFilter(DevModeSanityFilter.groovy:44)
at java.lang.Thread.run(Thread.java:680)'
Why is this occuring? Is it a bug in Grails or expected behaviour?
I would expect that there should not be name clashes between configured SpringBeans and action names.
The problem is that Groovy syntax like
class FooController {
def bar = {
// do something
}
}
gives the FooController class two public methods
public Object getBar() {
return bar;
}
public void setBar(Object newBar) {
bar = newBar;
}
The existence of the setBar method makes Spring consider it as a property to be autowired, and it replaces the closure value with your bean. Grails itself only requires the getter method, so if instead you say
class FooController {
final bar = {
// do something
}
}
(i.e. declare bar to be final) then Groovy will synthesize only the getter and not the setter, and Spring will not see bar as a property it can autowire.
The action in the controller is a closure, which is transformed into a inner class. Your bean has the same name, so I believe you come to name collision through this. Did you try to rename the bean or the action?

Resources