Como anda a qualidade do seu projeto com Spring?

Quando pensamos em software, principalmente os de médio e longo prazo, um dos fatores que, com certeza vai machucar o time de desenvolvimento, é o momento onde começamos a modificar ou implementar novas funcionalidades no projeto. É nesse momento que os parentes dos antigos programadores começam a ser xingados e, com o passar do tempo, até uma reescrita do sistema começa a ser cogitada.

Acompanhamento e medição da qualidade de código é um fator super importante para a saúde do sistema. Para projetos que envolvem times, é sempre importante lembrar que, provavelmente, as pessoas do seu time vão sair e outras vão chegar. Buscando justamente colaborar com o mundo de desenvolvimento nesse aspecto, meu amigo Maurício Aniche (autor do livro de TDD da Casa do Código) vem trabalhando em projetos que nos ajudam a tirar métricas de qualidade do nosso código.

E para a felicidade geral dos times que usam Spring como alicerce dos seus sistemas, ele publicou um projeto focado em fornecer métricas para softwares que usem o framework. O Springlint pode ser executado como um plugin do maven ou até mesmo diretamente através do jar.

   mvn com.github.mauricioaniche:springlint-maven-plugin:0.4:springlint

Ele fornece uma saída indicando justamente os pontos onde estamos mandando bem e também todos os pontos onde o springlint considera que estamos pecando.

relatorio-springlint

A saída dele é uma página HTML. Na figura acima vemos o que ele fala de cada classe anotada com @Controller. Cada quadradinho verde revela o nome da classe :).

Existem métricas que já são estabelecidas no mercado como:

  1. Métricas de Acoplamento (CBO e RFC), pois não queremos classes acopladas.
  2. Coesão (LCOM), pois uma classe não coesa também não é bom.
  3. Complexidade ciclomática (WMC), pois um código muito complicado é difícil de manter.

Além dessas, também existem métricas criadas por ele durante os estudos do mestrado e do seu atual doutorado.

  1. Promiscuous Controller: Quando um Controller oferece muitas ações diferentes para seus clientes.
  2. Smart Controller: Quando há muito fluxo dentro de um só Controller.
  3. Meddling Service: Quando um Service acessa o banco de dados diretamente.
  4. Smart repositories: Quando um Repositório tem lógicas muito complicadas.
  5. Laborious Repository Method: Quando um único método em um Repositório faz mais de uma coisa só no banco de dados.
  6. Fat Repository: Quando um Repositório lida com muitas entidades de uma só vez.

Este é o tipo de informação que você deve buscar o tempo todo nos seus projetos. Muito simples de executar e com um resultado muito interessante.

Fiquei um bom tempo sem postar, mas o motivo foi nobre! Meu filho nasceu e eu passei 1 mês num curso super prático de cuidados de bebês! Semana que vem, na segunda, tem post novo!

 

Advertisements

Abstraindo o download de arquivos no Spring MVC

Há um tempo atrás, escrevi um post sobre como realizar download de arquivos utilizando o Spring MVC. Rafael Ponte,  um amigo meu, empreendedor/programador que mora em Fortaleza, perguntou se não tinha um jeito mais fácil de realizar o mesmo processo. Basicamente ele queria que tivesse uma abstração melhor para indicar um download, algo como o que segue:

	@RequestMapping(value = "/downloads/{code}", 
		method = RequestMethod.GET)
	public FileDownload dowload(@PathVariable("code") String code,
			@AuthenticationPrincipal User user) {

		Optional<Course> foundCourse = courseDao.findByUserEmailAndCode(
				user.getEmail(), code);

		if (!foundCourse.isPresent()) {
			return ResponseEntity.notFound().build();
		}

		Book book = bookDao.find(foundCourse.get().getCode());
		return new FileDownload(...);
	}

Pronto, eu não encontrei nada. Confesse que não procurei muito, e, ainda acho, que existe a chance de ter algo mais elegante e que eu não conheça. De todo jeito eu caí no mesmo problema, trabalhando em um projeto interno aqui na Caelum e a pessoa que estava pareando comigo fez o mesmo questionamento :/. Nesse momento paramos para pensar um pouco mais e chegamos na seguinte solução de código:

@RequestMapping(value = "/downloads/{code}", 
	method = RequestMethod.GET)
public HttpEntity<?> dowload(@PathVariable("code") String code,
		@AuthenticationPrincipal User user) {

	Optional<Course> foundCourse = courseDao.findByUserEmailAndCode(
			user.getEmail(), code);
	if (!foundCourse.isPresent()) {
		return ResponseEntity.notFound().build();
	}

	Book book = bookDao.find(foundCourse.get().getCode());
	return new DownloadEntity(book.generateDrmVersion(user), 
		code + ".pdf");
}

