Capturar Exceção org.hibernate.StaleObjectStateException

Olá amigos!
Estou utilizando a anotação @Version do pacote javax.persistence para trabalhar a concorrência em minha aplicação Java EE 6. Porém quando utilizo try-catch para capturar a exceção e apenas exibir uma mensagem mais bem trabalhada para o usuário, a mesma continua explodindo na minha página web.

Abaixo um exemplo simples de como estou capturando a exceção:

public void salvar() {
		FacesContext contexto = FacesContext.getCurrentInstance();
		
		try {
			aula.setStatusAula(StatusAula.AGENDADA);
			this.aula = this.aulaDAO.salvar(aula);
			this.listarAulas();
			
			contexto.addMessage(null, new FacesMessage("Sucesso!", "Nova Aula criada com sequencial " + aula.getSequencial()));
		} catch (org.hibernate.StaleObjectStateException sose) {
			contexto.addMessage(null, new FacesMessage("Erro!", "Este registro está foi alterado por outro usuário. Repita a Operação!"));
			aula = aulaDAO.buscarPorId(aula.getId());
		}
	}

A causa principal é mostrada assim:
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)

A anotação na classe modelo é simples:

@Version
	public int getVersion() {
		return version;
	}

OBS 01: a aplicação é do Tipo Enterprise Application, e tem dois módulos dependentes: um WAR e um EAR. A classe modelo está no EAR e o ManagedBean que contém o método salvar exibido logo acima está no WAR.

OBS 02: Quando eu utilizo uma exceção mais genérica, como javax.ejb.EJBException, o tratamento com o try-catch funciona perfeitamente. Vejam a diferença na linha 07 deste exemplo:

try {
	aula.setStatusAula(StatusAula.AGENDADA);
	this.aula = this.aulaDAO.salvar(aula);
	this.listarAulas();
			
	contexto.addMessage(null, new FacesMessage("Sucesso!", "Nova Aula criada com sequencial " + aula.getSequencial()));
} catch (javax.ejb.EJBException ee) {
	contexto.addMessage(null, new FacesMessage("Erro!", "Registro alterado por outro usuário!"));  // Não posso afirmar que essa foi a causa!
	aula = aulaDAO.buscarPorId(aula.getId());  // Por conta do tratamento genérico da exceção, isto pode gerar um NullPointerException!
}

Vale lembrar que aqui utilizo o servidor Glassfish 3.1 como servidor de aplicações, e as transações são controladas pelo servidor com recurso JDBC, além de utilizar o hibernate 3.6 como provider.

Alguém tem alguma solução?

Bom pessoal, segundo Mike Keith e Merrick Schincariol, autores do livro Pro JPA 2 - Mastering the Java Persistence API, o problema que está ocorrendo é o seguinte: quando trabalhamos com servidores de aplicações as exceções são geradas pelos mesmos, e são tratadas como exceções de sistema, e não como exceções de aplicação.
Dessa forma, qualquer exceção levantada pelo servidor de aplicações vai ser reconhecida como uma exceção mais genérica de RunTimeException, não podendo ser facilmente capturada e tratada apenas como a exceção mais específica como, por exemplo, um StaleObjectStateException(do pacote org.hibernate) ou uma OptimisticLockException (do pacote javax.persistence).

Trocando em miúdos:
Como a transação é gerenciada pelo Application Server(Glassfish, no meu caso), ele mesmo se encarrega de lançar uma exceção específica que, aos olhos da aplicação, chega como um erro em tempo de execução e é tratada como uma exceção mais genérica (EJBException). Com isso não há como tratar o erro e determinar a real causa do problema, já que EJBException é genérica e pode estar relacionada a várias causas.

O autores propõem uma forma alternativa de capturar o erro e tratá-lo, criando uma exceção personalizada, anotando-a com @ApplicationException (para que o controle do lançamento da exceção seja gerenciado pela aplicação e direcionado ao cliente) e relacionando-a com a exceção lançada pelo servidor de aplicações. Mas não obtive sucesso. Esta explicação encontra-se no capítulo 11 - Advanced Topics, na seção entitulada Recovering from Optimistic Failures, na página 355.
Os mesmos ainda propõem que a melhor e mais simples alternativa seria capturar apenas a exceção mais genérica e informar ao usuário que algo deu errado durante a operação e solicitar que seja realizada nova tentativa.

Bem, após esta explanação eu gostaria de saber se os caros colegas poderiam opinar sobre o assunto.

Desde já agradeço a participação de todos.

Passei por um problema muito parecido com esse, em um ambiente EJB queria validar os paramêtros de métodos. Para isso lançava um IllegalArgumentException (filha de RuntimeException), porém o erro também estourava, mesmo com try catch. A solução foi criar uma Exception (que não herdasse de RuntimeException) e lançar ela segundo minhas regras, isso resolveu o problema.
No meu caso não anotei minha exception com @ApplicationException e ela era filha de Exception.
Não sei se esse é o teu caso, mas se for, seria tratar isso no método de salvar do dao:

try{
  //lógica de salvar
 } catch (org.hibernate.StaleObjectStateException sose) {  
        throw new ExcecaoPersonalizada("O objeto já está em sendo usado em outro processo");
}