users@glassfish.java.net

Re: how to implement a "global" application counter?

From: <glassfish_at_javadesktop.org>
Date: Fri, 04 Jan 2008 15:58:39 PST

Is GeneratedValue cluster aware?

I guess it depends on the definition of the sequence, and requirements of the counter.

He also mentioned that he wanted to be able to reset the counter (which would not be easy to do with a GeneratedValue).

Frankly, I don't know what is wrong with this:

[code]
@Stateless
public class CounterSessionBean
    implements CounterSessionRemote, CounterSessionLocal {
    @Resource(name = "jdbc/counterds")
    private DataSource ds;

    public CounterSessionBean() {
    }
    
    public int getValue() {
        String sql = "update counter set value = value + 1";
        Connection con = ds.getConnection();
        PreparedStatement ps = con.prepareStatement("update counter set value = value + 1");
        ps.execute();
        ps.close();
        ps = con.prepareStatement("select value from counter");
        ResultSet rs = ps.executeQuery();
        int result = 0;
        if (rs.next()) {
            result = rs.getInt(1);
        }
        rs.close();
        ps.close();
        con.close();
        return result;
    }
}
[/code]

Note, the distinct lack of exception catching and throwing...that's left as an exercise for the reader.

Anyway, with the proper isolation level (though most any should work), this will work on every ACID SQL DB that I know.

It's bone simple and relies on the transaction properties of the database.

The "counter" table has a single column (value), and a single row.

The update will increment and lock the row, the select will fetch the value back, the implicit commit of the EJB will make all that permanent and unlock the row. Since the update itself locks and is atomic, everyone will block until this entire transaction commits.

Obviously, autoCommit is false for the connection (it is by default). This is atomic and database portable.

It is resetable (simply update the counter to whatever value you want).

It will support the entire cluster, HOWEVER, it IS synchronous (it has to be). So, if you're generating zillions of these, you will have a bottleneck. (Which is why many systems cache some local number, but then you can't easily reset the value as you need a cluster wide caching strategy to handle the reset, also there may be a requirement for sequencing, who knows). But you will ALWAYS have this problem, as it pretty much HAS to be synchronous, again, depending on your needs.

It is trivial to implement.

The biggest expense here is the network traffic, and the synchronous nature of the process.
[Message sent by forum member 'whartung' (whartung)]

http://forums.java.net/jive/thread.jspa?messageID=252314