Исключение NullPointerException с внедрением зависимостей

#grails #dependency-injection

#grails #внедрение зависимостей

Вопрос:

Я пытаюсь использовать внедрение зависимостей для экспорта в функциональность Excel, предоставляемую «Плагином экспорта», Кажется, что всякий раз, когда я пытаюсь использовать сервис в своем проекте, я получаю ошибку, подобную следующей

 Stacktrace follows:
java.lang.NullPointerException: Cannot invoke method export() on null object
    at pm.ProjectsController$_closure2.doCall(ProjectsController.groovy:39)
    at pm.ProjectsController$_closure2.doCall(ProjectsController.groovy)
    at java.lang.Thread.run(Thread.java:662)
  

Код, который я использую, следующий, это просто означает, что служебная переменная имеет значение null

 def exportService// i have  tried with and without the initialization
        if(params?.format amp;amp; params.format != "html"){
            response.contentType = ConfigurationHolder.config.grails.mime.types[params.format]
            response.setHeader("Content-disposition", "attachment; filename=books.${params.extension}")

            exportService.export(params.format, response.outputStream,projectsList, [:], [:])
        }
  

Похоже, что в моем проекте не работает ни один плагин, который использует сервисы, например, AsynchronousMailService в моем проекте не работал так, как предполагалось, и поэтому я использовал его следующим образом

 AsynchronousMailService asynchronousMailService = new AsynchronousMailService()
            asynchronousMailService.sendAsynchronousMail  {    
                to projectsInstance.projectLead.emailAddress
                subject "New project is assigned to you"
                html msg
            }
  

Если я не пропускаю что-то очень простое, я не верю, что я должен создавать экземпляр этого класса, если плагин предлагает то же самое, что и service.

Спасибо

Ответ №1:

Правильно, вы никогда не должны создавать экземпляры сервисов или других компонентов Spring — используйте внедрение зависимостей. Это может сработать, но если у компонента есть какие-либо собственные зависимости, они будут нулевыми, поскольку вы обходите Spring.

Вы не используете внедрение зависимостей, вы объявляете локальную переменную и ожидаете волшебства.

Внедрение зависимостей в Grails использует общедоступные поля. Поскольку Groovy создает общедоступное поле в получателе и установщике под капотом, Spring видит установщик, а Grails настроен на ввод по имени, поэтому, пока поле / установщик соответствует имени компонента Spring, оно работает.

Итак, ваш контроллер должен выглядеть примерно так:

 class MyController {

   def exportService

   def myAction = {
      if (params?.format amp;amp; params.format != "html") {
         response.contentType = grailsApplication.config.grails.mime.types[params.format]
         response.setHeader("Content-disposition",
                            "attachment; filename=books.${params.extension}")

         exportService.export(params.format,
                 response.outputStream,projectsList, [:], [:])
      }
   }
}
  

Обратите внимание, что я также удалил использование ConfigurationHolder, поскольку оно устарело. Лучший способ получить доступ к конфигурации — из grailsApplication компонента. Оно уже внедрено в контроллеры (и теги), а в сервисе или другом компоненте вам просто понадобится def grailsApplication объявление поля.