Call groovy parent class method - Grails - grails

I have a Grails service,
Parent Class:
class BarService{
def fetchData(params) {
return fooData.toString()
}
}
Child Class:
class FooService extends BarService{
def fetchData(params) {
def fooData = super.fetchData(params) //this will call the BarService method
return fooData
}
}
Is this the right groovy way of doing it? Because to me this looks like Java
Thanks

As per your example, there is not much that can be done, except maybe removing the optional return keyword:
// Parent Class:
class BarService{
def fetchData(params) {
params.fooData.toString()
}
}
// Child Class:
class FooService extends BarService{
def fetchData(params) {
super.fetchData params
}
}
assert new FooService().fetchData([fooData: 900]) == "900"

The "return" keyword isn't the problem (as U can see here - https://groovyconsole.appspot.com/edit/5158539458772992). If You're getting a "null", the problem is the code at:
return fooData.toString()
Should be like the #WillP said (with "return" keywork optionally):
return param.fooData.toString()

Related

Grails controllers and inheritance/closures

Grails 2.4.4 here. All of my controllers were generated using the standard grails create-controller ... command:
class FizzController {
def index() {
// ...
}
}
class BuzzController {
def index() {
// ...
}
}
...etc.
At the top of each action method, in each controller, I need to call a method doSomething(String). This method needs to have access to redirect(...) so that it can redirect the user if need be. Ideally, I could create an abstract base controller class and have all my controllers extend it:
abstract class BaseController {
void doSomething(String cmd) {
if(cmd == 'Yee haw!') {
redirect(controller: 'foo', action: 'baz')
return false
}
}
}
class FizzController extends BaseController {
def index() {
String cmd = getCmdSomehow()
doSomething(cmd)
// ...etc.
}
}
class BuzzController extends BaseController {
def index() {
String cmd = getCmdSomehow()
doSomething(cmd)
// ...etc.
}
}
However I'm not sure Grails will allow this, since it's doing "Groovy magic" under the hood to make sure there is access to things like redirect(...) and render(...), etc. It would also be wonderful if I could put all this in a closure and just have it executed implicitly (without having to call doSomething() at the beginning of each and every controller action.
What is my best option/solution here? Please use a concrete code example!
Use Filter instead:
class ExampleFilters {
def filters = {
logFilter(controller: '*', action: '*') {
before = {
}
after = { Map model ->
}
afterView = {
}
}
}
}

Grails create instance of inner class of service

In Grails, services are singletons by default. Can I keep it that way and still create an instance of an inner class of that service from a controller?
//by default grails makes MyTestService a singlton
class MyTestService{
public class InnerTest{
String msg;
def addMsg(String str){
this.msg=str;
}
def printMsg(){
println this.msg;
}
}
}
In controller "MyController"...
def m=myTestService.getInstance().new InnerTest();
//produces " MyTestService.InnerTest cannot be cast to MyTestService.InnerTest"
def m=myTestService.new InnerTest();
//No signature of method:MyController.InnerTest()
You should be able to do something like:
class MyTestService{
public class InnerTest{
String msg;
def addMsg(String str){
this.msg=str;
}
def printMsg(){
println this.msg;
}
}
def InnerTestFactory() {
new InnerTest()
}
}
And use it from your controller:
def m=myTestService.InnerTestFactory();

Grails Reusable Service for saving Domain Objects

I have a Grails project with multiple Domain Classes, and I want to make a persistence service as reusable as possible by only having one save() inside of it. To try and achieve this I have done the following in my project.
//PersistenceService.groovy
#Transactional
class PersistenceService {
def create(Object object) {
object.save flush: true
object
}
//BaseRestfulController
class BaseRestfulController extends RestfulController {
def persistenceService
def save(Object object) {
persistenceService.create(object)
}
//BookController
class BookController extends BaseRestfulController {
private static final log = LogFactory.getLog(this)
static responseFormats = ['json', 'xml']
BookController() {
super(Book)
}
#Transactional
def save(Book book) {
log.debug("creating book")
super.save(book)
}
So basically I have a bunch of domains for example Author etc, each with their own controller similar to the bookController. So is there a way to reuse the service for persistence like I am trying above?
Thank you
I'm doing something similar, but mainly because all my entities are not actually removed from the database but rather "marked" as removed. For several apps you need such an approach since it's critical to prevent any kind of data loss.
Since most databases do not provide support for this scenario, you can't rely on foreign keys to remove dependent domain instances when removing a parent one.
So I have a base service class called GenericDomainService which has methods to save, delete (mark), undelete (unmark).
This service provides a basic implementation which can be applied to any domain.
class GenericDomainService {
def save( instance ) {
if( !instance || instance.hasErrors() || !instance.save( flush: true ) ) {
instance.errors.allErrors.each {
if( it instanceof org.springframework.validation.FieldError ) {
log.error "${it.objectName}.${it.field}: ${it.code} (${it.rejectedValue})"
}
else {
log.error it
}
}
return null
}
else {
return instance
}
}
def delete( instance, date = new Date() ) {
instance.dateDisabled = date
instance.save( validate: false, flush: true )
return null
}
def undelete( instance ) {
instance.dateDisabled = null
instance.save( validate: false, flush: true )
return null
}
}
Then, in my controller template I always declare two services: the generic plus the concrete (which may not exist):
def ${domainClass.propertyName}Service
def genericDomainService
Which would translate for a domain called Book into:
def bookService
def genericDomainService
Within the controller methods I use the service like:
def service = bookService ?: genericDomainService
service.save( instance )
Finally, the service for a given domain will inherit from this one providing (if needed) the custom logic for these actions:
class BookService extends GenericDomainService {
def delete( instance, date = new Date() ) {
BookReview.executeUpdate( "update BookReview b set b.dateDisabled = :date where b.book.id = :bookId and b.dateDisabled is null", [ date: date, bookId: instance.id ] )
super.delete( instance, date )
}
def undelete( instance ) {
BookReview.executeUpdate( "update BookReview b set b.dateDisabled = null where b.dateDisabled = :date and b.book.id = :bookId", [ date: instance.dateDisabled, bookId: instance.id ] )
super.undelete( instance )
}
}
Hope that helps.

Why can't I access injected service from scaffolding template for controller?

I have a controller which looks like this:
class CategoryController {
static scaffold = true
def messageSource
def categoryService
...
}
I want to modify Controller template to use service when needed:
class ${className}Controller {
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
def list() {
def domainObjectsProperty = ... //long complex line
render view: "/${domainClass.propertyName}/list", model: [(domainObjectsProperty): ${domainClass.propertyName}Service.list()]
}
...
}
Expression ${domainClass.propertyName}Service is evaluated to categoryService, but I get message:
No such property: categoryService for class:
mypackage.CategoryController
At the same time, when I call not scaffolded methods of CategoryController, which use CategoryService, everything is fine.
What causes this behavior and how to work around the issue? Thanks!
I think you forgot the service injection
class ${className}Controller {
def ${domainClass.propertyName}Service
...
}

Cannot inject any service annotated with #Transactional into any controller in 1.3.7

i'm caught in a strange question about grails injection any service annotated with #Transactional into any controller in 1.3.7.
SyncSpInfoService:
package test
import org.springframework.transaction.annotation.*
class SyncSpInfoService {
static transactional = false
#Transactional
def syncSpInfoData(def dataSource)throws RuntimeException{
...
}
Controller:
package test
class SyncSpInfoController {
def syncSpInfoService
def dataSource
def index = {
try{
syncSpInfoService.syncSpInfoData(dataSource)
render "Success"
return
}catch(RuntimeException e){
e.printStackTrace()
render "Error:"+e.getMessage()
return
}
}
}
And run the controller,if the SyncSpInfoService is caugth in error,then i modify it,and run it again,there are errors as following:
Error:test.SyncSpInfoService cannot be cast to test.SyncSpInfoService
i don't why? Pls help me,thx a lot...
Try removing the 'def' in your service method parameter:
def syncSpInfoData(datasource) {} // and you don't need the throws

Resources