2009年2月7日土曜日

[Grails]can't override the methods(like save(), find()...) defined in domain class

References
  • Grails Documentation
    http://grails.org/doc/1.0.x/
Description
  • Can't override the standard methods (like the save(), find(), delete()..) and dynamic finders defined in domain class. For example, I define the original save() method into the domain class and start the grails jetty, System ignores my original save() method and overrides the save() method.
Cause
  • According to the doWithDynamicMethods() method defined in HibernateGrailsPlugin.groovy file, the Clusure named "lazyInit" is defined, and this closure is called from the methodMissing methods.
    When calling the methodMissing methods, System tries to initialize the domain class and inject various dynamic methods into the domain class.
    When System initializes the Domain Class and calls the dynamic method at the first time,
    Groovy calls the methodMissing method if System can't find the method definition in the domain class. And then, System injects and overrides the pre-defined and duplicated methods.
    Please refer to the org.codehaus.groovy.grails.plugins.orm.hibernate.HibernateGrailsPlugin in source code.
Resolution
  • Change the method name like save()==>saveXXX(), we have to avoid to duplicate the method name(or change and override the methodMissing method definition?).

2009年2月6日金曜日

[Grails]NullPointerException sometimes occurs after upgrading the grails to the version 1.0.4

References
  • bug information
    http://jira.codehaus.org/browse/GRAILS-3493
  • Content Negotiation
    http://www.ibm.com/developerworks/java/library/j-grails09168/?S_TACT=105AGX90&S_CMP=EDU
Description
  • Following exception sometimes occurs after upgrading the grails to the version 1.0.4.
    After starting up the grails jetty server, following exception occurs when accessing the application url. This exception occurs before executing the controller's beforeInterceptor() and any action method, this error is outputted by the grails HttpHeader parser program.
    java.lang.NullPointerException: Cannot invoke method toBigDecimal() on null object
    at org.codehaus.groovy.runtime.NullObject.invokeMethod(NullObject.java:77)
    at org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:784)
    at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:758)
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN(ScriptBytecodeAdapter.java:170)
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethod0(ScriptBytecodeAdapter.java:198)
    at org.codehaus.groovy.grails.web.mime.QualityComparator.compare(DefaultAcceptHeaderParser.groovy:122)
    at java.util.Arrays.mergeSort(Arrays.java:1284)
    at java.util.Arrays.sort(Arrays.java:1223)
    at java.util.Collections.sort(Collections.java:159)
    at org.codehaus.groovy.runtime.DefaultGroovyMethods.sort(DefaultGroovyMethods.java:3509)
    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:585)
    at org.codehaus.groovy.runtime.metaclass.ReflectionMetaMethod.invoke(ReflectionMetaMethod.java:51)
    at org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod.invoke(NewInstanceMetaMethod.java:54)
    .......
Cause
  • This problem is caused by the Http Content Negotiation logic and the values of http headers. If the user accesses the url, the browser is sending the http headers and values of the client information as follows
    (This output is sample http headers)
       accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
    accept-language: en-us,en;q=0.5
    accept-encoding: gzip,deflate
    accept-charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    keep-alive: 300
    connection: keep-alive
    Grails reads these http headers before executing the controller action, and DefaultAcceptHeaderParser program parses the http headers sent from the client. When the value of "accept" or "content type" http header is including the value "application/xhtml+xml" or "application/xml", Grails parses these http headers and tries to find the "q" parameter into the "accept" or "content-type" header.
    While parsing the headers, the NullPointerException occurs because some client program doesn't have the "q" parameter value into the http header even though the accept header includes the value "application/xhtml+xml" or "application/xml".
Resolution
  • According to the http://jira.codehaus.org/browse/GRAILS-3493, this problem is fixed in grails 1.1.beta1. I tried to the grails 1.1.beta3, this problem is fixed.(but other error occurs.)