Como seu sistema envia email?

Mandar email é uma tarefa bem rotineira em nossos projetos. Mandamos email de boas vindas quando um novo usuário se cadastra, email para recuperar senha etc. Uma coisa que geralmente todas essas features tem em comum, é que o email deve ser enviado em HTML.

Existem alguns projetos para facilitar a escrita do template do email e carregá-lo dentro do projeto, o Freemarker é um desses. Mais antigamente, o Velocity também era uma opção muito usada no mercado. O objetivo do post é justamente mostrar que podemos implementar essas features com algo que já está presente no seu projeto, sem a necessidade de aprender uma nova tecnologia ou adicionar uma dependência nova no seu projeto.

Pensando no código que você escreveria com o Freemarker, seria algo mais ou menos assim:

		@Controller
		public class HomeController {
		
			@PostMapping("/usuario")
			public String novoUsuario(Usuario usuario) {
		
				usuarioDao.salva(usuario);
  
				HtmlEmail email = new HtmlEmail();
				Freemarker template = new Freemarker();
				String body = template.resolve(HomeController.class.getResourceAsStream("/boasvidas.ftl"),usuario);
				email.setBody(body);
				...
			}
		}

A ideia é que agora a gente tem que carregar o HTML de uma outra forma. Pensando que nosso projeto é web, meio que já temos isso pronto. Dê uma olhada no controller que temos abaixo:

		@Controller
		public class TemplateController {
		
			@GetMapping("/template/boas-vindas")
			public String boasVindas(Integer idUsuario,Model model) {
				Usuario usuario = usuarioDao.carrega(idUsuario);
				model.addAttribute("usuario", usuario);
				return "templates/boasvindas";
			}
		}

Este é um controller que serve como gerador de HTML para emails que precisam ser enviados pelo sistema. Agora só precisamos acessar o endereço no momento de envio dos emails.

		@Controller
		public class HomeController {
		
			@GetMapping("/")
			public String novoUsuario(Usuario usuario) {
				RestTemplate restTemplate = new RestTemplate();
				ResponseEntity<String> entity = restTemplate.getForEntity("http://localhost:8080/template/boas-vindas/"+usuario.getId(), String.class);
				String body = entity.getBody();
				
				HtmlEmail email = new HtmlEmail();
				email.setBody(body);
				
				return "home/index";
			}
		}

Dessa forma resolvemos o problema de geração do conteúdo do email. Como o acesso é feito via localhost, não interfere quase nada no desempenho. Além disso você pode continuar escrevendo seu HTML da mesma maneira que sempre escreveu, o que também é um bom ganho.

O post em si não tem muito haver com o universo do Spring, mas achei legal compartilhar porque é uma solução que tenho usado bastante nos projetos e acho que tem funcionado bem. E aí, o que achou? Muita gambiarra?

Advertisements

Feign uma forma simples para consumir serviços

Dificilmente uma aplicação “vive sozinha” e em algum momento pode surgir a necessidade de integrá-la com outras aplicações.

As necessidades podem ser diversas:

  • Consultar dados de um sistema legado
  • Retornar endereço a partir de um CEP
  • Efetuar pagamento online
  • Consultar o custo de envio de determinada mercadoria
  • Fazer autenticação através de alguma rede social ou qualquer

Hoje em dia muitas das integrações utilizam o modelo arquitetural REST, e não é uma tarefa muito difícil criar um cliente para consumir um serviço web.

Vamos usar como exemplo via cep, que é uma alternativa para pesquisar um endereço a partir de um CEP.

Para consumir o serviço este basta efetuar uma requisição GET no seguinte formato https://viacep.com.br/ws/NUMERO-DO-CEP/FORMATO. O formato pode ser: json,xml,piped,querty.

Se por exemplo efetuarmos uma requisição GET para https://viacep.com.br/ws/04101300/json, temos o seguinte retorno:

{
"cep": "04101-300",
"logradouro": "Rua Vergueiro",
"complemento": "de 2771 a 5049 – lado ímpar",
"bairro": "Vila Mariana",
"localidade": "São Paulo",
"uf": "SP",
"unidade": "",
"ibge": "3550308",
"gia": "1004"
}

Consumindo Serviço com RestTemplate

Para consumir um Web Service  no Spring podemos usar a classe RestTemplate que tem uma interface de uso bem simples.

Vamos criar uma aplicação com Spring Boot para consumir o serviço do via cep.

Vamos começar adicionando o parent do Spring Boot ao pom.xml:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
    </parent>

E também o plugin para gerar o JAR auto-contido:

<build>
    <plugins>
       <plugin>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Para representar o retorno do Web Service vamos criar a classe Endereco

public class Endereco {

    private String cep;
    private String logradouro;
    private String complemento;
    private String bairro;
    private String localidade;
    private String uf;

    //getters 