Basicamente alcançamos a mesma abstração que Rafael tinha sugerido :). A sacada é que um dos possíveis retornos do seu método é um objeto cuja classe seja igual ou filha de HttpEntity. Herdamos dela e criamos nossa abstração para representar um download.

package br.com.caelum.alumni.infra.spring;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;

public class DownloadEntity extends HttpEntity<byte[]> {

	private HttpEntity<byte[]> httpEntity;

	public DownloadEntity(byte[] bytes, String fileName) {
		HttpHeaders httpHeaders = new HttpHeaders();
		httpHeaders.add("Content-disposition", "attachment; filename=\""+fileName+"\"");
		httpEntity = new HttpEntity<byte[]>(bytes, httpHeaders);
	}

	public HttpHeaders getHeaders() {
		return httpEntity.getHeaders();
	}

	public byte[] getBody() {
		return httpEntity.getBody();
	}

	public boolean hasBody() {
		return httpEntity.hasBody();
	}

	public boolean equals(Object other) {
		return httpEntity.equals(other);
	}

	public int hashCode() {
		return httpEntity.hashCode();
	}

	public String toString() {
		return httpEntity.toString();
	}
}

Herdamos de HttpEntity e simplesmente delegamos as chamadas dos métodos para o HttpEntity que criamos internamente no nosso objeto. Uma solução simples e que você pode reaproveitar para vários projetos seus.

Acho que esse é um passo muito importante quando falamos de programação, no caso aqui estamos usando orientação a objetos. Precisamos ser capazes de aplicar os conceitos que aprendemos em qualquer situação, não importa se o código é nosso ou provido por algum framework. Tem uma interface, você pode implementar, ta vendo uma classe que não é marcada como final, você pode herdar! O foco é a solução e a facilidade de manutenção :).

Combinando Angular e Spring MVC

O leitor Bruno Leonardo pediu que eu escrevesse um post sobre como lidar com requisições ajax dentro dos controllers do Spring MVC. Talvez a maior dificuldade seja entender que, provavelmente, a única coisa que você vai precisar mudar nos métodos dos controllers é o retorno deles. Em vez de retornar uma página html completa, você tem a possibilidade de retornar os dados em outros formatos, como JSON.  Vou pegar um caso de uso real e mostrar um pouco do fluxo. Para completar, já que estamos falando de JavaScript, vou usar o angular como biblioteca :).

Em um dos projetos que estou programando atualmente, tive que possibilitar o login do usuário via ajax. O html ficou igual ao que segue abaixo.

  <form ng-submit="login()">
    <div>
     <input type="text" ng-model="usuario.email" />
    </div>
    <div>
     <input type="password" ng-model="usuario.senhaLimpa" />
    </div>

    <input type="submit" value="login">
  </form>

