2009-02-11 2 views
53

Grails может быть немного медведя, чтобы отлаживать его длинными свалками. Получение источника проблемы может быть сложным. Я несколько раз сжег в BootStrap.groovy, например, «def foo = new Foo (a: a, b: b) .save()». Какие ваши любимые трюки для отладки приложений Grails?Мои любимые трюки от Grails?

+2

Лучший вопрос в последнее время ... –

+1

@MichaelEaster прикомандирован. Поистине стыдно, что SO считает подобные статьи KB не конструктивными. Они так же конструктивны, как и они, и система голосования с ответами обеспечивает отличную систему коллективного сортировки советов от большинства до наименее полезных, гораздо более того, чем в стиле вики-стиля. – Tobia

ответ

32

Некоторые общие советы:

  • Clear stacktrace.log, сделать Grails запустить приложение, затем откройте StackTrace .log в средстве просмотра (я предпочитаю less stacktrace.log на linux) ... один раз в вашем телезрителе, ищите .groovy и .gsp ..., что обычно приводит вас к тому, что вас действительно волнует.
  • Когда стоп-трасса ссылается на номер строки в GSP-файле, вы должны открыть это представление в браузере с номером ?showSource в строке запроса, то есть http://localhost:8080/myProject/myController/myAction?showSource ... это показывает скомпилированный источник GSP и все номера строк GSP в stacktrace относятся к скомпилированному GSP, а не к фактическому источнику GSP.
  • Всегда, всегда, всегда окружайте ваши сбережения, по крайней мере, при минимальной обработке ошибок.

Пример:

try { 
    if(!someDomainObject.save()) { 
     throw new Exception ("Save failed") 
    } 
} catch(Exception e) { 
    println e.toString() 
    // This will at least tell you what is wrong with 
    // the instance you are trying to save 
    someDomainObject.errors.allErrors.each {error -> 
     println error.toString() 
    } 
} 

Кроме того, многое из этого просто сводится к распознаванию stacktraces и сообщения об ошибках ... много времени, Grails невероятно бесполезным в сообщениях об ошибках, которые она дает вы, но вы можете научиться распознавать образы, как следующее:

  • Некоторые из самых сложных ошибок, чтобы понять это, потому что вы не запускали grails clean или grails upgrade ... чтобы избежать их проблемы, я всегда использую следующее в командной строке для запуска grails: grails clean; yes | grails upgrade; grails run-app
  • Если ошибка связана с повторяющимися определениями класса, убедитесь, что вы объявляете пакет, к которому принадлежит класс, в верхней части класса file
  • Если ошибка связана с метаданными схемы, соединением, сокетом или чем-то подобным, убедитесь, что ваш соединитель базы данных находится в lib/, убедитесь, что ваши права указаны как в DataSource.groovy, так и в базе данных для имени пользователя, пароля , и хост, и убедитесь, что вы знаете входы и выходы версии вашего соединителя (т.е. MySQL Connector версии 5.1.x имеет странные проблемы с псевдонимами, которые могут потребовать, чтобы установить useOldAliasMetadataBehavior=true на URL в DataSource.groovy)

И так далее. Существует много шаблонов, чтобы научиться распознавать.

+0

«t/myController/myAction? ShowSource» Работает ли это в режиме производства? :) – itsraja

+0

Извините nope - только режим разработки, а не тест или производство –

+1

Я никогда не понимал, почему save не пошатнется. По умолчанию - я обнаружил, что это совершенно неожиданное поведение для каждого разработчика, которого я знаю, поэтому я хочу, чтобы ' grails.gorm.failOnError = true' Первое, что нужно сделать при запуске нового проекта. – elias

16
  • Чтобы добавить предложение Криса Кинга на сохранение, я написал многоразовое закрытие:

    Closure saveClosure = { domainObj -> 
         if(domainObj.save()) 
          println "Domain Object $domainObj Saved" 
         else 
         { 
           println "Errors Found During Save of $domainObj!" 
           println domainObj.errors.allErrors.each { 
            println it.defaultMessage 
           } 
         } 
        } 
    

Тогда вы можете просто использовать его везде, и он будет заботиться о сообщениях об ошибках:

def book = new Book(authorName:"Mark Twain") 
    saveClosure(book) 
  • Кроме того, я использую debug plugin - он позволяет выполнять дополнительную регистрацию, и я добавил тег в нижней части моей основной - это дает мне представление обо всех переменных в сеансе/запросе.

  • Runtime Logging plugin позволяет включить ведение журнала во время выполнения.

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

  • Консоль Grails также полезна. Я использую его для интерактивного поиска и экспериментирования с некоторым кодом, который также пригодится во время отладки.

  • И, конечно же, возможность прохода через отладчик сладка. Я переключился на IntelliJ IDEA, так как у него есть лучшая поддержка Grails/Groovy.