    @Override
    public String toString() {
        return "Endereco{" +
                "cep='" + cep + '\'' +
                ", logradouro='" + logradouro + '\'' +
                ", complemento='" + complemento + '\'' +
                ", bairro='" + bairro + '\'' +
                ", localidade='" + localidade + '\'' +
                ", uf='" + uf + '\'' +
                '}';
    }
}

Agora vamos criar a classe que inicializa o contexto do Spring:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Vamos encapsular o código para consumir o serviço em uma classe ViaCepCleient


@Component
public class ViaCEPClient {

    public Endereco buscaEnderecoPor(String cep){
        RestTemplate template = new RestRemplate();
        return template.getForObject("https://viacep.com.br/ws/{cep}/json",Endereco.class, cep);
    }
}

Como a ideia do projeto é bem simples vamos rodar tudo a partir da classe Application. A ideia é pegar o cep na variável args e através do cliente (ViaCepClient) retornar o endereço e logar no console.

O Spring Boot disponibiliza uma interface chamada CommandLineRunner que tem a declaração do método void run(String… args) throws Exception;.

Quando temos no nosso classpath algum Bean que produza CommandLineRunner, o Spring Boot após a inicialização pega o que foi recebido no método main e repassa para esse Bean.

Dessa forma conseguimos separar o código de inicialização e o código que deve ser executado baseado nos argumentos que foi passado para o Spring Boot.

Vamos alterar nossa classe Application para que ela tenha um Bean para CommandLineRunner.

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public CommandLineRunner run(ViaCEPClient client){
        return args -> {
            if (args.length > 0) {
                String cep = args[0];

                Endereco endereco = client
                                     .buscaEnderecoPor(cep);

                System.out.println(endereco);
            }
        };
    }

}

Ao executarmos nossa classe Application com algum argumento veremos no console algo similar a isso:

Endereco{cep=’04101-300′, logradouro=’Rua Vergueiro’, complemento=’de 2771 a 5049 – lado ímpar’, bairro=’Vila Mariana’, localidade=’São Paulo’, uf=’SP’}

Consumindo serviço com Feign

Agora imagine em uma aplicação onde temos que consumir diversos serviços, ou em um arquitetura de micro serviços onde temos que nos integrar com diversos serviços para que a aplicação como um todo funcione. Pense em quantas vezes vamos ter que escrever um cliente usando o RestTemplate?

E geralmente se o programador teve que repetir uma tarefa mais de 3 vezes, ele automatiza essa tarefa de alguma forma.

Pensando nisso alguém teve a brilhante ideia de deixar ainda mais fácil a criação de clientes para consumir serviços. E então nasceu o projeto Feign.

O projeto Feign foi inspirado em: Retrofit, JAXRS-2.0, entre outras. Com ele podemos criar clientes de uma forma declarativa.

Então a galera do Spring incorporou o Feign dentro da sua própria stack. Mais especificamente abaixo do projeto Spring Cloud. Que é um projeto voltado para arquitetura de micro serviços, cloud e etc.

Vamos então migrar nosso cliente de RestTemplate para usar Feign. Primeiramente vamos adicionar as dependências do projeto Spring Cloud e do Feign.

O Spring Cloud segue a mesma linha do Spring Boot com as ideias dos Starters. Só que ao invés de usar um projeto base (parent) ele usa o conceito de dependências gerenciadas.

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Dalston.SR1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Agora que temos o Spring Cloud no nosso projeto vamos adicionar a dependência do Feign

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>

Para habilitar o Feign no projeto vamos anotar a classe Application com @EnableFeignClients

@SpringBootApplication
@EnableFeignClients
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public CommandLineRunner run(ViaCEPClient client){
        return args -> {
            if (args.length > 0) {
                String cep = args[0];

                Endereco endereco = client.buscaEnderecoPor(cep);

                System.out.println(endereco);
            }
        };
    }
}

Como falei anteriormente com o Feign podemos criar clientes de uma forma declarativa. Ou seja só iremos declarar o cliente sem colocar nenhuma implementação.

Vamos começar convertendo nossa classe ViaCEPClient para uma interface (pois não queremos ter nenhuma implementação nela).

@Component
public interface ViaCEPClient {
    Endereco buscaEnderecoPor(String cep);
}

Vamos trocar a anotação @Component para @FeignClient e nela adicionar a URL do serviço.

@FeignClient(url="https://viacep.com.br/ws/")
public interface ViaCEPClient {
    Endereco buscaEnderecoPor(String cep);
}

Precisamos dizer qual o Endpoint o método Endereco buscaEnderecoPor(String cep); deve acessar.

Para isso vamos usar as anotações de mapeamento do Spring MVC:

  • @RequestMapping
  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping

Da mesma forma precisamos mapear os parâmetros:

    • @PathVariable
    • @RequestParam

.

@FeignClient(url="https://viacep.com.br/ws/")
public interface ViaCEPClient {

    @GetMapping("{cep}/json")
    Endereco buscaEnderecoPor(@PathVariable("cep") String cep);
}

