两周以来,出现了一个疯狂的问题!它只出现在生产中(而不是在开发、集成、预生产模式中)和下班后......
症状:一旦“某事”发生,用户就不能再注册了。经过几天和几天的调查,我不知道如何重现这个问题。目前,我们有重新启动 tomcat 实例的丑陋解决方法,但这非常丑陋。
有关信息,两次交付之间的差异不会涉及注册过程。
这里我认为是相关的:
领域 :
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;
}
}
控制器 :
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()
}
输出日志:
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]
问题 :
- 这个输出可能是如何出现的?我们看到了这个输出
pwd
或者email
字段,从来没有看到其他人。 - “methodInvocation”代码的含义是什么?(我在捕捉异常
MethodInvocationException
时抛出的spring-context中看到过BeanWrapperImpl.setPropertyValue
) - 如何获取更多信息?(现在,我们运行一个修补过的 spring-context.jar,在 BeanWrapperImpl 中显示 StackTrace,但直到现在我们才能重现)
资料:
- Grails 1.3.7 => 春季 3.0.5-GA
- mysql jdbc
- 雄猫 6
在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"
编辑:我们改变和编译spring-context.jar
能够看到 StackTrace。我们得到了这个:
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)
根本原因是存在一个creationDate
可能null
在一些奇怪的条件下。我想解决方案不是调用generateTokenLogin()
setter(而且只调用 getter)。
我无法解释为什么我们之前没有这个问题(最近没有升级等)