Testando serviços REST com Spring Boot e RestTemplate

Uma das principais características do Spring Boot é a sua simplicidade em permitir criar rapidamente uma aplicação sem abrir mão do design do seu código. E se você realmente quer fazer um trabalho de qualidade não pode abrir mão dos testes. Um bom modo de se fazer isso é com testes efetivos (não mocks) rodando no seu ambiente desenvolvimento. No trecho de códigos criamos o nosso primeiro teste.

package br.com.erudio;

import java.io.IOException;
import java.util.List;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import br.com.erudio.models.Person;
import br.com.erudio.repository.PersonRepository;

//Inicializamos o SpringRunner
@RunWith(SpringRunner.class)
//Setamos como uma classe de testes com o Server inicializando em uma porta fixa
//Essa porta pode ser a 8080 ou a que desejarmos setada no nosso aplication.properties
//Acesse src/test/resources/application.properties caso deseje alterar
//No nosso caso é a 8888 como você pode ver no aplication.properties "server.port = 8888"
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class PersonEndpointTests {
    
    //URL base para onde as requests serão feitas
    final String BASE_PATH = "http://localhost:8888/person";

    //Injetamos o repositório para acesso ao Banco de dados
    @Autowired
    private PersonRepository repository;
	
    //Definimos o restTemplate
    private RestTemplate restTemplate;
    
    //Definimos o JacksonMapper responsável por converter
    //JSON para Objeto e vice versa
    private ObjectMapper MAPPER = new ObjectMapper();
    
    //Definimos o que será feito antes da execução do teste
    @Before
    public void setUp() throws Exception {

        //Deletamos todos os registros do banco
        repository.deleteAll();

        //Inserimos alguma pessoas no banco
        repository.save(new Person("Diego", "Samuel", "Asa Sul"));
        repository.save(new Person("Eudes", "Silva", "Rosário"));
        repository.save(new Person("Anderson", "Silva", "Santa Teresa"));
	repository.save(new Person("Alice", "Ferreira", "Bombeiros"));
	repository.save(new Person("Alan", "Franco", "Granja Marileusa"));        
       
        //Inicializamos o objeto restTemplate
        restTemplate = new RestTemplate();
    }
    
    @Test
    public void testCreatePerson() throws JsonProcessingException{

        //Criamos uma nova pessoa
        Person person = new Person("Leandro", "Costa", "Presidente Roosevelt");

        //Fazemos um HTTP request do tipo POST passando a pessoa como parâmetro
        Person response = restTemplate.postForObject(BASE_PATH, person, Person.class);

        //Verificamos se o resultado da requisição é igual ao esperado
        //Se sim significa que tudo correu bem
        Assert.assertEquals("Leandro Costa", response.getFirstName() + " " + response.getLastName());
    }
    
  

}

Agora faremos um HTTP request do tipo GET para listar todas as pessoas ou uma em específico

    @Test
    public void testFindOne() throws IOException{

        //Fazemos uma requisição HTTP GET buscando por todas as pessoas
    	String response = restTemplate
			.getForObject(BASE_PATH + "/findAll", String.class);

        //Convertemos a resposta JSON para Objeto usando op Jackson
        List<Person> persons = MAPPER.readValue(response, 
			MAPPER.getTypeFactory().constructCollectionType(List.class, Person.class));
        //Pegamos o ID da pessoa na posição 1 da lista e fazemos nova requisição
        //Recuperando as informações da mesma
        Person person = restTemplate.getForObject(BASE_PATH + "/" +
			persons.get(1).getIdPerson(), Person.class);
        
        //Verificamos se o resultado da requisição é igual ao esperado
        //Se sim significa que tudo correu bem
        Assert.assertNotNull(person);
    	Assert.assertEquals("Eudes", person.getFirstName());
    	Assert.assertEquals("Silva", person.getLastName());
    }