Por ultimo o Feign pede que além da URL o nosso cliente de serviço tenha um nome (que nada mais é do que um identificador). Vamos adicionar o parâmetro name na anotação @FeignClient.

@FeignClient(url="https://viacep.com.br/ws/", name = "viacep")
public interface ViaCEPClient {

    @GetMapping("{cep}/json")
    Endereco buscaEnderecoPor(@PathVariable("cep") String cep);
}

Se rodarmos o código novamente teremos o mesmo resultado utilizando o RestTemplate. Com a diferença que o código real para consumir o serviço será gerado em tempo de execução. Ou seja nunca mais precisamos usar RestTemplate para gerar clientes.

E aí o que achou do Feign?

Spring Data Rest é vida

Fala aí galera, tudo bem? Meu nome é Fernando e sou instrutor e desenvolvedor na caelumalura.

Não é de hoje que o Spring vem facilitando nossa vida, e vamos combinar que os caras mandam muito bem!

Agora imagina só um mundo perfeito, onde declaramos nossas classes de modelo, repositórios e magicamente temos enpoints para fazermos todas as operações que declaramos nos nossos repositórios (por exemplo incluir, listar, alterar e remover).

Esse mundo perfeito existe e nele essa mágica se chama Spring data rest. Sim, ao utilizarmos ele só de declararmos nossos repositórios temos endpoints disponíveis.

Tá, legal saber que existe o Spring Data Rest.  Mas e como uso ele? (Show me the code!!!)

Bom galera eu montei um exemplo bem básico com Spring Boot Maven e está no meu Github. Nele você vai ver no arquivo pom.xml as seguintes declarações:

Spring Boot

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>1.4.2.RELEASE</version>
</parent>

E os staters do Spring Data e do Spring data Rest

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

Além dos Starters tenho também o h2 como banco de dados em memória e o lombok.

<dependency>
	<groupId>com.h2database</groupId>
	<artifactId>h2</artifactId>
</dependency>

<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
</dependency>

Para quem não conheçe o lombok, ele nos ajuda a escrever menos código repetitivo por exemplo: getter, setter, construtor, toString, equals/hashcode e etc...

Com ele anotamos nossos atributos com @Getter e/ou @Setter, anotamos nossa classe com @NoArgsConstructor ou @RequiredArgsConstructor, @AllArgsConstructor e ao compilarmos nosso código ele gera os byte-codes equivalentes.Vale a pena dar uma conferida!

No meu caso estou usando a anotação @Data (que engloba um monte dessas anotações) e @NoArgsConstructor (para ter um construtor sem parâmetros, por conta dos frameworks).

(OBS: Para rodar o projeto por dentro do IDE você precisa instalar o agent lombok, do contrário seu IDE não vai encontrar o getters, setters e afins.)

Em java temos duas classes de modelo Book e Author.

@Entity
@Data
@NoArgsConstructor
public class Author {

	@Id
	@GeneratedValue
	private Long id;

	@NotBlank
	private String name;

}
@Entity
@Data
@NoArgsConstructor
public class Book {

	@Id
	@GeneratedValue
	private Long id;

	@NotBlank
	private String title;

	@NotBlank
	private String description;

	@Min(50)
	private Integer numOfPages;

	@Valid
	@ManyToMany(fetch=FetchType.EAGER)
	private Set<Author> authors = new HashSet<>();

	public void add(Author author) {
		authors.add(author);
	}

}

Além do modelo tenho também um repositórios para cada, BookRepository e AuthorRepository

public interface BookRepository extends CrudRepository<Book, Long> {
}
public interface AuthorRepository extends CrudRepository<Author, Long>{
}

Para subir a aplicação tenho a classe Application que inicia o Spring Boot e salva um livro e um autor no banco de dados;

@SpringBootApplication
public class Application {

	public static void main(String[] args) throws Exception {
		SpringApplication.run(Application.class, args);
	}

	@Autowired
	private BookRepository bookRepository;

	@Autowired
	private AuthorRepository authorRepository;

	@PostConstruct
	@Transactional
	public void onLoad(){

		Author alberto = new Author();
		alberto.setName("Alberto");
		authorRepository.save(alberto);

		Book book = new Book();
		book.setTitle("Spring MVC");
		book.setDescription("Domine o principal framework web Java");
		book.setNumOfPages(237);

		book.add(alberto);

		bookRepository.save(book);

	}

}

E pronto! Temos uma endpoints para efetuarmos o CRUD de livros e autores. (Spring Data Rest é ou não é vida?)

Ao acessarmos http://localhost:8080, temos o seguinte retorno

{
"_links" : {
"authors" : {
"href" : "http://localhost:8080/authors&quot;
},
"books" : {
"href" : "http://localhost:8080/books&quot;
},
"profile" : {
"href" : "http://localhost:8080/profile&quot;
}
}
}

