【问题标题】:g.formatDate raises error when executed from a Job?g.formatDate 从作业执行时会引发错误?
【发布时间】:2015-12-26 04:52:43
【问题描述】:

我使用 Grails 作业来启动使用 g.formatDate 的服务。直接从控制器使用服务时,我没有问题。当我使用作业中的服务时,出现以下错误:

ERROR listeners.ExceptionPrinterJobListener  - Exception occurred in job: Grails Job
Message: java.lang.NullPointerException
   Line | Method
->> 111 | execute in grails.plugins.quartz.GrailsJobFactory$GrailsJob
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|   202 | run     in org.quartz.core.JobRunShell
^   573 | run . . in org.quartz.simpl.SimpleThreadPool$WorkerThread
Caused by NullPointerException: null
->> 245 | $tt__sendReportCompanyWeekly in Test.SendMailService$$EPPc274K
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    47 | doCall  in Test.ReportCompanyWeeklyJob$_execute_closure1
|    31 | execute in Test.ReportCompanyWeeklyJob$$EPPc2HTU
|   104 | execute in grails.plugins.quartz.GrailsJobFactory$GrailsJob
|   202 | run . . in org.quartz.core.JobRunShell
^   573 | run     in org.quartz.simpl.SimpleThreadPool$WorkerThread

这是我的工作:

class ReportCompanyWeeklyJob {  

  SendMailService sendMailService


  static triggers = {
    cron name: 'scheduledReportCompanyWeeklyJob', cronExpression: "0 15 22 ? * *" 
  }

  def execute() {
    sendMailService.sendReportCompanyWeekly(company.id, user.id)
  }

}

这是我的服务:

@Transactional
class SendMailService {

    def gspTagLibraryLookup  // being automatically injected by spring
    def g

  def sendReportCompanyWeekly(String companyId, String userId) {    
    g = gspTagLibraryLookup.lookupNamespaceDispatcher("g")

    Date today = new Date()
    Locale locale = // some locale

    // Line 245
    def test = g.formatDate(date: today, formatName: 'date.format.long.no.year', locale: locale)  

 }

}

编辑:我使用groovyPageRenderer.render(template: viewPathHTML, model: myModel) 在服务中呈现 GSP。

如何让 g.formatDate 从 Job 运行时工作?

【问题讨论】:

  • 为什么要从服务中调用 gsp 标签?
  • 因为我必须为电子邮件呈现 GSP 模板。
  • 没有完全错误的答案。
  • 我使用groovyPageRenderer.render(template: viewPathHTML, model: myModel) 在服务中呈现 GSP。你还有什么想法吗?

标签: grails groovy


【解决方案1】:

grails.gsp.PageRenderer 可以呈现的内容受到限制,因为它与从控制器呈现 GSP 页面的上下文不同。

当使用 formatName 时,g.formatDate() 会尝试从 GrailsWebRequest 获取 LocaleLocale 用于从MessageSource 检索“date.format.long.no.year”。问题是grails.gsp.PageRenderer 没有GrailsWebRequest。可以看g.formatDate()源代码here

解决方法

您可以通过格式化服务中的日期并通过模型将其传递给 GSP 来解决此问题。像这样的:

import java.text.SimpleDateFormat

@Transactional
class SendMailService {

    ...
    def messageSource // Injected to look up 'date.format.long.no.year'

    def sendReportCompanyWeekly(String companyId, String userId) {    
        Date today = new Date()
        Locale locale = // some locale

        def formattedDate = new SimpleDateFormat(messageSource.getMessage('date.format.long.no.year', null, locale), locale)
            .format(today)

        /* 
          1. Add the formattedDate to the PageRenderer model, 
          2. Update the GSP code to use the value from the model instead of g.formatDate()
        */
    }

}

更好的主意 - 创建一个 formatDate 闭包

import java.text.SimpleDateFormat

@Transactional
class SendMailService {

    ...
    def messageSource // Injected to look up 'date.format.long.no.year'

    def sendReportCompanyWeekly(String companyId, String userId) {    
        Date today = new Date()
        Locale locale = // some locale

        def formatter= new SimpleDateFormat(messageSource.getMessage('date.format.long.no.year', null, locale), locale)

        def formatDate = { Date date -> formatter.format(date) }

        /* 
          1. Add the formatDate Closure to the PageRenderer model, 
          2. Update the GSP code to use the Closure from the model instead of g.formatDate()
        */
    }

}

【讨论】:

  • 如何调用闭包?为它创建一个tagLib不是更好吗?
  • 这里是一个例子<div>${myFormatDate(somedate)}<\div> 如果你创建一个标签库,你必须传入足够多的参数(例如语言环境),以便它可以使用消息源。可能但更棘手。
  • 你也有标签库的例子吗?
猜你喜欢
  • 1970-01-01
  • 2014-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-15
  • 2017-10-04
  • 2020-12-17
  • 2012-09-30
相关资源
最近更新 更多