Como estou usando o angular, utilizei as diretivas do mesmo para indicar que quando o usuário decidir submeter o formulário, a função login() deve ser chamado. É justamente para isso que serve a diretiva ng-submit. Além disso, preciso pegar os valores que estão nos campos dos formulário e atualizar meu objeto JavaScript. Para esta parte, a gente pode usar a diretiva ng-model. A ideia aqui não é explicar em detalhes o angular, mas sim já fornecer um exemplo prático para que você possa estudá-lo depois :). Abaixo segue o código do meu controller do angular, para lidar com essa parte de login.

	angular.module('agendamento-online').controller('LoginController', function($scope,$http,$location,localStorageService,$routeParams) {	
				
		$scope.login = function(){
			var tentandoLogar = $http.post('/api/clientes/salao/login',$scope.usuario);
			
			tentandoLogar.success(function(retorno){
				lidaComRetornoDaApiUsuario(retorno);			
				$location.path("/agendamento-online/servicos.html");H
			});
			
			tentandoLogar.error(function(retorno,status){					
				console.log(retorno);
			});
		};
	}

Vamos dar um zoom aqui nas linhas, para ver o que cada uma está fazendo e também o que precisamos fazer no lado do servidor.

    var tentandoLogar = $http.post('/api/clientes/salao/login',$scope.usuario);

Aqui estamos tentando fazer um post para um endereço específico, passando como argumento o json contendo as informações de login. Agora sim, chegou o momento de suportarmos esse endereço no nosso servidor!

		@RequestMapping(method = RequestMethod.POST, value = "/api/clientes/salao/login", consumes = {
				MediaType.APPLICATION_JSON_VALUE}, produces = MediaType.APPLICATION_JSON_VALUE)
		public ResponseEntity<?> login(@Valid @RequestBody LoginClienteSalaoDTO form,
				BindingResult bindingResult) {
			if (bindingResult.hasErrors()) {
				return ResponseEntity.badRequest().body(
						ValidationErrorBuilder.fromBindingErrors(bindingResult));
			}

			Optional<ClienteSalao> cliente = loginClienteSalaoAction.execute(form);
			if (!cliente.isPresent()) {
				return ResponseEntity.notFound().build();
			}

			return ResponseEntity.ok(new RetornoSimples(cliente.get().getCodigoInterno()));
		}

Perceba que mapeamos ele com a annotation padrão, @RequestMapping. O detalhe que acrescentamos mais algumas informações. Informamos que o parâmetro do método vai vir via JSON, isso é feita através do header da requisição chamado content-type. O próprio angular já define isso para a gente, você pode definir a mesma coisa quando estiver usando jquery ou qualquer outra solução para fazer seu ajax. Também informamos, através do atributo produces que o retorno do método deve ser transformado em JSON e enviado para o cliente.

Só para deixar registrado, por default o seu método  recebe parâmetros com o content-type application/x-www-form-urlencoded, que é o utilizado pelos seus formulários nas páginas pela web. Um detalhe que você deve ficar atento em requisições do tipo post, que esperam, por exemplo, json como formato dos dados nos parâmetros, é que tais informações vem no próprio corpo da requisição. Por conta disso, você precisa anotar o seu parâmetro com @RequestBody. 

Um outro ponto interessante é que o retorno do método é um objeto do tipo ResponseEntity, justamente a abstração do Spring MVC que recebe algum objeto como argumento e transforma ele para o tipo especificado pelo header accept-type, também enviado pela aplicação cliente. Os tipos de retornos suportados são justamente os especificados no atributo producesPerceba que inclusive os erros de validação devem ser retornados como um objeto a ser serializado.

Para fechar, um ponto muito importante é a correta utilização dos status http. Perceba que nessa lógica podem ser gerados três tipos de status:

  1. Bad Request(400) -> Indica que a requisição veio com dados inválidos
  2. Not Found(404) -> Como o próprio nome diz, quer dizer que algo não foi encontrado
  3. ok(200) -> Quer dizer que deu tudo certo

O uso correto dos status influencia diretamente no uso da sua api javascript. Vamos dar uma olhada no trecho de código abaixo.

	var tentandoLogar = $http.post('/api/clientes/salao/login',$scope.usuario);

	tentandoLogar.success(function(retorno){
		lidaComRetornoDaApiUsuario(retorno);
		
		$location.path("/agendamento-online/servicos.html");H
	});

	tentandoLogar.error(function(retorno,status){					
		console.log(retorno);
	});

Perceba que a função post retorna um objeto(promise) que possui alguns outras funções. No exemplo acima, registramos dois callbacks: success e error. A função de erro só é chamada caso um status acima de 400 seja retornado. Isso é super importante! Já vi api’s que sempre retornam 200, mesmo quando um erro de validação acontece :(. Nessa situação, você tem que ficar acrescentando ifs no callback que lida com retornos de sucesso, poluindo o código e afetando na manutenção.

Mais um lembrete aqui. Para seus objetos poderem pegar os objetos e transformar os mesmos para JSON, XML ou qualquer outro formato, você vai precisar de uma biblioteca. Como JSON e XML são os formatos mais comuns, você pode usar o Jackson, que o Spring já possui integração.

Lembre que para ajudar nas configurações você sempre pode usar o Spring Boot, que facilita demais todo o setup do seu projeto. Aproveitando o último parágrafo, caso você tenha interesse no angular, tenta dar uma olhada no curso do Alura ou no curso presencial da Caelum.

SetupMyProject open source!

Um pouco depois do meio do ano passado, foi lançado o SetupMyProject. De lá para cá podemos dizer que ele tem caminhado bem, já temos mais de 5000 downloads dos mais variados tipos de projetos. A ideia do SetupMyProject é facilitar a criação de novos projetos Java usando alguns dos frameworks mais conhecidos, como:

  1. Spring e Spring MVC
  2. Spring Boot
  3. VRaptor 4
  4. JSF 2.2
  5. JAX-RS(RestEasy)

Como a aceitação tem sido muito boa, achamos que um bom próximo passo era deixá-lo open source, e foi justamente isso que fizemos. Ele está disponível no github e todo mundo está convidado para ver nossas gambiarras, acertos e, se possível, contribuir para deixarmos o projeto ainda melhor. Tentei deixar o readme o mais convidativo possível, para que você baixe e tente até rodar na sua máquina.

Outro ponto que é legal de comentar é sobre a arquitetura do projeto, não é nada de outro mundo, mas vou deixar aqui registrado.

  1. Linguagem : Java
  2. Framework MVC : Spring MVC
  3. Spring Boot para facilitar setup e utilização de plugins do Spring
  4. ORM : Hibernate(bem pouca coisa para ser sincero)
  5. Engine para geração dos projetos : JBoss Forge 2

Olhando as tecnologias, tirando o JBoss Forge, não tem nada fora do normal. Além disso, pensando em design de código mesmo, tem bastante coisa legal. Usamos o Design Pattern Command para abstrair os passos necessários para geração de um projeto, além de um grafo ordenado, roubado do VRaptor 3, para que um comando possa informar se deve ser executado antes ou depois de outro. Da uma olhada, acho que você pode gostar :).

Caso você já tenha usado o SetupMyProject, gostaria de te pedir um pequeno favor, vai lá no github e da aquela estrela para gente :). É um jeito de sabermos o quanto a comunidade gostou e também é uma forma de incentivo. Outro ponto importante, vamos adorar que o maior número possível de issues sejam abertas. Tem um projeto que gostaria de gerar, ou algum plugin a mais que você quer ver configurado na geração do setup, nos avise por lá :).

 

 

 

