Validação após flush - Bean Validation + VRaptor + JPA

O padrão de uso do Validator do VRaptor seria assim:

validator.validate(user);
validator.onErrorForwardTo(this).signup();
service.insert(user);

Acontece que alguns atributos da minha classe são gerados automaticamente, como por exemplo signupDate e a senha (hash gerado com tamanho fixo). Minha classe User está assim:

@Entity
public class User implements Serializable {

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue
	private Long id;

	@Column(unique = true)
	@NotNull(message = "{LOGIN_CANNOT_BE_EMPTY}")
	@Size(min = 4, max = 50)
	@Pattern(regexp = "^(?=.{4,50}$)(?![_.])(?!.*[_.]{2})[a-zA-Z0-9._]+(?<![_.])$", message = "Nome de usuário inválido")
	private String loginId;

	@NotNull(message = "{NAME_CANNOT_BE_EMPTY}")
	@Size(min = 4, max = 150)
	private String name;

	/**
	 * User's password encrypted (SHA-256)
	 */
	@NotNull(message = "{PASSWORD_CANNOT_BE_EMPTY}")
	@Size(min = 71, max = 71)
	private String password;

	@NotNull
	@Temporal(TemporalType.TIMESTAMP)
	private Calendar signupDate;

Esses atributos automáticos são carregados dentro do EJB UserService.

	@Override
	@Transactional(TxType.REQUIRED)
	public void insert(User entity) {
		entity.setSignupDate(Calendar.getInstance());
		entity.encryptPassword();
		entityManager.persist(entity);
	}

Quando eu usava o plugin vraptor-jpa cada requisição gerava uma transação com o banco de dados. Migrei do Tomcat para o Wildfly e estou usando JTA. Removi o plugin vraptor-jpa e estou controlando as transações via anotação @Transactional.

Eu fazia assim antes:

@Transactional
try {
    service.insert(user);
    //Validação do bean após carregamento dos atributos pelo serviço
    validator.validate(user);
    validator.onErrorForwardTo(this).signup();
    service.flush();
}

No entanto isso ficou estranho. O controller não deveria depender da camada serviço para fazer uma validação. Se eu remover a anotação @Transactional do método do controller e remover o service.flush(), recebo o seguinte erro:

20:14:02,363 WARN  [com.arjuna.ats.arjuna] (default task-32) ARJUNA012125: TwoPhaseCoordinator.beforeCompletion - failed for SynchronizationImple< 0:ffffc0a80166:12a2803d:5692cfb1:164, org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization@340e8f93 >: javax.persistence.PersistenceException: error during managed flush
[...]
Caused by: javax.validation.ConstraintViolationException: Validation failed for classes [aaqd.model.User] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
	ConstraintViolationImpl{interpolatedMessage='{PASSWORD_CANNOT_BE_EMPTY}', propertyPath=password, rootBeanClass=class aaqd.model.User, messageTemplate='{PASSWORD_CANNOT_BE_EMPTY}'}
	ConstraintViolationImpl{interpolatedMessage='{NAME_CANNOT_BE_EMPTY}', propertyPath=name, rootBeanClass=class aaqd.model.User, messageTemplate='{NAME_CANNOT_BE_EMPTY}'}
	ConstraintViolationImpl{interpolatedMessage='{LOGIN_CANNOT_BE_EMPTY}', propertyPath=loginId, rootBeanClass=class aaqd.model.User, messageTemplate='{LOGIN_CANNOT_BE_EMPTY}'}
]

Parece que o VRaptor não consegue capturar automaticamente as validações dessa exceção e jogar no Validator. Achei que isso era um problema, mas pensando melhor está certo. O Validator, do Controller, não deveria ser tão dependente da camada de serviço (que poderia estar rodando em um servidor EJB separado, por exemplo).

Eu testei isso e funcionou:

		try {
			if (service.getByLoginId(user.getLoginId()) != null) {
				throw new UniqueConstraintViolatedException("loginId", "USER_ALREADY_EXISTS");
			}
			service.insert(user);
		} catch (UniqueConstraintViolatedException e) {
			validator.add(e.getValidationMessage());
		} catch (Exception e) {
			validator.validate(user);
			if (!validator.hasErrors()) {
				validator.add(
						new SimpleMessage("bar", "Não foi possível realizar o cadastro (" + e.getMessage() + ")."));
				e.printStackTrace();
			}
		}

No entanto, não sei se é a melhor alternativa. Alguém tem sugestões?
A anotação @NotNull para signupDate está correta? Penso que sim, tanto que na inserção dos dados é feita a validação. Um parâmetro nessa anotação resolveria o problema: @NotNull(validateOnView=“false”).

O que vocês acham? Eu estou muito errado?