3

I have developed a grails/groovy application for a legacy database which has user maintenance page to (add,edit) user information. The page is using editinplace and ajax to update the information.

The program has been tested on local with no problem. However, on any remote server (alpha,beta,prod) when I "update" any property of user, it will save it in the database but when I refresh the page the contents "sometimes" go back the previous values. If I keep pressing refresh (F5) it will switch between old and new values without any particular trend. (wasn't able to reproduce in local)

I thought it might be a cache issue so I set cache false on user domain

class User {
static hasMany = [notes: Note]
static mapping = {
    table 'MICR_USERS'  
    cache false
    version false        
    id generator:'sequence', column:'SEQ_ID', params:[sequence:'MICR_USR']
    lineOfBusiness column:'LOB_APP_CODE'
    authorityProfile column:'AUTH_PRIVILEGE_LEVEL', lazy:false
}
...

Another thing I thought might cause the issue is the createCriteria in list action which I set the cache false there too

    def list = {
    def f = getUserList(session.oldSearchUserTextBox?:null)
    return [list:f,oldSearchKeyword:session.oldSearchUserTextBox]
}

    private getUserList(String searchFilter){
            ....
    def c = User.createCriteria()
    def results
    if (searchFilter) {
        results = c.list (max: params.max, offset: params.offset) {
            or {
                ilike ("oraAcct", "%"+ searchFilter+"%" )
                ilike ("lastName", "%"+ searchFilter+"%" )
                ilike ("firstName", "%"+ searchFilter+"%" )
            }
            order("oraAcct", "asc")
            cache false
        }
    }
    else {
        results = c.list (max: params.max, offset: params.offset) {
            cache false
            order("oraAcct", "asc")
        }
    }
    [userInstanceList : results,userInstanceTotal :results.getTotalCount()]
}

This is my save method

    private JSON saveValidateObj(def myUser,def oldValue,def fieldname,def returnFieldName){
    try {
        def value =  myUser."$fieldname"
        if( myUser.validate() && myUser.save(flush:true) ) {
            if (returnFieldName) value = value."$returnFieldName"
            flashMessage = getMess('user.information.update.success',[
                myUser.oraAcct,
                oldValue,
                value
            ])

            def json = ['value':value,'id':params.id,'updatedField': fieldname,'errorList':null,'errMessage':null,'okMessage':flashMessage]
            def j = json as JSON
            return j
        }

.....

It seems that hibernated keeps different version of the data and by refreshing the page randomly one of those versions will be displayed. However, the latest values are dominant and appear more frequently but still seeing the old values appearing on the screen is devastating.

These are the steps I did and didn't help 1- turned off the caching (checked the hibernate statistics to make sure its off) cache.use_second_level_cache=false cache.use_query_cache=false

2- tried it in different browsers

3- cleaned the browser cache and deleted cookies

I am also suspicious on websphere which is my production server and my local is apache but really dont know why its reacting this way

Grails/hibernate 1.1

I still have this issue and could not think of anything else. I appreciate, if anyone can provide me any hint

New Findings

If I use select u.id, u.sysAcct, u.firstName, u.lastName, u.mailAddress, u.phoneExt from User u... the problem will be solved. but if I use select u from User u,... the problem will happen again. For some reason if I return the User object this issue happens. The getUserListHSQLStatic and getUserListHSQL are basically same except one is returning the object and one is returning fields. the values from the static one will never change by pressing F5 but the object (User) one will change.

    private getUserListHSQLStatic(params){
    def filter = params.filter
    def newlist
    def count
    def query = """
        select      
        u.id, u.sysAcct, u.firstName, u.lastName, u.mailAddress, u.phoneExt
        ,lob.name,auth.name
        from User u, AuthorityProfile auth, LineOfBusiness lob
        where  u.authorityProfile = auth.id
        and  u.lineOfBusiness = lob.id
        and u.sysAcct not like '%DUMMY%'
        """
    if (filter){
        query +="""
         and (u.sysAcct  like :filter or
             u.sysAcct  like :lfilter or
             u.firstName like :filter or
             u.firstName like :lfilter or
             u.lastName  like :filter or
             u.lastName  like :lfilter
        ) order by u.sysAcct asc
        """
        def filterMap =  [filter:"%${filter.toUpperCase()}%",lfilter:"%${filter.toLowerCase()}%"]
        newlist = User.executeQuery(query,filterMap,
                [ max:params?.max?.toInteger()?:10, offset:params?.offset?.toInteger()?:0]
                )
        count = User.executeQuery(query,filterMap).size()
    }
    else {
        query += " order by u.sysAcct asc "
        newlist = User.executeQuery(query,[max:params?.max?.toInteger()?:10, offset:params?.offset?.toInteger()?:0])
        count = User.executeQuery(query).size()
    }
    [userInstanceList:newlist,userInstanceTotal:count]
}
private getUserListHSQL(params){
    def mysession = sessionFactory.currentSession
    if (params.reset=="true"){
        println "clear session"
        mysession.clear()
    }

    def filter = params.filter
    def newlist
    def count
    def query = """
        select u
        from User u, AuthorityProfile auth, LineOfBusiness lob
        where  u.authorityProfile = auth.id
        and  u.lineOfBusiness = lob.id
        and u.sysAcct not like '%DUMMY%'
        """
    if (filter){
        query +="""
         and (u.sysAcct  like :filter or
             u.sysAcct  like :lfilter or
             u.firstName like :filter or
             u.firstName like :lfilter or
             u.lastName  like :filter or
             u.lastName  like :lfilter
        ) order by u.sysAcct asc
        """
        def filterMap =  [filter:"%${filter.toUpperCase()}%",lfilter:"%${filter.toLowerCase()}%"]
        newlist = User.executeQuery(query,filterMap,
                [ max:params?.max?.toInteger()?:10, offset:params?.offset?.toInteger()?:0]
                )
        count = User.executeQuery(query,filterMap).size()
    }
    else {
        query += " order by u.sysAcct asc "
        newlist = User.executeQuery(query,[max:params?.max?.toInteger()?:10, offset:params?.offset?.toInteger()?:0])
        count = User.executeQuery(query).size()
    }
    [userInstanceList:newlist,userInstanceTotal:count]
}
Alidad
  • 5,463
  • 1
  • 24
  • 47
  • Aren't you creating something twice and then getting the first value from the result set? The order would than be arbitrary, especially if this is a production database, and not some HSQLDB toy database. – julx Mar 26 '11 at 01:31
  • @julkiewicz, Im not sure im following what you mean by saying "creating something twice and then getting the first value". I simply update a user object with the new values and save it to database. On the list action, i simply get the list of all or filter it if the filter exist. This code is right now in production with this bug. it is using oracle database. – Alidad Mar 26 '11 at 13:49
  • Can you confirm you definitely don't have 2 users with same name in your DB (which I think is what @julkiewicz is asking). I doubt this is the case, you've probably got name as unique in DB... – Chris Mar 29 '11 at 09:47
  • @Chris, The oraAcct is unique userid that exist in the system. However, the users are differentiated with seq_id (id) and there is a unique constrains on that column. I am kind of leaning toward the idea concerning the hibernate caching. However, turning cache flags on/off won’t make any good (I might not do it correctly). The code perfectly works in the development environment (local) though, which makes it harder to debug. – Alidad Mar 29 '11 at 14:22

2 Answers2

2

Are there multiple servers in the other environments? Also, when you refresh, using a tool like Firebug can you check the response code isn't 304? Finally, when you say you cleared the browser cache, are you getting the old value after clearing the cache?

Since you're using Edit in Place, the page you're retrieving can often times be cached by the browser (if you're using Chrome, I've seen that it does this almost too aggressively). I'd want to make sure that the server is passing back old data on the wire.

Phuong LeCong
  • 1,834
  • 16
  • 19
  • I would suggest installing this plugin to make sure that your responses aren't being cached also http://www.grails.org/plugin/cache-headers – Phuong LeCong Apr 08 '11 at 16:44
  • thank you for your response. I looked at those items you mentioend, the status code is 200. I used IE debuger and cleared the cache and checked the reading from server option and still get the same problem. On the plugin you mentioned that plugin is for grails 1.2.0 > * and we are using 1.1. – Alidad Apr 13 '11 at 18:22
  • I added a counter variable to the session and increase it as I hit the controller actions. I looks like at all time it is hitting the controllers. – Alidad Apr 13 '11 at 18:26
0

At this time the problem is still unknow, however, I was able to fix the issue by using the

def query = """ select  u.id, u.sysAcct, u.firstName, u.lastName, u.mailAddress, ...

instead of returning the whole object.

def query = """ select u from User u, AuthorityProfile auth, LineOfBusiness lob   ...

This change has fixed my problem and refreshing the page wont change the values anymore.

Alidad
  • 5,463
  • 1
  • 24
  • 47