Spring 5 e Reactive programming parte 1

Antes que você continue a ler este post, preciso deixar um aviso, ainda estou formando a minha opinião sobre o real uso do conceito da programação reativa em nosso contexto de trabalho. Por mais que eu ache super importante saber as teorias, pelo menos para mim, elas não são tão relevantes se eu não consigo encaixar no meu dia a dia. Caso eu escreva alguma coisa que você não concorde, ficarei mais do que feliz de debater na parte dos comentários :).

Dada a condição que eu gosto de tentar aplicar as teorias nos projetos que eu participo, vamos pegar um exemplo real aqui. No meu tempo extra, tenho pego alguns projetos com Rasa, inclusive já mencionei ele num post anterior, e um desses projetos é um site que centraliza a venda de outros produtos.  Basicamente, no fluxo final da compra do usuário os seguintes passos são executados:

  1. Gravo um objeto que representa a compra do usuário no banco
  2. Faço uma requisição HTTP para o sistema do produto sendo comprado, avisando do novo usuário
  3. Mando um email para o usuário informando os dados de acesso para o produto que foi adquirido

Abaixo segue um exemplo de código invocado dentro do controller:

	@RequestMapping(value = "/confirma/{idCompra}")
	public String callbackPagseguro(
			@PathVariable("idCompra") String idCompra,
			@RequestParam("code") String notificationCode,
			HttpServletRequest request) {
		
		Compra compra = tentaAcharACompraPeloIdCustomizado(idCompra);
		
		customEnv.indicaAmbientePagSeguro();

		RespostaNotificacaoAssinatura resposta = customEnv.
			getRespostaNotificacaoTransacao(notificationCode);
		
		finalizaPagamento.finaliza(compra,resposta);
		

		return "redirect:/pagseguro/fim/"+compra.getTransacaoId();
	}

E aqui temos o nosso ponto a ser resolvido. Até a invocação do método no controller, o Spring tem o controle sobre tudo. Não precisamos nem ficar imaginando o que acontece lá dentro, mas sabemos que entre chegar um request no Servlet do Spring MVC e ele invocar o método correto no seu controller, muita coisa pode acontecer, seguem alguns passos.

  1. Descoberta do classe/método que deve ser invocado
  2. Conversão de parâmetros do request para os tipos esperados pelos parâmetros
  3. Execução da validação da entrada dos dados convertidos

Depois que seu método é invocado, ele ainda tem trabalho a fazer.

  1. Caso você não use o @ResponseBody, ele vai te jogar para a view em questão
  2. Caso você use o @ResponseBody no método, ele vai pegar o retorno e serializar, usando alguma biblioteca em questão, como o Jackson.

Todos esses passos são implementados do jeito que ele quiser. Atualmente a maioria deles, pelo menos eu acho, ocorre de forma serial. Tudo é executado em apenas um core do seu servidor, mesmo que ele tenha 4, 8 ou 16 núcleos. Além disso, tudo também é implementado de forma síncrona, com um passo sempre esperando o outro, antes do fluxo evoluir.

Essa vai ser uma das grandes mudanças na próxima versão do framework! Todo o core vai ser remodelado para que o framework possa tirar proveito da super infraestrutura provida pelos servidores. Execução de código em paralelo(já provido pelos parallel streams no Java 8), assíncrono, lazy etc. A ideia é que consigamos escalar o máximo nossa app dentro de uma máquina só!