O Spring Data Rest usa fortemente os conceitos de HATEOAS que a grosso modo diz que através de um recurso disponível deve ser possível navegar pelo estado desse recurso através dos links. Por padrão o spring usa um modelo de apresentação chamado HAL para representação da resposta.

Bom os endpoints /authors e /books me parecem bem ok, o que deve ter neles, mas e o endpoint /profile?

Esse enpoint tem as meta-informações do seus serviços, por exemplo ao acessarmos http://localhost:8080/profile/authors temos o seguinte resultado

{
"alps":{
"version":"1.0",
"descriptors":[
{
"id":"author-representation",
"href":"http://localhost:8080/profile/authors&quot;,
"descriptors":[
{
"name":"name",
"type":"SEMANTIC"
}
]
},
{
"id":"create-authors",
"name":"authors",
"type":"UNSAFE",
"rt":"#author-representation"
},
{
"id":"get-authors",
"name":"authors",
"type":"SAFE",
"rt":"#author-representation"
},
{
"id":"patch-author",
"name":"author",
"type":"UNSAFE",
"rt":"#author-representation"
},
{
"id":"update-author",
"name":"author",
"type":"IDEMPOTENT",
"rt":"#author-representation"
},
{
"id":"get-author",
"name":"author",
"type":"SAFE",
"rt":"#author-representation"
},
{
"id":"delete-author",
"name":"author",
"type":"IDEMPOTENT",
"rt":"#author-representation"
}
]
}
}

Essas meta-informações estão associadas a qual representação temos no enpoint (no nosso caso)  authors e toda a definição dessa representação (os atributos e métodos). O endpoint profile é definido na RFC 6906.

Dentro da representação do author temos um objeto com id author-representation e nele temos um descritor com nome name e o tipo dele é SEMANTIC.
Esse tipo SEMANTIC indica um elemento que guarda um estado (atributo).

Além desse objeto temos um objeto com id create-authors, get-authors ou update-author ambos com nome author porém com tipos diferentes (nesse caso temos UNSAFE, SAFE e IDEMPOTENT). Esse objetos são as operações que podemos fazer sobre essa representação (methods).

Cada tipo tem um comportamento diferente:

SAFE – operações desse tipo são idempotentes e não alteram estado no servidor (GET, HEAD).

UNSAFE – operações desse tipo não são idempotentes e alteram estado no servidor (POST).

IDEMPOTENT – operações desse tipo são idempotentes e alteram estado no servidor (PUT, DELETE).

Uma operação é considerada idempotente se o resultado dele for bem sucedida indiferente do numero de vezes que ela for executada.

Agora sim, vamos para os endpoints mais “óbvieis“. Irei utilizar o programa curl para efetuar as chamadas para nosso endpoints.

Para listar nosso autores podemos efetuar a seguinte requisição:

curl -X GET http://localhost:8080/authors

(Deixei explicito o verbo GET somente por questões didáticas).

Nesse caso temos o seguinte resultado:

{
"_embedded" : {
"authors" : [ {
"name" : "Alberto",
"_links" : {
"self" : {
"href" : "http://localhost:8080/authors/1&quot;
},
"author" : {
"href" : "http://localhost:8080/authors/1&quot;
}
}]
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/authors&quot;
},
"profile" : {
"href" : "http://localhost:8080/profile/authors&quot;
}
}
}

Nesse caso temos um autor com o nome Alberto e os links do autor levam ao recurso dele mesmo. E os links da representação como um todo levam a lista de autores ou ao profile de autores.

Vamos seguirmos o link para listar somente o autor Alberto.

curl -X GET http://localhost:8080/authors/1

E nesse caso temos o seguinte resultado:

{
"name" : "Alberto",
"_links" : {
"self" : {
"href" : "http://localhost:8080/authors/1&quot;
},
"author" : {
"href" : "http://localhost:8080/authors/1&quot;
}
}
}

E para criar um novo autor? bom para isso temos que usar o verbo POST.

curl -X POST -H "Content-type: application/json" -d '{"name": "Fernando"}' http://localhost:8080/authors

Agora temos dois autores, e para alterar? Fácil né, só usar outro verbo. Nesse caso o PATCH

 curl -X PATCH -H "Content-type: application/json" -d '{"name": "Fernando Willian"}' http://localhost:8080/authors/2

E para excluir vamos usar o verbo DELETE

curl -X DELETE http://localhost:8080/authors/2

Podemos usar as mesmas operações para os livros.

Para deixar um pouco mais interessante, vamos adicionar um pouco de segurança ao nossos endpoints.
Para isso vamos adicionar o starter do Spring Security no nosso arquivo pom.xml:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
</dependency>

E vamos configurar como será nossa autenticação e quais os endereços que queremos proteger:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.inMemoryAuthentication()
		.withUser("common").password("123").roles("USER").and()
		.withUser("admin").password("@dm1n").roles("ADMIN");
		
	}
	
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http
			.httpBasic()
			.and()
				.authorizeRequests()
					.antMatchers(HttpMethod.POST, "/**").hasRole("ADMIN")
					.antMatchers(HttpMethod.PATCH, "/**").hasRole("ADMIN")
					.antMatchers(HttpMethod.DELETE, "/**").hasRole("ADMIN")
				.and()
					.csrf()
						.disable();
	}
	
}