+2

is saveClosure (x) действительно, что groovy? Конечно, было бы лучше переопределить метод save()? – Armand

+3

Не беспокойтесь о p6spy. Используйте Spring Insight. Он имеет всю функциональность p6spy без проблем с конфигурацией. Кроме того, вы можете использовать его для настройки производительности. Посмотрите видео Питера Ледбрука. http://www.youtube.com/watch?v=rR-8EMKzduA – JGFMK

1

Для простых применений я использую инструкцию println. Это очень простой трюк. Для сложных приложений используется режим отладки в идее intellij.

14

Однажды я спросил опытного мастера-богатого о том, как он эффективно отлаживал свои приложения. Его ответ:

Я пишу тесты!

И у него есть очень хорошая точка: если ваш код имеет достаточные тесты на единицу и интеграцию, вам вряд ли когда-либо придется отлаживать что-либо. Кроме того, вы получите сказать самодовольные вещи, как, что для ваших коллег-разработчиков ...

Для Grails:

+3

Я рад видеть, что у нас наконец есть серебряная пуля. –

+14

WTF? Итак, как он отлаживал код, когда его тесты не удались? Или его код никогда не терпел неудачи? В каком случае он тестировал только то, что знал? Это очень странная вещь, чтобы сказать и напасть на меня как тавтологическую. Не говоря уже о самодовольстве, как вы правильно говорите. – Simon

+0

Ответ Simon & WTF на письменные тесты ... Вы можете попробовать добавить журнал в свои тесты. – JGFMK

4

I «Не уверен, что это можно сделать из коробки, но в webapps я считаю полезным иметь« кто я? » объект в различных файлах просмотра.

Идея состоит в том, чтобы передать сообщение в визуализированный HTML, чтобы идентифицировать фрагмент. Это особенно актуально, когда я впервые сталкиваюсь с приложением.

В Grails я делаю это с помощью специального тега. Например, рассмотрите список.GSP для студента:

<g:debug msg="student list" /> 

Вот код:

class MiscTagLib { 
    def debug = { map -> 
     if (grailsApplication.config.grails.views.debug.mode == true) { 
      def msg = map['msg'] 
      out << "<h2>${msg}</h2><br/>" 
     } 
    } 
} 

Ключ в том, что вы можете оставить эти метки там, при желании, как они появляются только в том, когда режим включен Config.groovy:

grails.views.debug.mode=true 
7

Для регистрации исключений с использованием GrailsUtil.

try{ 
    ... 
}catch (Exception e){ 
    log.error("some message", GrailsUtil.sanitize(e)) 
    ... 
} 

More info about sanitize.

4

Глядя на исходный код! Это спасло меня так много раз! И теперь, когда код размещен в GitHub, это проще, чем когда-либо. Просто нажмите «t» и начните вводить текст, чтобы найти класс, который вы ищете!

http://github.com/grails/grails-core

5

добавив этот код Bootsrap.groovy: INIT перезаписывает метод сохранения и выполнения какой-либо другой код, а также, печатая сообщения об ошибках в этом случае.

class BootStrap { 

    def grailsApplication 

    def init = {servletContext -> 

     grailsApplication.domainClasses.each { clazz -> 
      clazz.clazz.get(-1) 

      def gormSave = clazz.metaClass.getMetaMethod('save') 

      clazz.metaClass.save = {-> 

       def savedInstance = gormSave.invoke(delegate) 
       if (!savedInstance) { 
        delegate.errors.each { 
         println it 
        } 
       } 
       savedInstance 
      } 

      def gormSaveMap = clazz.metaClass.getMetaMethod('save', Map) 
      clazz.metaClass.save = { Map m -> 
       def savedInstance = gormSaveMap.invoke(delegate, m) 
       if (!savedInstance) { 
        delegate.errors.each { 
         println it 
        } 
       } 
       savedInstance 

      } 

      def gormSaveBoolean = clazz.metaClass.getMetaMethod('save', Boolean) 
      clazz.metaClass.save = { Boolean b -> 
       def savedInstance = gormSaveBoolean.invoke(delegate, b) 
       if (!savedInstance) { 
        delegate.errors.each { 
         println it 
        } 
       } 
       savedInstance 


      } 
     } 
... 
} 

надежда, что кто-то помогает :)

(я знаю его не очень DRY)

исх: http://grails.1312388.n4.nabble.com/How-to-override-save-method-on-domain-class-td3021424.html

Смежные вопросы