Só que para sua aplicação tirar realmente proveito desse modelo, a ideia é que ela também seja escrita seguindo a mesma ideia. Para dar suporte a tudo isso, é que um dos alicerces da próxima versão do Spring vai ser o Project Reactor. Ele traz implementado as ideias de Reactive Programming e você vai ter que gastar um tempo para aprender, se quiser embarcar na aventura :P.

Agora eu vou tentar resumir ao máximo o princípio. A ideia é que tudo seja baseado em eventos, basicamente uma implementação de um Observer. Quem já conhece o pattern, talvez fique um pouco mais confortável. Vamos pegar o mesmo fluxo que tinha escrito lá em cima e fazer usando o novo modelo.

	@RequestMapping(value = "/confirma/{idCompra}")
	public Mono<ModelAndView> callBackPagseguro(@PathVariable("idCompra") 
			String idCompra,
			@RequestParam("code") String notificationCode, 
			HttpServletRequest request) {

		Mono<Compra> eventoBuscaCompra = 
			tentaAcharACompraPeloIdCustomizado(idCompra);
		
			
		Mono<Mono<NotificacaoLiberacao>> eventoNotificaLiberacao = 
			eventoBuscaCompra.map(c -> {
				customEnv.indicaAmbientePagSeguro();
				RespostaNotificacaoAssinatura resposta = customEnv
						.getRespostaNotificacaoTransacao(notificationCode);
				return finalizaPagamento.finaliza(c, resposta);
		});
		
		
		Mono<ModelAndView> eventoGeracaoModelAndView = eventoNotificaLiberacao.
			map(notificacao -> {
				return new ModelAndView("redirect:/pagseguro/fim/");			 
			});

		return eventoGeracaoModelAndView;
	}

Antes de entrar no detalhe da implementação, o que precisamos entender é o seguinte: quando o Spring MVC chamar nosso método, ainda não vamos executar nenhuma chamada para o banco de dados, nem para o outro sistema e muito menos mandar um email. Simplesmente criamos um fluxo de eventos que devem ser executadas nessa ordem e gerar o resultado esperado.

E quem vai executar? Esse é o pulo do gato, o framework! Sei lá se ele vai executar de maneira serial, paralela, síncrona ou assíncrona. Aqui você pode pensar do mesmo jeito que já pensamos em relação a chamada do Garbage Collector. Deixamos a JVM invocar ele, porque ela sabe qual é o melhor momento! Na apresentação do Spring One(instante 21:26) é comentado justamente isso, Reactive Programming não significa, necessariamente, executar tudo de maneira assíncrona, mesmo que o manifesto até passe essa ideia.

Para fechar, vamos olhar de novo o código para tentar entender como que isso foi implementado.

	@RequestMapping(value = "/confirma/{idCompra}")
	public Mono<ModelAndView> callBackPagseguro(@PathVariable("idCompra") 
			String idCompra,
			@RequestParam("code") String notificationCode, 
			HttpServletRequest request) {

		Mono<Compra> eventoBuscaCompra = 
			tentaAcharACompraPeloIdCustomizado(idCompra);
		
			
		Mono<Mono<NotificacaoLiberacao>> eventoNotificaLiberacao = 
			eventoBuscaCompra.map(c -> {
				customEnv.indicaAmbientePagSeguro();
				RespostaNotificacaoAssinatura resposta = customEnv
						.getRespostaNotificacaoTransacao(notificationCode);
				return finalizaPagamento.finaliza(c, resposta);
		});
		
		
		Mono<ModelAndView> eventoGeracaoModelAndView = eventoNotificaLiberacao.
			map(notificacao -> {
				return new ModelAndView("redirect:/pagseguro/fim/");			 
			});

		return eventoGeracaoModelAndView;
	}

Olhando com atenção, você vai perceber que o nome das minhas variáveis sempre tem a palavra evento. Como eu tinha dito, essa é a ideia. Precisamos criar vários eventos que, em algum momento do tratamento da requisição, vão ser executados. A classe Mono, representa a idea de um evento que gera(emite) apenas uma saída.

	public abstract class Mono<T> implements Publisher<T>,Backpressurable, 
	Introspectable,Completable {

	...

	}

