9

I need to call the Static Resources Plugin (http://www.grails.org/Static+Resources+Plugin) from my domain class.

This works perfectly in a controller:

 def tstLink = resourceLinkTo(dir:"docs/${identifier}",file:originalFileName)

but in a domain class I get

Exception Message: No signature of method: static org.maflt.ibidem.Item.resourceLinkTo() is applicable for argument types: (java.util.LinkedHashMap) values: [[dir:docs/19e9ea9d-5fae-4a35-80a2-daedfbc7c2c2, file:2009-11-12_1552.png]] 

I assume this is a general problem.

So how do you call a taglib as a function in a domain class?

Brad Rhoads
  • 1,828
  • 3
  • 29
  • 52
  • I just ran up against the same exact problem and was about to ask this question myself before finding yours. – Mark S Jan 29 '10 at 03:25
  • 1
    The accepted answer is good for general taglib calls, but for the specific use-case of generating links you can get ahold of the `grailsLinkGenerator` bean in your service by just `def grailsLinkGenerator` in your service class. Then you can call the `link` method and pass it parameters, or access the `serverBaseURL` property. – Ted Naleid Aug 13 '12 at 20:56
  • @TedNaleid that option may not have been available at the time I wrote my answer. That would be the cleaner approach. – Matt Lachman Jul 18 '13 at 13:43

2 Answers2

11

I encountered this problem a while ago for an app I was working on. What I ended up doing was putting a call to the tag in a service method:

class MyService {
   def grailsApplication //autowired by spring

   def methodThatUsesATag(identifier, originalFileName) {
      //This is the default grails tag library
      def g = grailsApplication.mainContext.getBean('org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib')

      g.resourceLinkTo(dir:"docs/${identifier}",file:originalFileName)
   }
}

Then in my domain class, I could get to the service via spring autowiring as well:

class MyDomain {
    String originalFileName
    def myService  //autowired

    static transients = ['myService'] //Necessary so that GORM doesn't try to persist the service instance.

    //You can create a method at this point that uses your
    //service to return what you need from the domain instance.
    def myMethod() {
       myService.methodThatUsesATag(id, originalFileName)
    }
}
Matt Lachman
  • 4,541
  • 3
  • 30
  • 40
  • You can use that same dependency injection in domain objects directly - you do not need to use a service to do the work for you. – Nancy Deschênes Mar 03 '14 at 16:15
  • That may be true now. It wasn't when I answered this question originally. – Matt Lachman Mar 04 '14 at 02:56
  • 1
    I have since also discovered that you can call getDomainClass().getGrailsApplication() from a domain object (or domainClass.grailsAppliction) to get the GrailsApplication. It looks like this became available with Grails 2.0 – Nancy Deschênes Mar 04 '14 at 14:28
-1

Most taglibs rely on data from the controller so it's often not possible to reuse them while others concern view logic so often it's not something you would want to put in a domain class.

That said, I'm sure you have your reasons so maybe the source of the taglib will help:

class ResourceTagLib  {

    def externalResourceServerService

    def resourceLinkTo = { attrs ->
        out << externalResourceServerService.uri
        out << '/'
        if(attrs['dir']) {
            out << "${attrs['dir']}/"
        }
        if(attrs['file']) {
            out << "${attrs['file']}"
        }
    }
}

ie inject the externalResourceServerService into your domain class and the rest should be simple.

Dave Bower
  • 3,487
  • 26
  • 28
  • Thanks. I would have expected that to work too. I did def tstLink = externalResourceServerService.resourceLinkTo(dir:"docs/${identifier}",file:originalFileName) but got No signature of method: ExternalResourceServerService.resourceLinkTo() is applicable for argument types: (java.util.LinkedHashMap) values: [[dir:docs/279a5b71-b05f-4d62-be7b-72a805b005e0, file:me.jpeg]] – Brad Rhoads Jan 29 '10 at 17:54
  • So it seems like I just need to get the data types correct. This doesn't work either def tstLink2 = externalResourceServerService.resourceLinkTo ("docs/${identifier}".toString(),originalFileName) with or without the toString(). – Brad Rhoads Jan 29 '10 at 18:08