Agora faremos um HTTP request do tipo PUT para atualizar uma pessoa em específico

    
    @Test
    public void testUpdatePerson() throws IOException{
    	String response = restTemplate.getForObject(BASE_PATH + "/findAll", String.class);
        List<Person> persons = MAPPER.readValue(response,
			MAPPER.getTypeFactory().constructCollectionType(List.class, Person.class));
        
        //Pegamos o ID da pessoa na posição 2 da lista e fazemos nova requisição
        //Recuperando as informações da mesma
        Person person = restTemplate.getForObject(BASE_PATH + "/" +
			persons.get(2).getIdPerson(), Person.class);

        //Alteramos as informações da pessoa recuperada
        person.setFirstName("Tiago");
        person.setLastName("Ferreira");

        //Fazemos um HTTP request do tipo PUT passando a pessoa 
        //e suas novas informações como parâmetro
        restTemplate.put(BASE_PATH, person);
        
        //como a operação PUT do RestTemplate é do tipo void
        //Precisamos fazer uma nova requisição para recuperar 
        //as informações da pessoa atualizada
        Person person2 = restTemplate.getForObject(BASE_PATH + "/" +
			persons.get(2).getIdPerson(), Person.class);
       
        //Verificamos se o resultado da requisição é igual ao esperado
        //Se sim significa que tudo correu bem
        Assert.assertNotNull(person2);
    	Assert.assertEquals("Tiago", person2.getFirstName());
    	Assert.assertEquals("Ferreira", person2.getLastName());
        
    }

Sendo assim nos testamos as operações do nosso endpoint. Se quiser ver mais detalhes você pode baixar o código deste post aqui, descompactar o arquivo zip e importar na sua IDE preferida ou clonar usando Git:


git clone https://github.com/leandrocgsi/spring-boot-rest-with-mongodb-example.git


Você pode acessar outros posts sobre SpringBoot e REST aqui mesmo no blog. É isso aí bons estudos e se gostou da postagem, vá até o topo desta página e torne-se um membro VIP para receber conteúdos exclusivos.

Tags: , ,

Guia Rápido de Docker

Fala rapazeada recentemente eu tirei um tempo pra estudar Docker e usar deploiando aplicações com Spring Boot. Este é minha lista de comandos básicos. Se você tiver alguma dica adicional que não está listada aqui sinta-se livre para mencionar nos comentários e eu irei atualizar o post. Lembrando que a maioria dos comandos podem ser usados em qualquer tipo de aplicação e não apenas com Spring Boot.

Exibir informações do Docker

docker info

Listar Todas as Docker Images

docker images -a

Listar Todos os Docker Containers que estão em execução

docker ps

Listar Todos os Docker Containers

docker ps -a

Iniciar um Docker Container

docker start <container name>

Parar um Docker Container

docker stop <container name>

Reiniciar um Docker Container

docker restart <container name>

Visualizar os logs de um Docker Container em execução

docker logs <container name>

Deletar um Docker Container

Use a opção -f caso precise forçar a remoção.

docker rm <container name>

Deletar Todos os Docker Containers

Use a opção -f caso precise forçar a remoção.

docker rm $(docker ps -a -q)

Remover uma Docker Image

docker rmi <image name>

Remover Todas as Docker Images

docker rmi $(docker images -q)

Acessando o Shell de um Docker Container em execução

sudo docker exec -it <container name> bash

Saindo do Shell de um Docker Container em execução

CTRL+P+Q

Baixando uma imagem do DockerHub

docker pull <image name>

Criando uma Tag de Uma imagem a ser commitada no DockerHub

docker tag <docker hub user>/<image name> <docker hub user>/<image name> 

Autenticar no DockerHub

docker login

Enviar uma imagem para o DockerHub

docker push <docker hub user>/<image name>

Cosntruindo uma imagem a partir de um Dockerfile no diretório atual

docker build -t="<image name>" .

Exibir o histórico de um container em execução

docker history <container name>

Criando um Alias para um comando Docker

alias dps="docker ps"

Limpando o console

reset

Dicas espertas de Dockerfile para developers Spring Boot

Add Oracle Java to an Image

Para Ubuntu versão 16.10 LTS

FROM dockerfile/ubuntu