Dentre as várias interfaces que ela implementa, está a Publisher<T>. Ela indica que determinado objeto é um produtor de eventos(sinais). Essa é uma das interfaces principais da especificação Reactor Streams. A ideia é que o tempo inteiro você esteja criando produtores de eventos. Aqui podemos dar um zoom em outro pedaço de código específico:

		Mono<Mono<NotificacaoLiberacao>> eventoNotificaLiberacao = 
			eventoBuscaCompra.map(c -> {
				customEnv.indicaAmbientePagSeguro();
				RespostaNotificacaoAssinatura resposta = customEnv
						.getRespostaNotificacaoTransacao(notificationCode);
				return finalizaPagamento.finaliza(c, resposta);
		});

Usamos o método map, tipicamente usado, nas aplicações tradicionais, para transformar coleções de um tipo para coleções de outro tipo. Só que pensando pelo lado funcional da coisa, a ideia é que o map seja uma função que recebe uma entrada X e retorna uma saída Y. No caso aqui vamos transformar um evento que gera uma compra em um evento de evento(Mono<Mono<…) que gera uma NotificacaoLiberacao.  Evento de evento? É o que? Quando temos uma sequência de produtores de eventos, dizemos que temos uma Flux! Para obter o Flux, podemos usar o flatMap :).

	Flux<NotificacaoLiberacao> eventosQueVaoGerarUmaNotificaco = 
		eventoBuscaCompra.flatMap(c -> {
			RespostaNotificacaoAssinatura resposta = customEnv
					.getRespostaNotificacaoTransacao(notificationCode);
			return finalizaPagamento.finaliza(c, resposta);
	});
	
	
	Flux<ModelAndView> eventosQueVaoGerarOModelAndView = 
		eventosQueVaoGerarUmaNotificaco.map(notificacao -> {
			return new ModelAndView("redirect:/pagseguro/fim/");			 
	});

Um outro exemplo de geração de Flux, que vai ficar para o próximo post, é quando você quiser retornar uma lista de objetos do seu DAO :).

Nesse ponto você pode estar pensando, já tem o produtor do evento, mas cadê o consumidor!? O seu pensamento não podia estar mais certo.

	Flux<ModelAndView> eventosQueVaoGerarOModelAndView = 
		eventosQueVaoGerarUmaNotificaco.map(notificacao -> {
			return new ModelAndView("redirect:/pagseguro/fim/");			 
	});
	
	ConsumerSubscriber<ModelAndView> consumer = 
		new ConsumerSubscriber<ModelAndView>();
	eventosQueVaoGerarOModelAndView.subscribe(consumer);

A classe ConsumerSubscriber é apenas uma das zilhares de implementações da interface Subscriber. Você pode associar quantos consumidores quiser, a um produtor de evento, exatamente do mesmo jeito que o Observer nos ensina. Inclusive o ConsumerSubscriber, possui um construtor para você passar os callbacks de tratamento dos eventos.

	public ConsumerSubscriber(Consumer<? super T> consumer,
			Consumer<? super Throwable> errorConsumer,
			Runnable completeConsumer) {
		this.consumer = consumer;
		this.errorConsumer = errorConsumer;
		this.completeConsumer = completeConsumer;
	}

Só que fique atento. Em geral, quando você tiver dentro do Spring 5, você não vai criar os subscribers, já que isso será trabalho do framework. Do mesmo jeito que hoje não é você que injeta as dependências nos seus objetos, e sim o container. Para fechar as interfaces importantes, quando você liga um interessado no evento(Subscriber) em um gerador de eventos(Publisher) você cria a chamada Subscription. 

Este post foi para tentar passar a ideia do novo modelo que muitos de nós teremos que lidar. Como disse no inicio, o meu entendimento ainda está em construção, o uso exagerado do método map até indica isso :).  Para facilitar o seu estudo, segue alguns links que eu usei.

  1. http://www.reactivemanifesto.org/
  2. https://www.youtube.com/watch?v=fec9nEIybp0&list=PLgGXSWYM2FpPuIFvbv6U_5cKLJB6PQbN4&index=35
  3. https://github.com/spring-projects/spring-reactive
  4. http://projectreactor.io/core/docs/reference/
  5. http://spring.io/blog/2016/02/09/reactive-spring
  6. https://github.com/reactor/lite-rx-api-hands-on

Nos próximos posts, eu vou tentar dar um zoom em outras partes do Project Reactor, além de associar com os casos de uso do nosso dia a dia. Apenas para fim de estudo, também criei um projeto no github que tenta demonstrar esse modelo de programação.

Como você disponibiliza os mesmos objetos para várias views?

Nos últimos tempos, no meu tempo extra, desenvolvi um sistema administrativo junto com um amigo meu de aulas na CaelumRasa Lariguet. Como vários destes sistemas, existem elementos dinâmicos que devem aparecer em toda santa tela que é carregada pela aplicação. No nosso caso, tínhamos que exibir sempre os últimos agendamentos e um calendário com o número de agendamentos para determinado dia. Abaixo segue um print:

