J2EE clustering is done on more levels.
Web tier : Session replication (for example in tomcat) and load balancing (for example apache with mod_jk or director) can be used to gain performance but also have fail over.
Ejb tier : Multiple ejb containers could be used with a shared or replicated jndi tree. This offers load balancing and fail over. But some problems are for example : reliable JNDI replication.
Storage tier : The persistent storage (e.g database) must also be replicated in order not to be the single point of failure and to increase the performance. This could be done by commercial products (Oracle RA cluster, IBM, ...) but an open way could also be C-JDBC.
Some good links which explains this are :http://www.javaworld.com/jw-02-2001/jw-0223-extremescale.htmlhttp://www.javaworld.com/javaworld/jw-08-2001/jw-0803-extremescale2.html