Nessa configuração temos que nos autenticar com uma conta com permissão de ADMIN para efetuar qualquer requisição com os verbos POST, PATCH e DELETE.

Agora para incluir um novo autor devemos nos autenticar:

curl -X POST -H "Content-type: application/json" -d '{"name": "Fernando"}' http://localhost:8080/authors -u admin:@dm1n

O mesmo se aplica para alteração ou exclusão.

E aí o que achou do Spring Data Rest? Já o conhecia?

Entrevista com Arjen Poutsma, commiter do Spring!

Eu estava esperando ansiosamente para escrever este post, ele contém uma rápida entrevista com um dos principais commiters do Spring, Arjen! Ele respondeu algumas perguntas que fiz sobre o mundo que nos espera com a nova versão do framework, com o suporte integral ao conceito de Reactive Programming. Já vou deixar aqui a versão em inglês, depois posto a tradução.

Alberto: Just to introduce to our readers, could you talk a little bit about you and your role in the Spring Framework?

Arjen:  My name is Arjen Poutsma. I have been working on Spring for over ten years. I started out with Spring Web Services, then worked on Spring MVC – specifically the REST features, then Spring Scala, and for the last two years I have been working on Spring Reactive, together with Brian Clozel, Sebastien Deleuze, Stephane Maldini, abd Rossen Stoyanchev.

In this project, our team has been creating a new reactive foundation for Spring. We have essentially looked at the Spring MVC module, evaluated the code therein, and rewrote those pieces we need over to a non-blocking, event-driven style. We used Reactor as a foundation for this. The resulting code lives in the new spring-web-reactive module, next to the existing spring-webmvc module. The two modules share many concepts, but do not share any code. This is because Spring Web Reactive runs on a Reactive Streams HTTP adapter layer that’s fully non-blocking and reactive all the way down to the HTTP runtime. So while Spring MVC is built for and runs on Servlet containers, Spring Web Reactive runs also on non-Servlet runtimes such as Netty.

On top of the Spring Web Reactive module, we have two programming models. One is the existing annotation-based model, with @Controller, @RequestMapping and so on. These are the exact same annotations you use in Spring Web MVC. The other model is a recently introduced functional model, with RouterFunctions and HandlerFunctions.

I’ve attached a picture which hopefully makes this clearer.

architecture

Alberto: So, we are all excited about the new version of Spring, with the Reactive support. Could you tell us how this update will affect our way of programming?

Arjen: Just to be clear: upgrading to Spring 5 alone will not require any changes any changes to your code. As with previous major version upgrades, we have made sure that Spring 5 is backward compatible with Spring 4. So if you have a Spring 4 MVC application running on a Servlet engine, you will not have to change anything.

However, if you choose to use the new Reactive features, you will have to reconsider your architecture, as there any many differences. For instance, the guarantee that a HTTP request will be handled in a single thread is no longer the case: request will be handled by many threads, each doing a piece of the work when there is need for it (i.e. backpressure). Essentially, you are switching from a model a big thread pool, where most threads are waiting (either for incoming HTTP request, or waiting on a blocking datastore) to a model with a smaller thread pool, where each thread switches between requests many times and is effectively . Fortunately, you will not have to deal with these threads yourself, as this is where Reactor comes in. Reactor allows you to define your request handling pipeline in a functional, high-level abstraction through Flux and Mono. So rather than returning a List<Person> from your controller, for instance, you would return a Flux<Person>. However, this does also mean that relying on ThreadLocals will no longer work, and there are quite a number of frameworks and libraries (including Spring) that rely on these for some of their functionality.

Alberto: A lot of frameworks and libraries do not support this style of programming, Hibernate is an example. How can we combine our most used frameworks and Reactive Programming? The stack will evolve to support? I really like Spring Data JPA and I was thinking about that.

Arjen: Indeed, another difference between a traditional architecture and a reactive one is data stores. Obviously, in Reactive environments, there is a strong preference for non-blocking, asynchronous data stores. For some data stores, this is a great fit; for others it is not. There are a couple of NoSQL data stores that do reactive support: Couchbase, and MongoDB come to mind. For other, more traditional data access APIs, such as JDBC and JPA, there is no reactive support yet, so if you rely on them, there is no other choice than to wrap these synchronous, blocking APIs, and give them access to their own thread pool. Oracle is actually working on a non-blocking version of JDBC, but details are very sparse at this point. For JPA, the question is whether a session-based model actually makes sense in a reactive world.

Alberto: Could you explain how the Reactive Programming will help our applications to scale? Is there this relation between Reactive Programming and scalibility?