componentes

Para fazer isso, uma das maneiras é adicionar esses objetos em todo request tratado pela aplicação.

	@Controller
	@RequestMapping("/cliente")
	public class ClienteController {

		@Autowired
		private ProximosServicos proximosServicos;
		@Autowired
		private CalendarioDia calendario;		
		
		@RequestMapping("/form")
		public ModelAndView form(Cliente cliente) {
			ModelAndView modelAndView = new ModelAndView("cliente/form-add");
			modelAndView.addAttribute("proximosServicos",proximosServicos);
			modelAndView.addAttribute("calendario",calendario);
			return modelAndView;

		}

		//outros métodos
	}

Como você já pode imaginar, essa solução ia ficar um pouco complicada. E se a gente precisasse colocar mais um objeto na tela? Teríamos que alterar diversos controllers! Um paliativo seria criar uma classe que faria esse trabalho para a gente.

	@Controller
	@RequestMapping("/cliente")
	public class ClienteController {

		@Autowired
		private ComponentesComunsViews componentes;
		
		@RequestMapping("/form")
		public ModelAndView form(Cliente cliente) {
			ModelAndView modelAndView = new ModelAndView("cliente/form-add");
			componentes.adicionaNaView(modelAndView);
			return modelAndView;

		}

		//outros métodos
	}

Mesmo assim, vamos ter que receber um objeto dessa classe injetado em todos os controllers e aí vamos ter que invocar um método nele para colocar tudo necessário no request. Uma segunda alternativa seria criar um interceptor. Dessa forma podemos interceptar todas as requisições, como se fosse um filtro de Servlet, e já disponibilizar esses objetos para a view.

Todas essas são formas são válidas, mas eu estou aqui para sugerir mais uma, que talvez você até já conheça. Ao invés de fazer com que todo controller ou que algum interceptor faça este trabalho, podemos simplesmente disponibilizar um objeto especializado em toda a view, de maneira automática! Vamos pegar especificamente o componente que busca os próximos serviços.

@Component
@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST)
public class ProximosServicos {

	@Autowired
	private AgendamentoDao agendamentoDao;
	@Autowired
	private DataSolicitadaAgendmento dataSolicitada;

	public List<Agendamento> lista() {		
		List<Agendamento> agendamentos = agendamentoDao
				.buscaAgendamentosDoDiaAPartirDeUmHorario(dataSolicitada.get());
		return agendamentos;
	}
}

Na página, para listar os agendamentos, basta que a gente continue fazendo como já estava sendo feito.

  	<c:forEach var="agendamento" items="${proximosServicos.lista()}">
		...
	</c:forEach>

O único problema que falta resolver é: como que esse objeto foi parar na jsp? Para ensinar ao Spring MVC, basta que invoquemos mais um método na hora de configurar o nosso objeto do InternalResourceViewResolver. 

	@Bean
	public InternalResourceViewResolver internalResourceViewResolver() {
		InternalResourceViewResolver resolver = new InternalResourceViewResolver();
		resolver.setPrefix("/WEB-INF/views/");
		resolver.setSuffix(".jsp");
		//aqui faz a mágica
		resolver.setExposeContextBeansAsAttributes(true);
		return resolver;
	}

Pronto, o objeto do tipo ProximosServicos sempre vai estar disponível em qualquer página da sua aplicação. O método setExposeContextBeansAsAttributes, como o próprio nome informa, faz com que qualquer objeto gerenciado pelo Spring fique acessível nas páginas. Caso você ache que isso pode fazer com que a gente fique usando tudo que é objeto direto na jsp, fique tranquilo, você também pode usar o setExposedContextBeanNames e passar o nome do bean que deve ser disponibilizado.

Mesmo enxergando o perigo de um acesso indiscriminado aos objetos na view, eu gosto dessa abordagem e tenho usado em meus projetos. Acho que deixamos as classes mais coesas, tanto nos controllers quanto nos objetos específicos para a camada de visualização.

Chegou até o fim do post? Conta para mim o que você achou :). Baseado nas discussões, muitas vezes, já surge a ideia para um próximo!

Saiba um pouco mais sobre os proxies do Spring

