Wednesday, April 13, 2011

How to write the Hibernate Transaction code on READ COMMITTED isolation level ?

I guess writing transaction codes with hibernate on READ COMMITTED isolation level is a well-tried combination. However why there isn't a good document for tips? Since the READ COMMITTED means Transaction is not atomic, we must care how transactions affect each other.

For example, if several concurrent transactions touch the same row and increment or decrement a value of a column, the value becomes inconsistent if I use save.
@Transactional
public void inc(Long id){
    E e = eDao.get(id);
    int val = e.getCount();
    e.setCount(val+1);
    eDao.save(e);
}

Since on the following sequence:

ThreadA: val = e.getCount();
ThreadB: val = e.getCount();
ThreadA: e.setCount(val+1);
ThreadB: e.setCount(val+1);
ThreadA: eDao.save(e);
ThreadB: eDao.save(e);

The "count" column is just +1 not +2.

I think there are two solutions, though I only tried the first.

First, use an "update" hcl statement. I add following methods at eDao class, and replace above codes to eDao.incCount(id);.
public void incCount(Long id) {
    getSession().createQuery("update E e set e.count = e.count + 1 where e.id=:id")
        .setParameter("id",id)
        .executeUpdate();
}
Since the update statement is an atomic operation (I guess), the above problem does not happen.

Second, replace eDao.save(e) to eDao.update(e).
@Transactional
public void inc(Long id){
    E e = eDao.get(id);
    int val = e.getCount();
    e.setCount(val+1);
    eDao.update(e); // not save!
}
It will cause "StaleStateException" when above sequence happens. Then retry transaction when the exception happens. For example,
int retry=0;
while(retry < MAX_RETRY){
    try {
        eAccessServices.inc(id);
        break;
    } catch (StaleStateException e) {
        retry++;
    }
}
The above code should be written where eAccessServices.inc(id) is called.

I guess there should be better way to solve the issue. If you know it, please let me know.

Updated (04/26/2011):
This is not related to READ COMMITTED isolation level.

Thanks.

Tuesday, April 5, 2011

Wicket: wicket-ajax Channel busy postponing

I got above error when using Wicket + wiQuery + wicket-push(cometd). I struggled for a day and finally, solved it.

In my case, the issue appeared on Firefox, but not happened on Chrome. Also When the page was first loaded, it worked fine. However, after reload the page, it happened. Any wicket's ajax request was blocked. And in the Wicket-Ajax-Debug window, "INFO: Channel busy postponing" message appeared.

The problem is caused by, **I guess**, wicket-ajax.js + jquery. When some jquery javascript start earlier than something, it will harm wicket-ajax.js. In my case, by cometd javascript, (see this) $.cometd.configure() and $.cometd.handshake() starts without waiting loading whole contents in the page. So I fix as follows.

$(window).load(function(){
    $.cometd.configure();
    $.cometd.handshake();
});

This will delay the two functions to start. And problem was gone.

I'm not sure this is a right way to do. Please leave comment if you find the better solution for the same problem.

How to use FlashPlayer 10.2 and 10.3 feature with Flash CS5

I want to use the new features introduced by FlashPlayer 10.2 and 10.3. More specifically, stage video and acoustic echo cancellation. Since adobe does not offer the update for Flash CS5, I have to find the other way to do it.

What I did is follow the instruction specified in the link. In this case, I set up FlashPlayer 10.3.

However there are two missing things:
  • FlashPlayer10_3.xml: In the player node, change the version from "10" to "12". This works as "-swf-version=12" on Flex Compiler.
  • Publish Settings: In the flash tab, change the "Hardware Acceleration" from "None" to "Level 2 - GPU".

The first enables to use new features, and the second enables to use stage video.