1

Although this or similar questions have been asked before for much older versions of grails, I wonder what would be the best approach to access a configuration value from application.yml in a grails domain class with modern grails 4.0.3.

So, let's say we have a voucher.groovy like

class Voucher implements HibernateEntity<Voucher> {
  ...

  Date reservedAt

  static transients = ['validUntil']

  Date getValidUntil() {
    Integer expirationTime = // TODO: fill in the configuration value

    DateTime expirationDateTime = new DateTime(this.reservedAt)
        .plusDays(expirationTime)
        .withHourOfDay(23)
        .withMinuteOfHour(59)
        .withSecondOfMinute(59)
        .withMillisOfSecond(999)
    return expirationDateTime.toDate()
  }

}

and a configuration value named voucher.expirationTime in our application.yml like

...
voucher.expirationTime: 10
...

How could I access the config value in my getValidUntil() method?

EDIT

As @JeffScottBrown mentioned in his comment, you shouldn't access config values in your domain class. So I ended up with his suggested apporach using a custom gsp tag. (See the answer below)

feuernurmitm
  • 312
  • 2
  • 11
  • 3
    I am leaving a comment instead of an answer because this does not answer your question as asked "How to access configuration values in domain classes?". You should not access configuration values in domain classes. A better idea for a number of reasons is to move the logic that needs the config into a service and inject config values there using `@Value`. – Jeff Scott Brown Jul 23 '20 at 12:39
  • Thank you, @JeffScottBrown! My final goal is to show the `validUntil` date in a gsp. Would it make sense to access to configuration value in the view or rather to fetch the `Voucher` via a service and add additional transient values in this service? – feuernurmitm Jul 23 '20 at 12:57
  • 1
    "Would it make sense to access to configuration value in the view or rather to fetch the Voucher via a service and add additional transient values in this service?" - I wouldn't do either of those. I would put the logic in a custom GSP tag, which are very simple to write and can also have configuration values injected into them using `@Value`. That keeps logic out of your GSP, which is good. – Jeff Scott Brown Jul 23 '20 at 13:38
  • @JeffScottBrown I don't think that accessing the config values in domain classes in general is evil. Yes, usually it occurs very rarely, but I can imagine some cases where config has some influence on how domain is persisted. Also, I don't want to break the active-record pattern and create services only to be able to grab some config values... – injecteer Jul 23 '20 at 14:50

1 Answers1

1

How to access configuration values in domain classes? You shouldn't!

In my case I needed to display a derived value as a combination of a domain attribute and a configuration value reservedAt + expirationTime. Thanks to Jeff Scott Brown's comment, I managed to create a custom gsp tag for my purpose:

class VoucherTagLib {
  static returnObjectForTags = ['validUntil']
  static namespace = "voucher"

  @Value('${voucher.expirationTime}')
  Integer expirationTime

  GrailsTagDateHelper grailsTagDateHelper

  def validUntil = { attrs, body ->
    Date reservedAt = attrs.reservedAt
    String style = attrs.style ?: "SHORT"

    Locale locale = GrailsWebRequest.lookup().getLocale()
    if (locale == null) {
      locale = Locale.getDefault()
    }
    def timeZone = grailsTagDateHelper.getTimeZone()

    def dateFormat = grailsTagDateHelper.getDateFormat(style, timeZone, locale)

    DateTime expirationDateTime = new DateTime(reservedAt)
        .plusDays(expirationTime - 1)
        .withHourOfDay(23)
        .withMinuteOfHour(59)
        .withSecondOfMinute(59)
        .withMillisOfSecond(999)

    return grailsTagDateHelper.format(dateFormat, expirationDateTime.toDate())

  }

}

Although this might not be the answer that you are looking for, I hope this will help others with a similar problem!

feuernurmitm
  • 312
  • 2
  • 11