Outro dia no grupo de discussões sobre o livro de Spring MVC apareceu uma dúvida que tenho uma impressão que é um tanto recorrente. O leitor explicou mais ou menos assim: “Tenho a classe UserDAO que implementa a interface UserDetailsService. Possuo um ponto de injeção onde declaro um atributo do tipo UserDAO e marco o mesmo com @Autowired. Quando subo a minha aplicação, recebo uma exception”. Pensando no código, a situação é a que está descrita abaixo.

	@Repository
	public class UserDAO implements UserDetailsService {

		@PersistenceContext
		private EntityManager em;

		@Override
		public UserDetails loadUserByUsername(String username) 
			throws UsernameNotFoundException {
			//implementacao
		}
	}
	@EnableWebSecurity
	@Configuration
	public class SecurityConfiguration extends WebSecurityConfigurerAdapter{

		@Override
		protected void configure(HttpSecurity http) throws Exception {
			//implementacao
		}	
		
                //injeção problemática
		@Autowired
		private UserDAO users;
		
		@Override
		protected void configure(AuthenticationManagerBuilder auth)
				throws Exception {
			//implementacao
		}
		
		
	}

A exception lançada é a seguinte:

Caused by: java.lang.IllegalArgumentException: Can not set br.com.casadocodigo.loja.daos.UserDAO field br.com.casadocodigo.loja.conf.SecurityConfiguration.users to com.sun.proxy.$Proxy49

Em uma primeira olhada talvez não faça muito sentido. Como não podemos injetar um objeto cuja classe é a mesma do ponto de injeção? Aí você começa a pesquisar e descobre que se trocar pela interface a injeção funciona corretamente.

	@Autowired
	private UserDetailsService users;

Para que isso fique mais claro, é necessário entender como que o Spring instância o seu objeto quando a classe dele implementa alguma interface.

	UserDAO delegate = new UserDAO();
	InvocationHandler handler = new InvocationHandler() {

		@Override
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			System.out.println("interceptando a invocação do metodo " + method.getName());
			return method.invoke(delegate, args);
		}
	};

        ClassLoader classLoader = //pega um classLoader;
	UserDAO instance = (UserDAO) Proxy.newProxyInstance(
			classLoader, 
			new Class[] { UserDetailsService.class }, handler);

	//invocando o método como se fosse no objeto real		
	instance.loadUserByUsername("alberto");	

A classe Proxy do pacote java.lang.reflect.Proxy é a classe padrão do Java quando necessitamos criar um objeto que segue esse design pattern. Sempre que você recebe algum objeto injetado em seu projeto com Spring, na verdade está recebendo um Proxy. O que vai causar a exception é justamente a maneira como o Proxy está sendo criado. Por exemplo, no código acima, caso tentemos executá-lo será lançada a seguinte exception.

Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to br.com.casadocodigo.loja.daos.UserDAO

Parecida com a que foi lançada quando você subiu o seu projeto :). Por default, quando implementamos alguma interface, o Spring vai criar o Proxy usando o mecanismo padrão do Java. Só para tentar deixar claro. Basicamente a implementação de um Proxy exige que uma classe seja construída em tempo de execução, herdando da classe base ou/e implementando as interfaces dessa mesma classe base. O mecanismo padrão do Java só fornece a segunda opção. Essa é a razão da exception ser lançada, não temos uma filha de UserDAO, e sim uma implementação da interface UserDetailsService.

Caso você realmente queira receber a injeção pela classe concreta, você pode configurar o Spring para criar o Proxy em função da classe concreta.

	@Repository
	@Scope(value=ConfigurableBeanFactory.SCOPE_SINGLETON,
		proxyMode=ScopedProxyMode.TARGET_CLASS)
	public class UserDAO implements UserDetailsService {
                 ...
        }

Para possibilitar esse estilo de criação de Proxy, o Spring recorre a uma biblioteca chamada cglib. Para não ficarmos curiosos, abaixo segue um exemplo de código de criação de Proxy usando o cglib.

	Enhancer enhancer = new Enhancer();
	enhancer.setSuperclass(UserDAO.class);
	UserDAO delegate = new UserDAO();
	org.springframework.cglib.proxy.InvocationHandler handler = new org.springframework.cglib.proxy.InvocationHandler() {

		@Override
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			System.out.println("interceptando a invocação do metodo " + method.getName());
			return method.invoke(delegate, args);
		}
	};
	enhancer.setCallback(handler);
	UserDAO proxy = (UserDAO) enhancer.create();
	proxy.loadUserByUsername("alberto");

A ideia desse post foi desmistificar a maneira como seus objetos são criados e injetados dentro do Spring. Em geral, toda exception faz bastante sentido. Precisamos ficar atentos e tentar sempre procurar o real motivo dela. Dessa forma nossa produtividade só cresce em cada novo projeto que pegamos, já que vamos passando cada vez menos por erros de infraestrutura.