Arjen: I like to compare the two programming styles with an analogy. Imagine you are eating in a restaurant, and want to order food. The moment you make your order with the waiter, he goes off to the kitchen and prepare it. When the food is done, he will come back from the kitchen to serve it to you. After that, he will look around to see if there are any other customers in need of his attention. Now imagine the owner of the restaurant wants to have more tables, i.e. he wants to scale up. If he wants to make sure every table does not have to wait for too long, he would have to hire as many waiters as he added tables, adding a lot of cost. This is the traditional, one-thread-per-request Servlet model, where the customers are HTTP clients, and the waiters represent threads.

A reactive model would operate more like a real-life restaurant, where the waiters just relay the orders to kitchen staff, and many people (i.e. threads) are working on your order before it is served to you. Looking at it this way, it becomes quite obvious why the reactive model scales better: you are using the resources available more efficiently.

That said, the reactive model does come with a certain cost. It is harder to write asynchronous code, and it is harder to debug. So Reactive Programming will definitely help *certain* application to scale; for others I would simply say that the effort is simply not worth it. There will always be many cases where imperative is just fine for the task at hand and others where reactive and non-blocking are a must. And with Spring 5, you can do both.

Espero que você tenha gostado da entrevista! Arjen foi muito solícito e acho que nos forneceu boas respostas.

Como vai ser seu código com o Spring 5?

Faz mais ou menos 1 mês que saiu o primeiro milestone do Spring 5 com o suporte a tão comentada Reactive Programming. Não vou me alongar explicando os conceitos de programação reativa, porque já o fiz em outro post, aqui no blog mesmo. A ideia desse post é mostrar as configurações necessárias para você ter o seu projeto usando o Spring 5 e também ter um exemplo funcionando e que esteja linkado com os código que fazemos no dia a dia.

A primeira coisa que você pode fazer é clonar o projeto que eu disponibilizei no github. Lá dentro você vai encontrar o pom.xml.

		<properties>
			...
			<reactor.version>3.0.0.RC1</reactor.version>
			<spring.version>5.0.0.M1</spring.version>		
		</properties>
		<dependencyManagement>
			<dependencies>
				<dependency>
					<groupId>org.springframework.boot.experimental</groupId>
					<artifactId>spring-boot-dependencies-web-reactive</artifactId>
					<version>0.1.0.M1</version>
					<type>pom</type>
					<scope>import</scope>
				</dependency>
			</dependencies>
		</dependencyManagement>	
		<dependencies>
			<dependency>
				<groupId>org.springframework.boot.experimental</groupId>
				<artifactId>spring-boot-starter-web-reactive</artifactId>
			</dependency>		

Perceba que usamos um novo starter do Spring Boot chamado spring-boot-starter-web-reactive. Ele contém justamente todas as dependências que precisamos, algumas delas são:

  1. Project Reactor
  2. Adapters para os servidores

Outro detalhe importante é definir que queremos a versão 5 do Spring. Isso foi feito através da propriedade spring.version.

Pronto, com o projeto configurado, podemos dar uma olhada no código em si. A nossa ideia aqui é ter um endpoint que retorna um JSON representando uma lista de autores. Um código normal para isso seria assim:


	@Repository
	public class AutorDao {
		
		@Autowired
		private EntityManager manager;

		public List<Autor> listaTodos(){		
			return manager.createQuery("select a from Autor a").getResultList())				
		}
	}



	@RestController
	public class AutoresController {
		
		@Autowired
		private AutorDao autoresDao;

		@RequestMapping("/autores")
		public List<Autor> index() {
			List<Autor> result = autoresDao.listaTodos();		
			return result;
		}
	}

O problema desse código é que quando o Spring delega a execução para seu método, ele perde completamente o controle da situação. Você escreve a lógica que quiser aí dentro e ela vai ser executada até o fim. É o código que chamamos de imperativo.

A grande sacada do Spring 5 é trazer um pouco de programação funcional para nossas soluções do dia a dia. Antes de detalhar o código, vamos apenas dar uma olhada nele.

	@Repository
	public class AutorDao {
		
		@Autowired
		private EntityManager manager;

		public Mono<List<Autor>> listaTodos(){		
			Mono<List<Autor>> query = Mono.fromSupplier(() -> manager.createQuery("select a from Autor a").getResultList());
			return query;
			
		}
	}

	@RestController
	public class AutoresController {
		
		@Autowired
		private AutorDao autoresDao;

		@RequestMapping("/autores")
		public Mono<List<Autor>> index() {
			Mono<List<Autor>> result = autoresDao.listaTodos();
			System.out.println("ainda não vai ter feito a query");
			return result;
		}
	}	

