简体   繁体   English

Grails:验证域对象时出现“ methodInvocation”错误代码

[英]Grails : 'methodInvocation' error code when validate domain object

Since two weeks, a wild issue appears ! 两个星期以来,出现了一个大问题! It comes only in production (not in dev, integration, preproduction modes) and after hours.... 它仅在生产中出现(不在开发,集成,预生产模式中)和下班后出现。

Symptoms : once "something" happens, users cannot sign up anymore. 症状:一旦发生“某事”,用户将无法注册。 After days and days of investigations, I have no clue how to reproduce neither where come this issue. 经过数天的调查,我不知道该如何复制这个问题。 For now, we have the ugly workaround to restart tomcat instances, but this is VERY ugly. 目前,我们有丑陋的解决方法来重新启动tomcat实例,但这非常丑陋。

For information, differences between two deliveries doesn't touch around the sign up process. 有关信息,两个交付之间的差异与注册过程无关。

Here what I think is relevant : 我认为这是相关的:

Domain : 域:

class UserAccount implements Serializable {
    static transients = ['tokenLogin']
    String email
    String pwd
    Date creationDate = new Date()
    String tokenLogin


    //[skip] dozen of other attributes

    static constraints = {
        email(matches:EmailRegexp,blank:false)
        pwd(blank:false)
        tokenLogin(editable:false)
    }

    public void setEmail(String email) {
        this.email = email
        authId = authenticationChannel.getUsername(email)
        // We must recalculate token login
        this.tokenLogin = generateTokenLogin(email, creationDate, pwd)
    }

    public void setPwd(String pwd) {
        this.pwd = pwd
        // We must recalculate token login
        this.tokenLogin = generateTokenLogin(email, creationDate, pwd)
    }

    public static String generateTokenLogin(String email, Date creationDate, String pwd) {
        // work well
        // even tested when return null or with NPE in it and does not produce the same log
        generated = // work with MessageDigest, MD5, salt, etc. (not disclosed, because we are currently under security audit)
        return generated;
    }
}

Controller : 控制器:

def saveAccount = {
    def user = new UserAccount(email: params.email?.trim(), pwd: params.pwd) // More parameters, but here what is relevant
    user.validate()
    if(user.hasErrors()) log.info("${user.errors}") // added since the issue appears
    // Other verification (unicity, clear password verification, etc.)
    // Password encryption
    // user.save()
}

Output log : 输出日志:

2013-06-03 15:37:32,165 [TP-Processor46] INFO  controller.UserAccountController  - org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'domain.UserAccount' on field 'pwd': rejected value [foobar]; codes [methodInvocation.domain.UserAccount.pwd,methodInvocation.pwd,methodInvocation.java.lang.String,methodInvocation]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [domain.UserAccount.pwd,pwd]; arguments []; default message [pwd]]; default message [Property 'pwd' threw exception; nested exception is java.lang.NullPointerException]

Questions : 问题:

  • How this output might be appears? 此输出如何显示? We saw this ouput either for pwd or email field, never for others. 我们看到此输出用于pwdemail字段,从未为其他人使用。
  • What is the signification of "methodInvocation" code? “ methodInvocation”代码的含义是什么? (I have seen in spring-context that MethodInvocationException is thrown when BeanWrapperImpl.setPropertyValue catch an exception) (我在spring-context中已经看到,当BeanWrapperImpl.setPropertyValue捕获异常时,抛出MethodInvocationException
  • How to get more information? 如何获得更多信息? (Now, we run a patched spring-context.jar displaying the StackTrace in BeanWrapperImpl, but we cannot reproduce until now) (现在,我们运行了一个修补的spring-context.jar,在BeanWrapperImpl中显示了StackTrace,但直到现在我们都无法重现)

Informations : 信息:

  • Grails 1.3.7 => spring 3.0.5-GA Grails 1.3.7 =>弹簧3.0.5-GA
  • Mysql jdbc MySQL的JDBC
  • Tomcat 6 雄猫6

In start.sh (tomcat options) start.sh (tomcat选项)

JAVA_OPTS="-Dapp=prod -Xms1024m -Xmx1024m -XX:MaxPermSize=256m \
-Dfile.encoding=UTF-8 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC \
-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled \
-XX:+HeapDumpOnOutOfMemoryError \
-Xloggc:/path/to/gc.log"

Edit : We change and compile spring-context.jar to be able to see a StackTrace. 编辑:我们更改并编译spring-context.jar才能看到StackTrace。 and we get this one : 我们得到这个:

org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessException details (1) are:
PropertyAccessException 1:
org.springframework.beans.MethodInvocationException: Property 'pwd' threw exception; nested exception is java.lang.NullPointerException
        at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:1127)
        at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:900)
        at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:76)
        at org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:673)
        at org.springframework.validation.DataBinder.doBind(DataBinder.java:569)
        at org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:191)
[snip]
Caused by: java.lang.NullPointerException
        at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.checkCall(PojoMetaClassSite.java:54)
        at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:42)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
        at domain.UserAccount.generateTokenLogin(UserAccount.groovy:369)
        at domain.UserAccount$generateTokenLogin.callStatic(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:48)
        at domain.UserAccount$generateTokenLogin.callStatic(Unknown Source)
        at domain.UserAccount.setPwd(UserAccount.groovy:184)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:1114)

The root cause is that exists an creationDate that might be null on some weird conditions. 根本原因是存在一个creationDate ,在某些怪异的条件下它可能为null I guess the solution is not to call generateTokenLogin() in setters (and only in getters). 我猜想解决方案不是在setter中(仅在getter中)调用generateTokenLogin() )。

I cannot explain why we did not have this issue before (no recent upgrade, etc.) 我无法解释为什么以前没有这个问题(最近没有升级等)

It sounds like once this happens it isn't fixed without a restart. 听起来好像一旦发生这种情况,就必须重新启动才能解决。 I would look at the permgen size for your application. 我会看看您的应用程序的permgen大小。 If it works in every environment expect production it might be a memory issues. 如果它在每种环境下都能正常生产,则可能是内存问题。

Easy way to test is add 200megs or so to start. 测试的简单方法是添加200兆个左右开始。

just a wild guess - when you override a setter, you shouldn't set the value of that field inside this setter, because it's a kind of recursion, or at least unpredicted behavior (like this) could be expected, maybe try using raw field access operator: 只是一个疯狂的猜测-当您覆盖设置器时,不应在此设置器中设置该字段的值,因为这是一种递归操作,或者至少会发生无法预料的行为(例如这样),请尝试使用原始字段访问运算符:

public void setPwd(String pwd) {
    this.@pwd = pwd
    // We must recalculate token login
    this.tokenLogin = generateTokenLogin(email, pwd)
}

the same goes for email field/setter email字段/设置者也是如此

Is your pre-prod server exactly the same as your prod server ? 生产前的服务器与生产前的服务器完全相同吗? Which are the minors modifications you make, are you sur there is no impact ? 您对未成年人进行了哪些修改,对您没有任何影响?

It could be the war generated which contains errors, did you try a rollback on your modifications ? 可能是产生了包含错误的战争,您是否尝试对所做的修改进行回滚?

Mayby you could take your prod war and put it into your pre-prod env to reproduce the issue. 也许您可以进行产品战争并将其放入产品前环境中以重现该问题。

Is there a recent update from a plugin, grails version, or whatever in your dependencies ? 是否有插件,grails版本或您的依赖项中的任何最新更新?

Not answering your question, but peraps I can give you investigations ideas. 我没有回答您的问题,但是可以为您提供调查思路。

Snite ite

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM