Using AOP in Grails is not working for service - spring

I use Grails 2.2.3 and type following codes in grails-app/conf/spring/resources.groovy
beans = {
xmlns aop:"http://www.springframework.org/schema/aop"
loggerAspect(com.test.aop.aspect.LoggerAspect)
aop{
config("proxy-target-class": true) {
aspect(id: "beforeService", ref: "loggerAspect") {
before method: "beforeMethod",
pointcut: "execution(* com.test.DemoService.serviceMethod())"
}
aspect(id: "afterService", ref: "loggerAspect") {
after method: "afterMethod",
pointcut: "execution(* com.test.DemoService.serviceMethod())"
}
}
}
}
then, create an aspect class under src/groovy/com/test/aop/aspect
package com.test.aop.aspect
class LoggerAspect {
def beforeMethod(JoinPoint jp){
println '-- Before Method.'
}
def afterMethod(JoinPoint jp){
println '-- After Method.'
}
}
And create a service class under grails-app/services/com/test
package com.test
class DemoService {
def serviceMethod() {
println 'In DemoService.serviceMethod()'
}
}
And create a controller to call service for testing
package com.test
class DemoController {
def index() {
println 'In DemoController.index()'
def demoService = new DemoService()
demoService.serviceMethod()
render 'Hello World'
}
}
Finally, I test the aop through url:
http://myhost:8080/grails-spring-aop/demo/index
and the aop is not invoked. Following is the result:
| Server running. Browse to http://myhost:8080/grails-spring-aop/
In DemoController.index()
In DemoService.serviceMethod()
I add the following line to the service class:
static transactional = false
And, it's still not working for me.
Anyone an idea how this can be solved or is this not possible.
Or I do the something wrong.
Thanks.

You need to inject the service (spring bean) in the controller instead of creating an instance of it.
package com.test
class DemoController {
def demoService //Autowired, not required to specify in resources.groovy
def index() {
println 'In DemoController.index()'
demoService.serviceMethod()
render 'Hello World'
}
}
Moreover, the aspect can be made annotation based as below:
package com.test.aop.aspect
#Aspect
class LoggerAspect {
//A more generic advice would be as below
//#Before("execution(* com.test.*.*(..))")
#Before("com.test.DemoService.serviceMethod()")
def beforeMethod(){
println '-- Before Method.'
}
//A more generic advice would be as below
//#Around("execution(* com.test.*.*(..))")
#After("com.test.DemoService.serviceMethod()")
def afterMethod(){
println '-- After Method.'
}
}
And resources.groovy could become:
beans = {
loggerAspect(com.test.aop.aspect.LoggerAspect)
xmlns aop:"http://www.springframework.org/schema/aop"
aop{
config("proxy-target-class": true) {
aspect(id: "loggerAspectService", ref: "loggerAspect")
}
}
}

Related

Kotest and kotlinx-coroutines-test Integration

I use the Funspec testing style in kotest and I get a coroutineScope injected automatically by the framework as shown below.
class MyTestSpec: FunSpec() {
init {
test("test event loop") {
mySuspendedFunction() // a coroutineScope is already injected by the test framework here
}
}
}
How can I configure the Kotest framework to use an instance of kotlinx.coroutines.test.TestCoroutineScope instead of a kotlinx.coroutines.CoroutineScope in my tests? or is there a reason why this wouldn't make sense?
Since Kotest 5.0, there is built-in support for TestCoroutineDispatcher. See here
Simply:
class MyTest : FunSpec(
{
test("do your thing").config(testCoroutineDispatcher = true) {
}
}
)
Create a test listener like this:
class MainCoroutineListener(
val testDispatcher: TestCoroutineDispatcher = TestCoroutineDispatcher()
) : TestListener {
override suspend fun beforeSpec(spec: Spec) {
Dispatchers.setMain(testDispatcher)
}
override suspend fun afterSpec(spec: Spec) {
Dispatchers.resetMain()
testDispatcher.cleanupTestCoroutines()
}
}
Then use it in your test like this
class MyTest : FunSpec({
listeners(MainCoroutineListener())
tests...
})

How to execute method in class using Gradle task?

I want to execute Hello method in class using gradle task(at springboot). The sample is like below.
class MyClass
{
public void Hello()
{
System.out.println("Hello World");
}
}
Is there any way to execute Hello function in gradle task?
I had added below and tried but below task cannot parse MyClass token.
task myTest{
doLast {
println "Executing MyClass method"
def v = new MyClass();
v.Hello();
}
}

Groovy/Grails caching on function/closure

I would like to know how to add caching capability to a groovy function. Should it go in the Controller or the Service? Example: How would I cache myService.getData() result for 10 seconds?
class myController {
def getDataAsJson {
String result = myService.getData(id) // returns JSON
render result
}
}
class myService {
def getData(String id) {
return '{"hello":"world"}'
}
}
I am using Grails 3.3.2 and Groovy 2.4.13.
Cheers!

spring testing, how to mock the result of a method call using `#TestConfiguration`

I have this bean which is used somewhere inside of another bean I try to test. However I can not mock the method call since it always says _ is an unknown property.
#TestConfiguration
class IntegrationTestMockingConfig {
private DetachedMockFactory factory = new DetachedMockFactory()
#Bean
CloudStorage s3Client() {
def mockedS3 = factory.Mock(CloudStorage)
1 * mockedS3.tempDownload(_) >> {
log.info("mocked s3 client")
new File(ClassLoader.getSystemResource("testfiles/regular.zip").toURI())
}
mockedS3
}
}
Simply stub the method in your test's setup()-method. You can get the mock via dependency-injection into the test.
Mocking/stubbing outside of a Specification context is not supported. I'd suggest to use the #SpringBean of Spock 1.2.
#SpringBootTest
class MyTest extends Specification {
#SpringBean
CloudStorage mockedS3 = Mock()
def "test"() {
when:
otherBean.otherMethod()
then:
1 * mockedS3.tempDownload(_) >> {
log.info("mocked s3 client")
new File(ClassLoader.getSystemResource("testfiles/regular.zip").toURI())
}
}
}

how to check if a service implements an interface in grails

I have an interface "TestInterface" and grails service "TestService" that implements the "TestInterface". But when I test if I have a service that implements the interface like this:
application.serviceClasses?.each { serviceClazz ->
if(serviceClazz instanceof TestInterface) {
println "service name => "+ serviceClazz.name;
}
}
The result is I am not getting anything neither error nor my expectation ( service name => TestService )
I have also tried changing the serviceClazz to serviceClazz.class,serviceClazz.metaClass in the if condition but still not working.
Thank you,
What about:
if (TestInterface.class.isAssignableFrom(serviceClazz)) {
...
}
UPDATE
So I managed to run the actual example using Grails 2.3.11.
class BootStrap {
def grailsApplication
def init = { servletContext ->
grailsApplication.serviceClasses.each { serviceClazz ->
if (TestInterface.isAssignableFrom(serviceClazz.clazz)) {
println serviceClazz
}
}
}
def destroy = {
}
}
As you can see, the important part is clazz in serviceClazz.clazz.
Hope this helps!

Resources