Agora que você já viu, espero que tenha respirado fundo também, podemos debater um pouco do que aconteceu. A primeira coisa é que em vez de retornar uma List<Autor>, você retornou uma Mono<List<Autor>>. Lembre que Mono é um evento que emite apenas um item, nesse caso uma lista de autores. Uma variação dessa solução é a que segue abaixo.

	@Repository
	public class AutorDao {
		
		@Autowired
		private EntityManager manager;

		public Flux<Autor> listaTodos(){		
			Mono<Query> query = Mono.fromSupplier(() -> manager.createQuery("select a from Autor a"));
			Flux<Autor> list = query.flatMap((q) -> Flux.fromIterable(q.getResultList()));
			return list;
			
		}
	}

	@RestController
	public class AutoresController {
		
		@Autowired
		private AutorDao autoresDao;

		@RequestMapping("/autores")
		public Flux<Autor> index() {
			Flux<Autor> result = autoresDao.listaTodos();
			System.out.println("ainda não vai ter feito a query");
			return result;
		}
	}



Em vez do nosso DAO ter um evento só, nós dividimos os passos do método em criar um evento que emite uma Query e aí aplicamos uma transformação para ele gerar um evento que emite vários autores, no caso Flux<Autor>Não estou explicando os tipos, já que isso já está explicado no outro post.

A grande mudança aqui é que você declara os comportamentos em vez de executá-los e, fazendo isso, você delega para o Spring a responsabilidade de executar os seus códigos. A ideia é que a sua aplicação vai ter a chance de usar melhor os recursos da máquina onde ela está executando. Já que o framework parece ser mais competente para isso do que nós, desenvolvedores do código de negócio.

No exemplo que eu usei, entretanto, o maior problema é que usamos o Hibernate e ele não tem nada de reativo dentro dele. O ideal era que o método que executa a query com Hibernate retornasse a Flux e por aí vai. Quando a stack de tecnologias inteira da nossa aplicação for para esse lado, aí sim, vamos realmente tirar proveito.

 

Facilidades com Mapping no Spring MVC 4.3

Olá pessoal, tudo bem? Me chamo Alex Felipe, sou editor de conteúdo na Alura com mais foco no blog da Alura, e também, sou desenvolvedor! A partir de agora e eventualmente, estarei escrevendo alguns posts sobre Spring, ou seja, novidades do framework, dicas que fazem toda diferença no nosso dia-a-dia como desenvolvedor entre diversos tópicos super bacanas! Espero que gostem 🙂

Uma das maiores rotinas para nós, desenvolvedores que usam o Spring, é justamente mapear um método para disponibilizarmos um recurso no sistema. Como fazemos isso no Spring MVC? Basicamente utilizamos a annotation @RequestMapping, como por exemplo, para exibir a home do nosso sistema:

@Controller
public class HomeController {

	@RequestMapping("/")
	public String home() {
	    return "home";
	}

}

E então, quando acessamos o endereço "/" do nosso sistema, ele exibe o conteúdo da nossa página home. Porém, existe casos em que estamos dentro de um controller e queremos acessar a mesma URL, porém, dependendo do verbo HTTP, queremos que o nosso sistema tenha um comportamento diferente.

Por exemplo, em um sistema que eu estava desenvolvendo, continha o controller ProdutoController e dentro tinha duas funcionalidades a gravar() e a listar():

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("produtos")
public class ProdutoController {

	@RequestMapping(method = RequestMethod.POST)
	public String gravar(Produto produto) {
		// recebe produto e salva
		return "redirect:/produtos";
	}

	@RequestMapping(method = RequestMethod.GET)
	public ModelAndView listar() {
		ModelAndView mav = new ModelAndView("/produtos/lista");
		// pega produtos do banco e lista
		return mav;
	}

    //métodos

}

Note que ambos os métodos estão mapeados para o mesmo endereço, "/produtos". Porém, para que isso seja possível no controller, diferenciamos cada método pelo request method do HTTP. Em outras palavras, quando acessamos o endereço "produtos" com GET entramos no método listar() e quando acessamos com POST entramos no método gravar().

Por enquanto não há muita novidade, mas e se ao invés de ficar acessando @RequestMapping(method=AlgumaCoisa), pudéssemos fazer algo como @GetMapping para GET, ou então, @PostMapping para POST? Seria super bacana, né? Pois é, a partir da nova release 4.3 do Spring que saiu agora em Julho de 2016, já podemos fazer isso!

Então aquele mesmo controller, com essas novas annotations, ficaria da seguinte forma:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("produtos")
public class ProdutoController {

	@PostMapping
	public String gravar(Produto produto) {
		// recebe produto e salva
		return "produtos/salvo";
	}

	@GetMapping
	public ModelAndView listar() {
		ModelAndView mav = new ModelAndView("/produtos/lista");
		// pega produtos do banco e lista
		return mav;
	}

	//métodos

}

Veja que agora o nosso mapeamento é muito mais objetivo! Em outras palavras, não precisamos mais nos preocupar em ficar passando o parâmetro method para indicar a qual tipo de request method o método irá funcionar. Além do @GetMapping e @PostMapping, temos também os seguintes métodos do HTTP:

Lembrando que essas novas annotations não são implementações totalmente novas, pois, por de trás dos panos, elas ainda fazem uso da annotaton @RequestMapping. Por exemplo, a implementação do @GetMapping:

