[RESOLVIDO] Vraptor + Validation (Erro vindo do Business)

7 respostas
gporpino

Galera, estou fazendo dois tipos de validação
1. Validações de tela (campo vazio, validacao de senha, etc...)
2. Validações de Business ( do banco ) - checar se já existe matrícula para o mesmo aluno, por ex.

O código abaixo funciona! eu gostaria de saber se existe alguma forma melhor de se fazer as validações sem tem que repetir...
validator.addAll(errors);	
validator.onErrorUse(Results.json()).withoutRoot().from(errors).serialize();
no código abaixo.
public void save(final Enrollment enrollment) {
		
		Enrollment enrollmentToUpdate = enrollmentBusiness.find(enrollment.getId());
		
		List<Message> errors = new Validations(){{
			that(enrollment.getStudent().getId() != null, "validation","studentNotSelected");
	    }}.getErrors(ResourceBundle.getBundle("messages"));  
	    
	    validator.addAll(errors);	
		validator.onErrorUse(Results.json()).withoutRoot().from(errors).serialize();
		
		if (enrollmentToUpdate == null){
			enrollmentToUpdate = new Enrollment();
			enrollmentToUpdate.setCreateDate(new GregorianCalendar());
		}
		enrollmentToUpdate.setUpdateDate(new GregorianCalendar());
		
		enrollmentToUpdate.setDayOfPayment(enrollment.getDayOfPayment());
		enrollmentToUpdate.setGrade(enrollment.getGrade());
		enrollmentToUpdate.setHasAddressProof(enrollment.isHasAddressProof());
		enrollmentToUpdate.setHasBirthCertificate(enrollment.isHasBirthCertificate());
		enrollmentToUpdate.setHasCPFXerox(enrollment.isHasCPFXerox());
		enrollmentToUpdate.setHasFacePhotos(enrollment.isHasFacePhotos());
		enrollmentToUpdate.setHasHealthPlanCard(enrollment.isHasHealthPlanCard());
		enrollmentToUpdate.setHasLastYearSchoolDischarge(enrollment.isHasLastYearSchoolDischarge());
		enrollmentToUpdate.setHasRegistrationNumberXerox(enrollment.isHasRegistrationNumberXerox());
		enrollmentToUpdate.setHasVaccinationCard(enrollment.isHasVaccinationCard());
		enrollmentToUpdate.setMonthOfEnrollment(enrollment.getMonthOfEnrollment());
		enrollmentToUpdate.setShift(enrollment.getShift());
		
		enrollmentToUpdate.setStudent(enrollment.getStudent());
				
		try {
			enrollmentBusiness.saveOrUpdate(enrollmentToUpdate);
		} catch (final InvalidAttributesException e) {
			
			errors.add(new I18nMessage("validation",e.getMessage()));
		}finally{
			validator.addAll(errors);	
			validator.onErrorUse(Results.json()).withoutRoot().from(errors).serialize();
		}
		
		ajaxRedirect("enrollment/list"); 
}

7 Respostas

Lucas_Cavalcanti

ao invés de fazer isso, muda para adicionar os erros diretamente no validator, e faça:

validator.onErrorSendBadRequest();

assim o status code da resposta vai ser 400 (assim vc não precisa fazer if lá no javascript) e os erros serão serializados em json (se a requisição veio pedindo json)

gporpino

Ok,

essa sua sugestão eu já havia entendido mais ainda não tinha aplicado.

mas a questão é que tem erros que são de validação e tem erro que vem no

ai queria saber se tem alguma forma mais limpa de chamar o validador.
para não ter que repetir o mesmo código em cima e em baixo no catch.

Lucas muito obrigado, por toda a força que vc dá ao GUJ.
Vejo vc investindo muito tempo aqui. e vejo várias respostas pertinentes.
Valeu brother!!

Lucas_Cavalcanti

adiciona todos os erros no validator. algo assim:

validator.checking(new Validations() {{
   //validações aqui
}});
...
validator.add(<mensagem de erro>);
...
validator.onErrorSendBadRequest();
...

assim, e usando o snapshot que eu te mandei, ele vai fazer do jeito que vc precisa

gporpino

Eu já fiz isso.

meu código atual.
public void save(final Enrollment enrollment) {
		
		Enrollment enrollmentToUpdate = enrollmentBusiness.find(enrollment.getId());
		
		validator.checking(new Validations(){{
			that(enrollment.getStudent().getId() != null, "validation","enrollment.studentNotSelected");
	    }});  
	    
		validator.onErrorSendBadRequest();
		...
				
		try {
			enrollmentBusiness.saveOrUpdate(enrollmentToUpdate);
		} catch (final InvalidAttributesException e) {
			validator.add(new I18nMessage("validation", e.getMessage()));
			
			validator.onErrorSendBadRequest();
		}
		
		
		result.use(Results.json()).withoutRoot().from("Matrícula salva com sucesso!").serialize();
	}

O detalhe é que tenho que repetir o

validator.onErrorSendBadRequest();

Se colocar esse trecho apenas no catch. ele vai salvar o objeto mesmo que tenho erro de validação em cima. sacou?
O que está me incomodando é eu ter que repetir esse código acima.
Tem alguma forma melhor?

Lucas_Cavalcanti

então, não tem muito o que fazer, pq qdo vc chama o validator.onErrorXXXX ele já verifica se tem erros e solta uma exception se tiver… vc precisa verificar se tem erros em dois momentos, então tem que chamar essa linha duas vezes mesmo, infelizmente…

na verdade na verdade o jeito que eu faria isso era ignorando esse try…catch no saveOrUpdate. Teoricamente vc deveria evitar esse erro dos InvalidAttributes com as validações anteriores, não é mesmo?

o que vc pode fazer também é usar o BeanValidations para fazer as validações no modelo, e então chamar

validator.validate(objeto);

antes de invocar o onErrorXXX

gporpino

Eu checo no bussiness se já existe matrícula (enrrolment) para o aluno.
Acredito que se colocar no controller vou estar quebrando a arquitetura. não acha?

Pensei em colocar um método para validar o objeto no Business. ai eu chamaria no that.

Esse é o method do business:

public void saveOrUpdate(Enrollment t) throws InvalidAttributesException {
		try{
			session.beginTransaction();
			
			Enrollment enroll = findByStudentId(t.getStudent().getId());
			if (t.getId() == null && enroll != null){
				throw new InvalidAttributesException("Já existe matrícula para este usuário");
			}
			
			Student student = studentBusiness.find(t.getStudent().getId());
			t.setStudent(student);
			
			session.saveOrUpdate(t);
			session.getTransaction().commit();
		}catch(InvalidAttributesException e){
			session.getTransaction().rollback();
			throw e;
		}
	}
Lucas_Cavalcanti

não sei se estaria quebrando a arquitetura… vc pode fazer algo do tipo, no controller:

if (enrollmentBusiness.existsEnrollmentFor(student)) {
   validator.add(new I18nMessage("student", "enrollment.exists"));
}
Criado 27 de setembro de 2011
Ultima resposta 27 de set. de 2011
Respostas 7
Participantes 2