Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

Dúvida onde colocar Validações um pouco mais complexas na arquitetura da aplicação

Olá a todos. além de verificar se os campos estão preenchidos corretamente, é muito comum também termos validações relacionadas com a regra de negócio, e muitas vezes precisamos inclusive de acesso ao banco de dados. Podemos citar por exemplo a verificação do estoque antes de efetuar uma venda, ou saber se certo item já foi comprado, vendido,reservado, etc...

Onde devemos fazer este tipo de validação? No próprio Controller, em um validador como na aula 06 ou criar uma camada mais específica?

ultimamente tenho optado pela opção 3, por exemplo se na nossa validação fosse exigido que o nome do produto deve ser único:

@Service
public class ProdutoService{
@AutoWired
private ProdutoDao dao;

public void salvar(Produto produto){

Produto other = findProduto(produto.getNome());

if(other != null)
{
throw new NegocioException("produto com esse nome já existe");
}
dao.salvar(produto);
}
}

Aqui no controller é um dos principais pontos da dúvida se escolhi a opção correta, não sei se é muito indicado, mas verifico de houve o erro com try catch, na minha opinião fica um pouco feio

public class ProdutoController{

@RequestMapping(method=RequestMethod.POST)
public ModelAndView gravar(@Valid Produto produto, BindingResult result,  RedirectAttributes redirectAttributes){
    if(result.hasErrors()){
        return form();
    }
try{
    produtoService.gravar(produto);
    redirectAttributes.addFlashAttribute("message","Produto cadastrado com sucesso");
    return new ModelAndView("redirect:produtos");
}catch(NegocioException e){
 redirectAttributes.addFlashAttribute("message",e.getMessage());
return form();
}
}
}

e então, qual caminho seguir?

5 respostas

Fala aí, Ricardo! Tudo certinho, cara? =)

Eu não sei se tem um jeito certo de se fazer essa validação. Seguindo o MVC, a única coisa que podemos dizer é que o Controller não deveria ser o responsável por toda a lógica de verificação, afinal, ele só deve controlar a requisição... =)

Uma das coisas que costumo ver em alguns projetos é justamente isso que você fez, ou seja, uma classe Service, que possui o DAO e faz a validação... Ou seja, não sei se tem uma forma correta, mas da maneira como você optou por fazer as coisas é um tanto quanto comum, sacou? =)

Espero ter ajudado, mas qualquer coisa posta aí para podermos ajudá-lo! =D

Abraço e bons estudos,

Fábio

Olá Fábio tudo bem!

Realmente acho que não existe uma forma "correta". Nessa forma que adotei o que me incomoda um pouco é ter que tratar essa exception com um try catch feioso lá no controler, até vi que existe no Spring um exceptionHandler que pode ajudar nessa tarefa, mas ainda assim fica um pouco feio quando a lógica pode lançar muitas exceptions, como por exemplo assinatura digital que dispara um monte de checked exceptions

Ricado,

Entendo... Mas, infelizmente, acho que não há muito o que fazer, sacou? =|

Espero ter ajudado,

Fábio

solução!

Já resolvi isso de outra forma. Criei um Bean Validation e o colocava em cima do atributo. EX:

public class CarrinhoDeComprasDTO{
    @ProdutoNoEstoque
    private List<Produto> produtos; 
}

O meu controller recebia a requisição parecido com isso

    @RequestMapping(method=RequestMethod.POST)
    @Transactional
    public ModelAndView registrarPedido(@Valid CarrinhoDeComprasDTO carrinhoDeCompras, BindingResult bindingResult){

      if(bindingResult.hasErrors()){
        return ...;
    }
}

Dessa forma ele chega no controller já validado e vc tem como saber se teve erros. Toda a lógica de validação fica no bean validation e pode ser reaproveitado em outros locais.

show Felipe! implementei algo parecido já faz algum tempo com cdi + jsf

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software