Search code examples
grails

Grails: How to override generated service method?


Grails novice here. I would like to override the get() and list() methods of the generated service shown here.

@Service(PlayerFile)
interface PlayerFileService {
    PlayerFile get(Serializable id)
    List<PlayerFile> list(Map args)
    Long count()
    void delete(Serializable id)
    PlayerFile save(PlayerFile playerFile)
}

Why? The default service/scaffolding model shows all domain objects for the PlayerFile class. I want to filter this so that only the objects belonging to the logged in user (i.e. the owner) are displayed.

I appreciate your recommendations on how to do this.

Here is the PlayerFile domain class

class PlayerFile {
    String playersJson
    Date dateCreated
    Date lastUpdated

    static belongsTo = [owner: User]

    static constraints = {
        playersJson sqlType: 'text', nullable: false, widget: 'textarea'
        owner nullable: false, editable: false
    }
}

Solution

  • You probably don't want to override the get method. You probably want a new query method...

    @Service(PlayerFile)
    interface PlayerFileService {
        PlayerFile get(Serializable id)
        List<PlayerFile> list(Map args)
        Long count()
        void delete(Serializable id)
        PlayerFile save(PlayerFile playerFile)
    
    
        List<PlayerFile> findByOwner(User owner)
    }
    

    If you don't need the get method for other purposes, delete it.

    EDIT

    Addressing the comment below:

    Where do I put the code for findByOwner() shown above? It can't be added to an abstract interface.

    I don't agree with that. It can definitely be in an abstract interface. You could turn PlayerFileService into an abstract class and make findByOwner a concrete method, but you do not have to. It can be an abstract method in an interface, which is the common thing in a GORM Data Service like this.

    See the project at https://github.com/jeffbrown/rock298query.

    https://github.com/jeffbrown/rock298query/blob/3eb713a5ac2692be1fd9666eb7e6b26c8c9a0921/grails-app/services/rock298query/PlayerFileService.groovy

    package rock298query
    
    import grails.gorm.services.Service
    
    @Service(PlayerFile)
    interface PlayerFileService {
        PlayerFile get(Serializable id)
        List<PlayerFile> list(Map args)
        Long count()
        void delete(Serializable id)
        PlayerFile save(PlayerFile playerFile)
    
        List<PlayerFile> findByOwner(User owner)
    }
    

    https://github.com/jeffbrown/rock298query/blob/3eb713a5ac2692be1fd9666eb7e6b26c8c9a0921/grails-app/init/rock298query/BootStrap.groovy

    package rock298query
    
    class BootStrap {
    
        UserService userService
        PlayerFileService playerFileService
    
        def init = { servletContext ->
            def jeff = userService.save('Jeff')
            def jake = userService.save('Jake')
    
            jeff.addToFiles(new PlayerFile(playersJson: '{"title":"Jeff File 1"'))
            jeff.addToFiles(new PlayerFile(playersJson: '{"title":"Jeff File 2"'))
            jeff.addToFiles(new PlayerFile(playersJson: '{"title":"Jeff File 3"'))
    
            userService.save jeff
    
            jake.addToFiles(new PlayerFile(playersJson: '{"title":"Jake File 1"'))
            jake.addToFiles(new PlayerFile(playersJson: '{"title":"Jake File 2"'))
            jake.addToFiles(new PlayerFile(playersJson: '{"title":"Jake File 3"'))
    
            userService.save jake
    
        }
        def destroy = {
        }
    }
    

    https://github.com/jeffbrown/rock298query/blob/3eb713a5ac2692be1fd9666eb7e6b26c8c9a0921/grails-app/controllers/rock298query/DemoController.groovy

    package rock298query
    
    class DemoController {
    
        PlayerFileService playerFileService
        UserService userService
    
        def jakeFiles() {
            def jake = userService.find('Jake')
    
            def files = playerFileService.findByOwner(jake)
    
            render files*.playersJson
        }
    
        def jeffFiles() {
            def jeff = userService.find('Jeff')
    
            def files = playerFileService.findByOwner(jeff)
    
            render files*.playersJson
        }
    }
    

    That all appears to work.

    ~ $ curl  http://localhost:8080/demo/jakeFiles
    ['{"title":"Jake File 1"', '{"title":"Jake File 2"', '{"title":"Jake File 3"']
    ~ $ 
    ~ $ curl  http://localhost:8080/demo/jeffFiles
    ['{"title":"Jeff File 1"', '{"title":"Jeff File 2"', '{"title":"Jeff File 3"']
    

    I hope that helps.