2

次のコードは、何らかの理由で保存が失敗した場合にgrails.validation.ValidationExceptionをスローします。しかし、結果は一般的なエラーです。エラーの実際の原因を知り、ユーザーに報告できるようにするにはどうすればよいですか?

 def addChild(cName,Parent theParent) {
    println "add child: ${cName}"
    def theChild = new Child(name:cName,parent:theParent)
    theChild.save(failOnError:true)
    return theChild
}

これは返されるスタックトレースです。私はそれを故意に引き起こしたので、それがユニークな制約に違反することによって引き起こされていることを偶然知っていますが、それが原因であるのか他の制約違反であるのかを示すものはトレースにありません。

org.codehaus.groovy.runtime.InvokerInvocationException: grails.validation.ValidationException: Validation Error(s) Occurred During Save

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:646)

    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:436)

    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374)

    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)

    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)

    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)

    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)

    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)

    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)

    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)

    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)

    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)

    at java.lang.Thread.run(Thread.java:619)

Caused by: grails.validation.ValidationException: Validation Error(s) Occurred During Save

    at AddRecordsService.addChild(AddRecordsService.groovy:30)

    at AddRecordsService$addChild.callCurrent(Unknown Source)

    at AddRecordsService.addAll(AddRecordsService.groovy:11)

    at AddRecordsService$$FastClassByCGLIB$$e47d68f4.invoke(<generated>)

    at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)

    at AddRecordsService$$EnhancerByCGLIB$$cdfdcc61.addAll(<generated>)

    at AddRecordsService$addAll.call(Unknown Source)

    at AddrecordController$_closure2.doCall(AddrecordController.groovy:14)

    at AddrecordController$_closure2.doCall(AddrecordController.groovy)

    ... 32 more

アップデート

OK、少なくとも今のところ、トランザクションをロールバックしてエラーの原因を突き止める唯一の方法は、保存が失敗したかどうかを確認し、failedobject.errorsを取得して、RuntimeExceptionをスローすることです。しかし、エラーを呼び出し元のコントローラーに戻すにはどうすればよいでしょうか。以下は動作しません。

   def addChild(cName,Parent theParent) {
        println "add child: ${cName}"
        def theChild = new Child(name:cName,parent:theParent)

       //theChild.save(failOnError:true)
       //theChild.save()


        if(!theChild.save()){
            println theChild.errors
             throw new RuntimeException(theChild.errors)
            //throw new RuntimeException('unable to save child')
        } 


        return theChild
    }
4

4 に答える 4

2

古い質問ですが、誰かがそれに出くわした場合: サービスでは、Grails (2.1) のイディオムは save() を呼び出し、save失敗した場合は ValidationException をスローすることです。

 if (!theChild.save()) {
     throw new ValidationException(theChild.errors)
 } 

通常、 は呼び出しませんsave(failOnError: true)。代わりに、コントローラーで ValidationException をキャッチします。

try {
    service.addChild(child)
} catch (ValidationException e) {
    errors.allErrors.each {
        // do something with each error code
    }
}

コントローラーですべての作業を行う場合も同じ考えです。その場合、例外をスローしてキャッチする必要はもちろんありませんchild.errors。その場で処理できます。

于 2013-01-14T13:35:38.053 に答える
0

確かに、現在、save(failOnError:true) アプローチでは、問題の原因となった検証に関する情報がほとんど得られません。(とにかくコントローラーで例外メッセージを解析しますか?) ただし、トランザクションのロールバックと通信の検証エラー情報の 2 つの異なる問題に対処するために検討できる複数の代替手段があります。

1 つの代替方法は、データの永続化を完全に回避することです。まず、theChild.validate() を呼び出して、theChild を保存できるかどうかを確認します。検証に失敗しなかった場合、validate() は true を返すので、theChild.save() を呼び出します。検証エラーが発生した場合、それらは theChild のエラー オブジェクトに記録されます。呼び出し元のコントローラーに返された新しく作成された子は、エラーがないか検査するか、単にビューでユーザーに表示することができます。

もう 1 つの方法は、宣言型トランザクションを使用しないことです。つまり、サービスで static transactional = false を設定します。次に、コードでトランザクション自体を管理できます。このようなもの:

Child.withTransaction { txStatus ->
   try {
     child.save(failOnError:true)
   } catch (ValidationException e) {
     // rollback, but swallow exception, requiring caller to check child for errors
     txStatus.setRollbackOnly()
   }
}

最後に、あなたの質問は、ユーザーがエントリを修正できるように元のページをレンダリングするなど、コントローラーがエラー情報を処理することを意味します。theChild は検証されるものであるため、例外がスローされている場合 (自分自身または ValidationException) に子を返すことはできません。ただし、子には save() 呼び出し中にエラーが入力されます。String と Parent を渡してからサービスで Child をインスタンス化する代わりに、呼び出し元で Child をインスタンス化し、参照渡しすることを検討する必要があります。次に、save() が失敗すると、save(failOnError:true) が ValidationException になったとしても、子のエラーが取り込まれます。呼び出し元は、ValidationException をキャッチし、ビューのモデルの一部として子を返すことができます。

個人的には、トランザクションを手動で管理するよりも、最初の選択肢 (validate() を最初に呼び出す) または最後の選択肢 (子をサービス外でインスタンス化する) が望ましいと思います。Grails では、宣言型トランザクション管理は、サービス全体にとってオール オア ナッシングです。つまり、サービスに対してstatic transactional = falseを設定すると、サービスのすべてのメソッドですべてのトランザクションを手動で管理する必要があります。ここでは KISS の原則を適用する必要があります。

于 2009-10-30T06:31:20.930 に答える
0

ValidationException には、検証に失敗したオブジェクトへの参照があると思いますか? 存在する場合は、errors プロパティでエラーのリストを確認します。

そうでない場合は、キャッチしてから theChild.errors でエラーを確認する必要があります。

于 2009-10-29T02:41:24.867 に答える
0

検証のために grails コマンド クラスを使用してみてくださいREFER HERE

例 :

class ParentCommand  {
    .....field.....
     ........constraint.....
   }


def addChild(cName,ParentCommand cmd) {
     if(cmd.hasErrors()) {
    render (cmd.errors as JSON).toString();
    return "false";
} 
于 2014-01-28T14:45:44.403 に答える