2014-07-16 3 views
1

У меня есть метод обслуживания, который выполняет некоторую операцию внутри транзакции.Как узнать исключение, возникшее в транзакции grails?

public User method1() { 
    // some code... 
    Vehicle.withTransaction { status -> 
     // some collection loop 
     // some other delete 
     vehicle.delete(failOnError:true) 
    } 

    if (checkSomething outside transaction) { 
     return throw some user defined exception 
    } 

    return user 
} 

Если есть исключение во время выполнения мы не должны поймать это исключение, и транзакция будет откат автоматически. Но как определить, что транзакция откатилась из-за какого-то исключения, и я хочу бросить какое-то удобное сообщение об ошибке. delete() также не вернет ничего.

Если я добавлю блок try/catch внутри транзакции, поймав Exception (суперкласс), он не попадает в этот блок исключений. Но я ожидал, что он войдет в этот блок и бросит удобное для пользователя исключение.

EDIT 1: Это хорошая идея, чтобы добавить try/catchwithTransaction Arround

Любая идея, как решать это ?? Заранее спасибо.

ответ

1

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

Прежде чем перейти к коду, я могу предложить несколько вещей. Во-первых, вам не нужно явно объявлять транзакцию в службе (я использую v2.2.5). Услуги являются транзакционными по умолчанию (не большая сделка).

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

В-третьих, я бы рекомендовал удалить failOnError:true с save() (я не думаю, что он работает на delete() ... Возможно, я ошибаюсь?). Я считаю, что проще запустить validate() или save() в службе, а затем вернуть экземпляр модели контроллеру, где ошибки объектов могут использоваться во флэш-сообщении.

Ниже приведен пример того, как мне нравится обрабатывать исключения и сейв, используя метод обслуживания и попытаться/поймать в контроллере:

class FooService { 
    def saveFoo(Foo fooInstance) { 
     return fooInstance.save() 
    } 

    def anotherSaveFoo(Foo fooInstance) { 
     if(fooInstance.validate()){ 
      fooInstance.save() 
     }else{ 
      do something else or 
      throw new CustomException() 
     } 

     return fooInstance 
    } 

} 

class FooController { 
    def save = { 
     def newFoo = new Foo(params) 
     try{ 
      returnedFoo = fooService.saveFoo(newFoo) 
     }catch(CustomException | Exception e){ 
      flash.warning = [message(code: 'foo.validation.error.message', 
        args: [org.apache.commons.lang.exception.ExceptionUtils.getRootCauseMessage(e)], 
        default: "The foo changes did not pass validation.<br/>{0}")] 
      redirect('to where ever you need to go') 
      return 

     } 

     if(returnedFoo.hasErrors()){ 
      def fooErrors = returnedFoo.errors.getAllErrors() 

      flash.warning = [message(code: 'foo.validation.error.message', 
        args: [fooErrors], 
        default: "The foo changes did not pass validation.<br/>${fooErrors}")] 
      redirect('to where ever you need to go') 
      return 
     }else { 
      flash.success = [message(code: 'foo.saved.successfully.message', 
           default: "The foo was saved successfully")] 
      redirect('to where ever you need to go') 
     } 
    } 
} 

Надеется, что это помогает, или получает какой-то другой вход от более опытного Grails Разработчики.

Вот несколько других способов, которые я нашел, чтобы получить информацию об исключении пройти по своему пользователю:

request.exception.cause 
request.exception.cause.message 
response.status 

Несколько ссылок на другие соответствующие вопросы, которые могут помочь:

Exception handling in Grails controllers

Exception handling in Grails controllers with ExceptionMapper in Grails 2.2.4 best practice

https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ExceptionUtils.html

+0

Спасибо @CheddarMonkey. Поэтому вы рекомендуете окружать сервисный вызов с помощью try/catch. Тогда мой «РЕДАКТИРОВАТЬ 1» в вопросе правильный способ сделать это ?? !! – user2001627

+0

Вы хотите, чтобы try/catch в контроллере вокруг вызова службы, как в примере, где он обертывает 'returnFoo = fooService.saveFoo (newFoo) ' – CheddarMonkey

+0

Да, но в наших контроллерах мы стараемся избегать try/catch и просто просим просто позвонить в службу (службы), и служба поставит ответное сообщение, для которого контроллер должен просто передать его. Потому что в некоторых сценариях у нас есть много разных вызовов для обслуживания api разных классов, тогда контроллер будет заселен try/catch. Спасибо за ваши материалы. – user2001627

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