# Instala o Java 8.
RUN \
  echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | debconf-set-selections && \
  add-apt-repository -y ppa:webupd8team/java && \
  apt-get update && \
  apt-get install -y oracle-java8-installer && \
  rm -rf /var/lib/apt/lists/* && \
  rm -rf /var/cache/oracle-jdk8-installer


# Define o diretório de trabalho.
WORKDIR /data

# Define a variável de ambiente JAVA_HOME
ENV JAVA_HOME /usr/lib/jvm/java-8-oracle

# Define o comando padrão.
CMD ["bash"]

Adicionando e executando um .jar de uma aplicação Spring Boot a uma Docker Image

VOLUME /tmp
ADD /maven/myapp-0.0.1-SNAPSHOT.jar myapp.jar
RUN sh -c 'touch /myapp.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/myapp.jar"]

É isso aí bons estudos e se gostou da postagem vá até o topo dessa página e torne-se um membro VIP para receber conteúdos exclusivos.

Tags: , ,

Definindo o MongoDB como um serviço.

Em um post anterior você aprendeu como instalar o MongoDB e executá-lo. Entretanto abrir a janela de comando toda vez que quiser usar o MongoDb pode não ser algo muito interessante. Para isso podemos definir o MongoDB como um serviço que se inicializará junto com o sistema operacional. Para isso adapte para o seu cenário e execute o seguinte comando:

mongod --dbpath "{{seu_diretorio_do_mongo}}" --logpath "{{seu_diretorio_do_mongo}}\logs.txt" --install --serviceName "MongoDB"

No meu caso o comando ficou da forma abaixo.

Downloading Installer

Agora tecle WINDOWS + R e na janela que se abre digite services.msc isso irá abrir a tela de serviços do Windows. Procure por nosso novo serviço “MongoDB”.

Downloading Installer

Caso não esteja em inicialização automática defina como tal. E caso esteja parado clique com o direto e clique no botão iniciar.

Downloading Installer

Pronto de agora em diante toda vez que você iniciar o Windows o MongoDB também será inicializado. É isso aí bons estudos e se gostou da postagem vá até o topo dessa página e torne-se um membro VIP para receber conteúdos exclusivos.

Tags: ,

Instalando o MongoDB

Nesse post iremos aprender a instalar o MongoDB. Um banco de dados não relacional ou NoSQL como são mais comumente conhecidos. Para isso precisamos efetuar o download do MongoDB no site site oficial. Temos duas opções baixar o instalador sugerido para a nossa plataforma, no meu caso um .msi para o Windows. Ou escolher entre as diferentes versões disponíveis clinando no link “All Versions Binaries” destacado em vermelho na imagem.

Downloading Installer

Caso a sua escolha seja a segunda opção você irá visualizar uma imagem similar a imagem abaixo. Nesse caso escolha o instalador que mais se adeque a sua necessidade. No meu caso o arquivo .zip destacado na imagem abaixo.

Downloading Installer

Após efetuar o dounload extraia seu conteudo para o local de sua preferência.

Downloading Installer

No meu caso a unidade C://.

Downloading Installer

Se preferir renomeie o diretório para um nome mais amigável.

Downloading Installer

Acesse a pasta e copie o endereço da instalação no meu caso “C:\mongodb\bin”.

Downloading Installer

Caso tenha escolhido a opção de baixar o binário .msi acesse o diretório de downloads e execute o instalador.

Downloading Installer

Na janela inicial clique em next.

Downloading Installer

Clique no checkbox de aceite dos termos e em seguida clique em “Next”.

Downloading Installer

Clique no botão Complete e em seguida em Next

Downloading Installer

Clique no botão Install

Downloading Installer

Por fim clique em Finish. Pronto você já sabe executar a instalação por arquivo zip ou por instalador compilado. Agora vamos fazer as configurações finais.

Downloading Installer

Acesse a raiz da unidade C:\\ e crie uma nova pasta chamada data.

Downloading Installer

Dentro da pasta data crie outra pasta chamada db.

Downloading Installer

Casdo se esqueça de executar a etapa anterior ao iniciar o MongoDB verá o seguinte erro.

Downloading Installer

Agora vamos adicionar as variáveis de ambiente do MongoDB. Para isto, no Windows Explorer, clique com o direito sobre ícone “Este computador” e clique em propriedades.

Downloading Installer

Se preferir acesse o menu iniciar e clique em configurações.

Downloading Installer

Digite “Configurações Avançadas” e selecione a opção “Exibir configurações avançadas do sistema”.

Downloading Installer

Dos dois modos chegaremos a tela abaixo clique no menu “Configurações avançadas do sistema”.

Downloading Installer

Na tela que se abre clique no botão “Variáveis de Ambiente” destacado em vermelho.

Downloading Installer

Nas variáveis do sistema selecione a variável Path e clique no botão Editar destacados em vermelho.

Downloading Installer

Clique em novo e cole o diretório em que se encontra a instalação do MongoDB que pode ser o endereço do zip que compiamos anteriormente ou o diretório dos arquivos de programas se você tiver usado o instalador.

Downloading Installer

Acesse um terminal e digite o comando mongod você deverá visualizar uma tela similar a imagem abaixo dizendo que o MongoDB pode ser acessado pela porta 27017.

Downloading Installer

Pronto você instalou com sucesso o MongoDB na sua máquina agora você pode se conectar a ele usando uma ferramenta como o “MongoVUE” ou “RoboMongo”. No próximo post aprenderemos como definir o como como um serviço que inicializa automáticamente com o Windows. É isso aí bons estudos e se gostou da postagem torne-se um membro VIP e receba conteúdos exclusivos.

Tags: ,

Configurando uma Conexão MySQL no JBoss com MySQL Connector JDBC Driver


Em um posts anterior aprendemos como criar uma conexão via JBoss e um banco MSQL Server usando o JTDS Driver e Microsoft JDBC Driver. Neste post falaremos do MySQL Connector JDBC Driver. Para configurar ele no JBoss seguiremos alguns passos similares aos outros posts:


1. Baixe o driver no site do MySQL.


2. Extraia o arquivo recem baixado e localize o arquivo mysql-connector-java-5.1.38-bin.jar.


3. No seu JBOSS_HOME crie diretórios respeitando a seguinte hierarquia “modules\com\mysql\main”. Dentro desse diretório coloque o arquivo recém baixado mysql-connector-java-5.1.38-bin.jar e crie um novo arquivo chamado module.xml com o seguinte conteúdo:


<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="com.mysql">
  <resources>
    <resource-root path="mysql-connector-java-5.1.38-bin.jar"/>
  </resources>
  <dependencies>
    <module name="javax.api"/>
    <module name="javax.transaction.api"/>
  </dependencies>
</module>


3. Agora precisamos modificar nosso standalone.xml adicionando as configurações abaixo à seção de datasources. Diferente dos posts anteriores adicionei novas configurações para que você saiba que pode definir novos parâmetros além do básico. No geral podemos definir parâmetros para o pool de conexões, validações, cache dentre outros. Essas configurações são padrão e com exceção das configurações de validação se aplicam à maioria dos bancos de dados.


<datasource jndi-name="java:jboss/datasources/SeuDatabase" pool-name="SeuDatabase" enabled="true" use-java-context="true" use-ccm="true">
   <connection-url>jdbc:mysql://localhost:3306/SeuDatabase</connection-url>
   <driver>mysql</driver>
   <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
   
   <!-- Configuração opcional pra definir os parâmetros do pool de conexões -->
   <pool>
      <min-pool-size>10</min-pool-size>
      <max-pool-size>100</max-pool-size>
      <prefill>true</prefill>
   </pool>
   <security>
      <user-name>seu_usuario</user-name>
      <password>sua_senha</password>
   </security>
   
   <!-- Configuração opcional para validação de conexões e tratamento de exceptions -->
   <validation>
      <valid-connection-checker
         class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker"/>
      <exception-sorter
         class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLExceptionSorter"/>
   </validation>
   
   <!-- Configuração opcional com os parâmetros de de cache -->
   <statement>
      <prepared-statement-cache-size>100</prepared-statement-cache-size>
      <share-prepared-statements>true</share-prepared-statements>
   </statement>
</datasource> 


E na seção drivers:


<driver name="mysql" module="com.mysql">
   <datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlDataSource</datasource-class>
</driver>


O resultado final deve ser similar a configuração abaixo:


<subsystem xmlns="urn:jboss:domain:datasources:1.1">
   <datasources>
      <datasource jndi-name="java:jboss/datasources/SeuDatabase" pool-name="SeuDatabase"
		enabled="true" use-java-context="true" use-ccm="true">
         <connection-url>jdbc:mysql://localhost:3306/SeuDatabase</connection-url>
         <driver>mysql</driver>
         <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
         
         <!-- Configuração opcional pra definir os parâmetros do pool de conexões -->
         <pool>
            <min-pool-size>10</min-pool-size>
            <max-pool-size>100</max-pool-size>
            <prefill>true</prefill>
         </pool>
         <security>
            <user-name>seu_usuario</user-name>
            <password>sua_senha</password>
         </security>
         
         <!-- Configuração opcional para validação de conexões e tratamento de exceptions -->
         <validation>
            <valid-connection-checker
				class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker"/>
            <exception-sorter
				class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLExceptionSorter"/>
         </validation>
         
         <!-- Configuração opcional com os parâmetros de de cache -->
         <statement>
            <prepared-statement-cache-size>100</prepared-statement-cache-size>
            <share-prepared-statements>true</share-prepared-statements>
         </statement>
      </datasource>
      <drivers>
         <driver name="mysql" module="com.mysql">
            <datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlDataSource</datasource-class>
         </driver>
      </drivers>
   </datasources>
</subsystem>


Complementando as postagens sobre os datasources MSQL Server dessa vez aprendemos a criar uma conexão com uma base MySQL . Mais uma vez para soluções mais complexas use o Google e sua criatividade. É isso aí bons estudos e se gostou da postagem torne-se um membro VIP e receba conteúdos exclusivos..


Tags: , , ,

AngularJS: Como fixar o bug module “ngStorage” is not available!

Bom esse é um errinho estúpido que eu poderia ter resolvido facilmente apenas olhando direito a documentação mas que me custou um tempo razoável.

O Erro:

Se quando você inspeciona o console vê o erro abaixo então esse post é pra você.

Uncaught Error: [$injector:modulerr] Failed to instantiate module yourAppNameHere due to:
Error: [$injector:modulerr] Failed to instantiate module ngStorage due to:
Error: [$injector:nomod] Module 'ngStorage' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
http://errors.angularjs.org/1.4.6/$injector/nomod?p0=ngStorage
    at REGEX_STRING_REGEXP (http://localhost:3000/bower_components/angular/angular.js:68:12)
    at http://localhost:3000/bower_components/angular/angular.js:1986:17
    at ensure *snip*

A correção:

No meu caso alguns pacotes usavam indiretamente o pacote ngstorage e eu havia instalado o ngStorage. Sim temos duas variantes uma com “S” maiúsculo e outra não. Então eu deletei todos os módulos, do Bower, em cache. Ele cria um cache local dos pacotes que você definir no seu projeto. Nos Windows 10, a pasta de cache padrão é C:\Users\[SeuUser]\AppData\Local\bower\cache\packages (tenha certeza de que você não substituiu esse endereço padrão em seu arquivo .bowerrc).
E também deletei todas as dependencias do NodeJS que estão em C:\Users\[SeuUser]\AppData\Roaming\npm-cache. Feito isto eu executei um npm install e bower install –save ngstorage rodei o projeto novamente e tudo funcionou como o esperado.

Assumindo que você esteja usando Bower execute “bower install ngstorage” você deve se assegurar de que está tendo algo similar à imagem abaixo como retorno:

bugNgStorage

Caso você tenha um arquivo de dependências “bower.json” então execute “bower install ngstorage –save” para que o Bower adicione uma nova entrada para o ngstorage.

Então tudo deverá funcionar normalmente. É isso aí bons estudos e se gostou da postagem torne-se um membro VIP e receba conteúdos exclusivos.

Tags: , , ,