@Target(value=METHOD)
 @Retention(value=RUNTIME)
 @Documented
 @RequestMapping(method=GET)
public @interface GetMapping

Isso significa que ainda podemos utilizar os mesmos atributos que utilizamos no @RequestMapping com exceção do method que já não é mais necessário 😉

Guia das annotations do Spring

O leitor Vinicius Silva escreveu um email dizendo que seria legal ter um post, meio que de referência, sobre várias das annotations mais comuns utilizadas em projetos com Spring. A seguir fiz uma lista das que vieram na minha cabeça e que realmente eu já utilizei nos projetos. Caso tenha faltado alguma, ou exista alguma outra que você queira saber, fique a vontade para perguntar :). Então vamos lá!

@Configuration

É uma annotation que indica que determinada classe possui métodos que expõe novos beans.

@Controller

Associada com classes que possuem métodos que processam requests numa aplicação web.

@Repository

Associada com classes que isolam o acesso aos dados da sua aplicação. Comumente associada a DAO’s.

@Service

Associada com classes que representam a ideia do Service do Domain Driven Design. Para ficar menos teórico pense em classes que representam algum fluxo de negócio da sua aplicação. Por exemplo, um fluxo de finalização de compra envolve atualizar manipular o carrinho, enviar email, processar pagamento etc. Este é o típico código que temos dificuldade de saber onde vamos colocar, em geral ele pode ficar num Service :).

@Component

A annotation básica que indica que uma classe vai ser gerenciada pelo container do Spring. Todas as annotations descritas acima são, na verdade, derivadas de @Component. A ideia é justamente passar mais semântica.

@ComponentScan

Em geral você a usa em classes de configuração(@Configuration) indicando quais pacotes ou classes devem ser scaneadas pelo Spring para que essa configuração funcione.

@Bean

Anotação utilizada em cima dos métodos de uma classe, geralmente marcada com @Configuration, indicando que o Spring deve invocar aquele método e gerenciar o objeto retornado por ele. Quando digo gerenciar é que agora este objeto pode ser injetado em qualquer ponto da sua aplicação.

@Autowired

Anotação utilizada para marcar o ponto de injeção na sua classe. Você pode colocar ela sobre atributos ou sobre o seu construtor com argumentos.

@Scope

Annotation utilizada para marcar o tempo de vida de um objeto gerenciado pelo container. Pode ser utilizada em classes anotadas com @Component, ou alguma de suas derivações. Além disso também pode usada em métodos anotados com @Bean. Quando você não utiliza nenhuma, o escopo default do objeto é o de aplicação, o que significa que vai existir apenas uma instância dele durante a execução do programa. Você alterar isso, anotando o local e usando alguma das constantes que existem na classe ConfigurableBeanFactory ou WebApplicationContext.

@RequestMapping

Geralmente utilizada em cima dos métodos de uma classe anotada com @Controller. Serve para você colocar os endereços da sua aplicação que, quando acessados por algum cliente, deverão ser direcionados para o determinado método.

@ResponseBody

Utilizada em métodos anotados com @RequestMapping para indicar que o retorno do método deve ser automaticamente escrito na resposta para o cliente. Muito comum quando queremos retornar JSON ou XML em função de algum objeto da aplicação.

@Primary

Caso você tenha dois métodos anotados com @Bean e com ambos retornando o mesmo tipo de objeto, como o Spring vai saber qual dos dois injetar por default em algum ponto da sua aplicação? É para isso que serve a annotation @Primary. Indica qual é a opção padrão de injeção. Caso você não queira usar a padrão, pode recorrer a annotation @Qualifier.

@Profile

Indica em qual profile tal bean deve ser carregado. Muito comum quando você tem classes que só devem ser carregadas em ambiente de dev ou de produção. Essa eu utilizo bastante e acho uma ideia simples, mas super relevante dentro do Spring.

@SpringBootApplication

Para quem usa Spring Boot, essa é uma das primeiras que você. Ela engloba a @Component, @ComponentScan e mais uma chamada @EnableAutoConfiguration, que é utilizada pelo Spring Boot para tentar advinhar as configurações necessárias para rodar o seu projeto.

Bom, acho que é isso aí. Adoro escrever posts que foram solicitados diretamente pela galera que acompanha o meu trabalho, é uma motivação bem grande. Querendo de outros temas, é só avisar por aqui ou pelo meu twitter.

@EnableAsync

Essa aqui não é tão comum, mas muitas vezes você precisa ações no sistema em background(outra thread). Essa annotation deve ser colocada em alguma classe marcada com @Configuration, para que o Spring habilite o suporte a execução assíncrona.

@Async

Uma vez que seu projeto habilitou o uso de execução de métodos assíncronos com a @EnableAsync, você pode marcar qualquer método de um bean gerenciado do projeto com essa annotation. Quando tal método for invocado, o Spring vai garantir que a execução dele será em outra thread.