Como usar minha interface Service fora de uma classe RestController(SpringBoot)

5 respostas
back-endjavaspring
Z

Olá pessoal,
Estou desenvolvendo um micro-serviço com SpringBoot e estou tentando validar o email que a pessoa manda verificando se já existe em minha base dados.
Porque estou fazendo isso?
A ideia é criar uma validação antes que chegue na camada de persistência, evitando exceptions do banco e retornando uma mensagem amigavel, o meu maior problema é como eu consigo usar a interface PessoaService que acessa a camada de persistência fora da classe PessoaController que tem a anotação @RestController

public interface PessoaService {

public Pessoa save(Pessoa pessoa);

public Pessoa update(Pessoa pessoa);

public Pessoa findById(Long id);

public void delete(Long id);

public List findAll();

}

Implementação da Interface

@Service
public class PessoaServiceBean implements PessoaService {

@Autowired
private PessoaRepository dao;

@Override
public Pessoa save(Pessoa pessoa){
// TODO Auto-generated method stub

Pessoa p1 = dao.save(pessoa);
  	return p1;

}

Minha classe Controller

@RestController
public class PessoaController {

@Autowired
private PessoaService dao;

@SuppressWarnings(rawtypes)

@RequestMapping(

value="/api/pessoas",

method=RequestMethod.POST,

consumes = MediaType.APPLICATION_JSON_VALUE,

produces = MediaType.APPLICATION_JSON_VALUE)

public ResponseEntity salvar(@RequestBody Pessoa pessoa) throws Exception{
ExceptionThrower e = new ExceptionThrower();
  e.trhowMandatorio(pessoa);
  
  Pessoa objPessoa = pessoa;			
  dao.save(pessoa);
  return new ResponseEntity<Pessoa>(objPessoa, HttpStatus.CREATED);

}

Minha Classe que trata os erros, a única forma que achei foi chamando minha API para poder fazer esse teste mas ai não fica legal

public class ExceptionThrower {

@Autowired
RestTemplate rs = new RestTemplate();

public void trhowMandatorio(Pessoa pessoa) throws CustomException {
CustomException e = new CustomException();

if (validateEmail(pessoa.getEmail()) == true) {
  	e.setCode(HttpStatus.CONFLICT);
  	e.setMessage("Email ja cadastrado");
  	throw e;
  } else {
  }

}

private boolean validateEmail(String email) {

boolean teste = false;

String obj = rs.getForObject(<a href="http://localhost:8080/servicopessoa/api/pessoas">http://localhost:8080/servicopessoa/api/pessoas</a>”, String.class);

JSONArray l = new JSONArray(obj);

if (l.length() > 0) {

for (int i = 0; i < l.length();i++) {
JSONObject json = l.getJSONObject(i);
  		if (email.equals(json.get("email"))){
  			teste = true;
  			return teste;
  		}
  	}
  } else {
  	return teste;
  }
  return teste;

}

quem puder dar essa força agradeço desde já!!!

5 Respostas

E

Olá @zefinir vejo que você é novo em Spring Framework :grinning:.

Pelo que análisei do seu código tem muita coisa a ser ajustada, na parte de micro-service recomendo que você use Spring Cloud Netflix que já é possui toda a arquitetura de micro-service pronta para usar, só basta configurar o seu comportamento e além do mais trata load balance, roteamento entre os micro-services, tolerância a falha e entre outras coisas. Vou lhe passar esse link caso você tenha interesse em usar.
http://cloud.spring.io/spring-cloud-netflix/spring-cloud-netflix.html

Outra coisa eu vi que você implentou a validação na mão, pois então, existe uma maneira mais simples, bonita e rápida de validação, chamada de Java Validatio no link a seguir tem uma exmplo de uso com Spring MVC.

Outra implementação complementar:
http://hibernate.org/validator/

Sobre o porque de sua classe PessoaService só funcionar em @RestController é porque ela é um Bean injetavél, pois você está usando um padrão chamada Injeção de Depedência. Outra coisa sua classe pode ser injetada em qualquer classe que esteja anotada diretamente com @Component ou de outra anotação que seja herdade @Component, que no caso de @RestController herda de @Component.

Mais qualquer outras dúvidas só perguntar, estamos aqui para ajudar :smiley:;

Z

Eu tinha pesquisado bastante sobre microservices e como implementar, como está muito recente ainda não tem muito material explicando, lendo o blog do Martin fowler ele comentou sobre o Netflix OSS, então fui atrás porém achei muito complexo de implentar, com mais pesquisas achei o springBoot foi onde achei mais fácil de trabalhar, mas pelo o que você está dizendo do jeito que estou implementando seria somente um serviço RestFull certo?

Então essa implementação que estou fazendo na mão é para gerar mensagens amigaveis ao cliente, ao invés de sempre estourar um exception e mandar um HttpCode 500 Internal server error.
Com esse validations que você mandou eu consigo evitar um exception?

E

Olá @zefinir novamente.

Para a primeira pergunta, a resposta é sim, no seu caso vejo que você não está utilizando o conceito de micro-service, mas sim de webservice.

Para a segunda pergunta, a resposta é não, mas tem como você tratar a exception e enviar as mensagens de error de validação para a aplicação cliente atráves de Exception Handling do Spring MVC.

Eu criei um gist de como eu uso para validar e mandar as mensagens de error para a aplicação cliente.

Qualquer dúvida só perguntar novamente.

Att.
Emanuel Batista

Z

Eu estava usando esse exemplo mesmo, mas só conseguia mandar um HttpCode personalizado, porque vamos supor no cadastro eu tenho campos que são requeridos que devem ser enviados e o email é unico na base de dados não pode se repetir, então para campos obrigatórios eu teria que mandar um 403 campos requeridos não informados, e caso o email já existe na base de dados enviar um 409 email já cadastrado e vendo esse video https://youtu.be/Mmh78Yf_6AM que achei e deu certo na forma que eu queria implementar, mas vou tentar usando esses validations e te falo se obtive sucesso.

ah só para complementar quem consumirá essa API será um cliente mobile.

C

Olá,

O problema da validação para campo único é a concorrência.
Exemplo: dois usuários preencheram o formulário usando um mesmo e-mail e esse e-mail não está no banco, então a validação vai passar mas quando for gravar os dados no banco um desses usuários irá reclamar pois somente uma gravação terá sucesso, uma vez que no backend você verifica se o e-mail já existe antes de gravar os dados.

Mesmo assim, uma pergunta que você deve fazer para si mesmo é: esse processo no backend de verificar se o e-mail existe e em seguida gravar os dados é atômico ? Caso o e-mail não exista, existe a possibilidade por menor que seja de uma gravação ter sucesso e a outra não.

Como resolver isso: tornar o campo e-mail único no banco ou usar transação no método que faz a verificação de e-mail e gravação, assim garantido a atomicidade.

Lembram-se de concorrência de threads e a utilização de monitores, semáforos e métodos synchronized do Java SE ?! Somente uma thread de cada vez pode executar esse método pois o monitor só deixa um de cada vez.

Espero ter sido claro o suficiente.

Criado 27 de outubro de 2016
Ultima resposta 2 de nov. de 2016
Respostas 5
Participantes 3