Posts com Tags Spring

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: , ,

Aplicações RESTful HATEOAS com SpringBoot


O HATEOAS, é uma das principais constraints arquiteturais do REST e possibilita a navegação entre recursos, que são representações dos modelos de negócio da aplicação. Esse post é bem mão na massa e se quiser aprofundar um pouco mais em conceitos teóricos de HATEOAS confira o nosso post Entendendo HATEOAS. Vamos tomar como base a aplicação desenvolvida no nosso outro post Documentando aplicações REST com SpringBoot e Swagger. Para começar você pode baixar o código deste post aqui e descompactar o arquivo zip e importar na sua IDE preferida ou clonar usando Git:


git clone https://github.com/leandrocgsi/simple-rest-example-swagger.git


Primeiro altere o pom.xml adicionando os trechos destacados por comentários abaixo.


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>br.com.erudio</groupId>
    <artifactId>simple-rest-example-hateoas</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.3.RELEASE</version>
    </parent>
    
    <dependencies>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        
        <!-- Adicione a dependencia de HATEOAS-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-hateoas</artifactId>
        </dependency>
        
        <dependency>
            <groupId>com.mangofactory</groupId>
            <artifactId>swagger-springmvc</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.ajar</groupId>
            <artifactId>swagger-spring-mvc-ui</artifactId>
            <version>0.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <scope>provided</scope>
        </dependency>
        
        <!-- Adicione as dependencias de teste -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.jayway.jsonpath</groupId>
            <artifactId>json-path</artifactId>
            <scope>test</scope>
        </dependency>        
        
    </dependencies>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    
    <repositories>
        <repository>
            <id>spring-releases</id>
            <url>https://repo.spring.io/libs-release</url>
        </repository>
        <repository>
            <id>jcenter-release</id>
            <name>jcenter</name>
            <url>http://oss.jfrog.org/artifactory/oss-release-local/</url>
        </repository>
    </repositories>
    
    <pluginRepositories>
        <pluginRepository>
            <id>spring-releases</id>
            <url>https://repo.spring.io/libs-release</url>
        </pluginRepository>
    </pluginRepositories>
    
</project>


Primeiro vamos alterar a classe Greeting que agora ira extender ResourceSupport.


package br.com.erudio.models;

import org.springframework.hateoas.ResourceSupport;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class Greeting extends ResourceSupport {

    private final long idGreeting;
    private final String content;

    @JsonCreator
    public Greeting(@JsonProperty("id") long id, @JsonProperty("content") String content) {
        this.idGreeting = id;
        this.content = content;
    }

    public long getIdGreeting() {
        return idGreeting;
    }

    public String getContent() {
        return content;
    }
}


Agora adicione os trechos comentados a classe GreetingController.


package br.com.erudio.web.controllers;

import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;

import java.util.concurrent.atomic.AtomicLong;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;

import br.com.erudio.models.Greeting;

@Api(value = "greeting")
@RestController
@RequestMapping("/greeting")
public class GreetingController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

	@ApiOperation(value = "Show Greeting Message" )
	@ResponseStatus(HttpStatus.OK)
    @RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public HttpEntity<Greeting> greeting(@RequestParam(value="name", defaultValue="World") String name) {
		Greeting greeting = new Greeting(counter.incrementAndGet(), String.format(template, name));
		
		// Na prática essa linha adiciona uma auto referência ao próprio endpoint
		// e apenas esse pequeno trecho de código já é o suficiente para que o endpoint 
		// greeting seja HATEOAS
		greeting.add(linkTo(methodOn(GreetingController.class).greeting(name)).withSelfRel());
        
		return new ResponseEntity<Greeting>(greeting, HttpStatus.OK);
    }
}


Se você iniciar a aplicação e acessar o endereço localhost:8080/greeting verá algo similar a imagem abaixo.

postagem_4_0


package br.com.erudio.models;

import java.io.Serializable;

import org.springframework.hateoas.ResourceSupport;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

// Adicione a anotação @JsonIgnoreProperties
@JsonIgnoreProperties(ignoreUnknown = true)

//Extenda ResourceSupport
public class Person extends ResourceSupport implements Serializable{
    
    private static final long serialVersionUID = 1L;
    
	// Por padrão implementação HATEOAS do Spring tem um atributo id
	// como default por isso o ID de nossa entidade deve ser alterado
    private Long idPerson;
    private String firstName;
    private String lastName;
    private String address;
    
    public Person() {}

	public Long getIdPerson() {
        return idPerson;
    }
    
    public void setIdPerson(Long id) {
        this.idPerson = id;
    }
    
    public String getFirstName() {
        return firstName;
    }
    
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    
    public String getLastName() {
        return lastName;
    }
    
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    
    public String getAddress() {
        return address;
    }
    
    public void setAddress(String address) {
        this.address = address;
    }
}


Agora vamos alterar a classe PersonController:


package br.com.erudio.web.controllers;
 
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
 
import java.util.ArrayList;
import java.util.List;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
 
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
 
import br.com.erudio.models.Person;
import br.com.erudio.services.PersonService;
 
@Api(value = "person")
@RestController
@RequestMapping("/person/")
public class PersonController {
     
    @Autowired
    private PersonService personService;
	@ApiOperation(value = "Find person by ID" )
    @ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = "/{personId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public Person get(@PathVariable(value = "personId") String personId){
        Person person = personService.findById(personId);
		
		//Adicione uma auto referencia ao método get do controller passando o ID como parâmetro
        person.add(linkTo(methodOn(PersonController.class).get(personId)).withSelfRel());
		return person;
    }
     
    .
    .
    .
     
}


Note que ao acessar esse recurso com uma ferramenta como o POSTman teremos uma resultado similar a imagem abaixo.


postagem_4_1


Agora vamos alterar o findAll:


package br.com.erudio.web.controllers;

import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;

import br.com.erudio.models.Person;
import br.com.erudio.services.PersonService;

@Api(value = "person")
@RestController
@RequestMapping("/person/")
public class PersonController {
	
	@Autowired
	private PersonService personService;
	
	.
	.
	.
	
	@ApiOperation(value = "Find all persons" )
	@ResponseStatus(HttpStatus.OK)
	@RequestMapping(value = "/findAll", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
	public List<Person> findAll(){
		List<Person> persons = personService.findAll();
		ArrayList<Person> personsReturn = new ArrayList<Person>();
		for (Person person : persons) {
			String idPerson = person.getIdPerson().toString();
			
			// Adicione uma referencia ao método get do controller passando o ID como parâmetro
			// isso é feito para todos os elementos da lista
			person.add(linkTo(methodOn(PersonController.class).get(idPerson)).withSelfRel());
			personsReturn.add(person);
		}
		return personsReturn;
	}
	
	.
	.
	.
	
}


A imagem abaixo nos mostra o resultado dessa mudança. A nossa lista nos tras referencias únicas para cada um dos recursos.


postagem_4_2


Agora vamos adicionar o suporte a HATEOAS ao verbo POST da nossa aplicação.


package br.com.erudio.web.controllers;

import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;

import br.com.erudio.models.Person;
import br.com.erudio.services.PersonService;

@Api(value = "person")
@RestController
@RequestMapping("/person/")
public class PersonController {
	
	@Autowired
	private PersonService personService;
	
	.
	.
	.
	
	@ApiOperation(value = "Create a new person" )
	@ResponseStatus(HttpStatus.OK)
	@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
	public Person create(@RequestBody Person person){
		Person createdPerson = personService.create(person);
		String idPerson = createdPerson.getIdPerson().toString();
		
		// Após criarmos um novo recurso do tipo Person nós recuperamos seu ID e adicionamos
		// uma referencia ao método get do controller passando o ID como parâmetro		
		createdPerson.add(linkTo(methodOn(PersonController.class).get(idPerson)).withSelfRel());
		return createdPerson;
	}
	
	.
	.
	.
	
}


Como se pode ver na imagem após salvar uma nova pessoa a aplicação retorna um link para que as informações da mesma possam ser acessadas.


postagem_4_3


Agora vamos modificar o verbo PUT.


package br.com.erudio.web.controllers;

import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;

import br.com.erudio.models.Person;
import br.com.erudio.services.PersonService;

@Api(value = "person")
@RestController
@RequestMapping("/person/")
public class PersonController {
	
	@Autowired
	private PersonService personService;
		
	.
	.
	.
	
	@ApiOperation(value = "Update an existing person")
	@ResponseStatus(HttpStatus.OK)
	@RequestMapping(method = RequestMethod.PUT,consumes = MediaType.APPLICATION_JSON_VALUE)
	public Person update(@RequestBody Person person){
		Person updatedPerson = personService.update(person);
		String idPerson = updatedPerson.getIdPerson().toString();
		
		// Após atualizarmos um recurso nós recuperamos seu ID e adicionamos
		// uma referencia ao método get do controller passando o ID como parâmetro		
		updatedPerson.add(linkTo(methodOn(PersonController.class).get(idPerson)).withSelfRel());		
		return updatedPerson;
	}
	
	.
	.
	.
	
}


Da mesma forma que com o verbo POST após atualizar uma pessoa a aplicação retorna um link para que as informações da mesma possam ser acessadas.


postagem_4_4


Como o verbo DELETE exclui um recurso não há necessidade de adicionar suporte a HATEOAS nele. Sendo assim fechamos a nossa implementação e podemos dizer que a nossa API é finalmente RESTful. Assim como nos posts anteriores você pode baixar o código deste post aqui e descompactar o arquivo zip e importar na sua IDE preferida ou clonar usando Git:

git clone https://github.com/leandrocgsi/simple-rest-example-hateoas.git


É isso aí bons estudos e continuem ligados no blog para mais novidades 😉


Tags: , , , , ,

Documentando aplicações REST com SpringBoot e Swagger



O Swagger é um dos frameworks mais usados para se documentar API’s REST. Ele facilita para que os clientes que consomem nossas API’s saibam quais os parâmetros nossas operações recebem, qual o retorno, o modelo, o media type retornado JSON, XML, CSV, binário etc. Sendo assim os clientes não precisam necessariamente discutir com a equipe de desenvolvimento da API sobre como usá-la. Pode-se dizer que a grosso modo o Swagger se comporta como o velho WSDL das aplicações SOAP. Sendo assim esse framework valoriza e muito nossas aplicações.


Tomando como base o projeto do post anterior vamos adicionar as configurações necessárias para habilitar o Swagger na aplicação. Para isso abra o arquivo pom.xml e adicione as tags destacadas com comentários no código abaixo.


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	
	<groupId>br.com.erudio</groupId>
	<artifactId>simple-rest-example-swagger</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.3.RELEASE</version>
    </parent>
    
    <dependencies>
    	
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
    	<!-- Adicionando a dependencia do Spring Boot Starter Actuator -->
    	<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		
		<!-- Adicione as dependências do Swagger API necessárias para gerar a documentação da aplicação-->
		<dependency>
			<groupId>com.mangofactory</groupId>
			<artifactId>swagger-springmvc</artifactId>
			<version>1.0.0</version>
		</dependency>
		<dependency>
			<groupId>org.ajar</groupId>
			<artifactId>swagger-spring-mvc-ui</artifactId>
			<version>0.4</version>
		</dependency>
		<dependency>
    		<groupId>org.apache.tomcat.embed</groupId>
    		<artifactId>tomcat-embed-jasper</artifactId>
    		<scope>provided</scope>
		</dependency>
		
    </dependencies>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    
    <repositories>
        <repository>
            <id>spring-releases</id>
            <url>https://repo.spring.io/libs-release</url>
        </repository>
   		
   		<!-- Adicione o repositório do Swagger ao projeto-->
		<repository>
			<id>jcenter-release</id>
			<name>jcenter</name>
			<url>http://oss.jfrog.org/artifactory/oss-release-local/</url>
		</repository>
    </repositories>
    
    <pluginRepositories>
        <pluginRepository>
            <id>spring-releases</id>
            <url>https://repo.spring.io/libs-release</url>
        </pluginRepository>
    </pluginRepositories>
	
</project>



Feito isto precisamos alterar a classe Application para que ela acione o Swagger quando inicializar a aplicação.


package br.com.erudio;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import com.mangofactory.swagger.configuration.SpringSwaggerConfig;
import com.mangofactory.swagger.models.dto.ApiInfo;
import com.mangofactory.swagger.plugin.EnableSwagger;
import com.mangofactory.swagger.plugin.SwaggerSpringMvcPlugin;

@Configuration // Define a classe como classe de configuração
@EnableAutoConfiguration // Habilita a autoconfiguração
@EnableSwagger //Habilita o Swagger
@ComponentScan(basePackages = {"br.com.erudio"}) //Escaneia todos os pacotes com o padrão br.com.erudio
public class Application {
    
	//Injeta uma instancia de SpringSwaggerConfig
    @Autowired
    private SpringSwaggerConfig swaggerConfig;
    
    public static void main(String[] args) {
		   //Troque esta linha SpringApplication.run(Application.class, args); pela linha abaixo
           new SpringApplicationBuilder(Application.class).web(true).run(args);
    }
    
    @Bean
    public SwaggerSpringMvcPlugin groupOnePlugin() {
       return new SwaggerSpringMvcPlugin(swaggerConfig)
			//Adiciona as configurações do Swagger ao SwaggerSpringMvcPlugin 
           .apiInfo(apiInfo()) //Adiciona as propriedades de configuração
           .includePatterns("/person.*?", "/greeting.*?") //Habilita o Swagger para os nossos 2 endpoints
           .swaggerGroup("admin");
    }
    
    private ApiInfo apiInfo() {
       ApiInfo apiInfo = new ApiInfo( //Configurações de contato, licença etc não nescessáriamente precisa ser definida
             "Swagger With Spring Boot",
             "This is a simple application to demonstrate how to work with Swagger in Spring Boot project!",
             "Free to use and mess around",
             "erudio@gmail.com",
             "Open Licence",
             "myemail@gmail.com"
       );
       return apiInfo;
    }
}



Agora que o Swagger já está configurado vamos documentar o endpoint Greeting.


package br.com.erudio.web.controllers;

import java.util.concurrent.atomic.AtomicLong;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;

import br.com.erudio.models.Greeting;

@Api(value = "greeting") //Diz ao Swagger que esse é um endpoint e REST deve ser documentado
@RestController
@RequestMapping("/greeting")
public class GreetingController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

	@ApiOperation(value = "Show Greeting Message" )
	 //Diz ao Swagger que essa operação REST deve ser documentado
	@ResponseStatus(HttpStatus.OK)
    @RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) {
        return new Greeting(counter.incrementAndGet(), String.format(template, name));
    }
}



Como se pode ver é extremamente simples documentar a nossa API agora vamos vazer o mesmo com o endpoint Person.


package br.com.erudio.web.controllers;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;

import br.com.erudio.models.Person;
import br.com.erudio.services.PersonService;


@Api(value = "person") //Diz ao Swagger que esse é um endpoint e REST deve ser documentado
@RestController
@RequestMapping("/person/")
public class PersonController {
	
	@Autowired
	private PersonService personService;
	
	@ApiOperation(value = "Find person by ID" )
	//Diz ao Swagger que essa operação REST deve ser documentado
    @ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = "/{personId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public Person get(@PathVariable(value = "personId") String personId){
        return personService.findById(personId);
    }
	
	@ApiOperation(value = "Find all persons" )
	//Diz ao Swagger que essa operação REST deve ser documentado
	@ResponseStatus(HttpStatus.OK)
	@RequestMapping(value = "/findAll", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
	public List<Person> findAll(){
		return personService.findAll();
	}
	
	@ApiOperation(value = "Create a new person" )
	//Diz ao Swagger que essa operação REST deve ser documentado
	@ResponseStatus(HttpStatus.OK)
	@RequestMapping(method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
	public Person create(@RequestBody Person person){
		return personService.create(person);
	}
	
	@ApiOperation(value = "Update an existing person")
	//Diz ao Swagger que essa operação REST deve ser documentado
	@ResponseStatus(HttpStatus.OK)
	@RequestMapping(method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_VALUE)
	public Person update(@RequestBody Person person){
		return personService.update(person);
	}

	@ApiOperation(value = "Delete person by ID" )
	//Diz ao Swagger que essa operação REST deve ser documentado
	@ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = "/{personId}", method = RequestMethod.DELETE)
    public void delete(@PathVariable(value = "personId") String personId){
        personService.delete(personId);
    }	
}



Não parece mas já terminamos toda a codificação necessária por adicionar o Swagger à nossa API mais uma vez acesse a classe Application e inicie a aplicação como no post anterior. Após inicializada a aplicação acesse a URL:


	localhost:8080/sdoc.jsp



Essa é a URL padrão da documentação e nunca tentei alterá-la. Ao acessá-la você verá algo similar a imagem abaixo documentando cada uma das operações dos nossos endpoints. Bastando clicar sobre cada uma para expandir e ver todos os detalhes da mesma.



postagem_3_1



Na imagem abaixo podemos ver a documentação da operação findAll. Temos a definição do modelo que ela nos retorna, o tipo de dados que ela retorna no caso JSON, os StatusCode que ela pode retornar, se clicarmos em Try Out o Swagger nos permite testar nossas operações. Ao executarmos esse teste a nossa API nos retornou um array de pessoas, o cabeçalho e o StatusCode 200 OK.



postagem_3_5


Chegamos com este post ao final da série de posts, práticos, sobre serviços REST. Você pode baixar o código deste post aqui e descompactar o arquivo zip e importar na sua IDE preferida ou clonar usando Git:

git clone https://github.com/leandrocgsi/simple-rest-example-swagger.git



Agora você já consegue dar os primeiros passos na criação de serviços REST, conhece conceitos, teóricos e práticos, básicos para executar esse tipo de tarefa. Sendo assim continue ligado no blog, por que no próximos posts iremos detonar o Rock’n Roll com outras tecnologias. É isso aí bons estudos.

Tags: , , , , ,

Do zero ao REST em 5 minutos com SpringBoot



Este post visa explicar de forma simples como criar um “hello world” RESTFul web service com Spring Boot.



Fique ligado no blog, por que, como já foi dito, nos próximos 2 posts entraremos em maiores detalhes sobre a sopa de letrinhas dos verbos REST, POST, PUT, GET e DELETE na prática e depois documentaremos a nossa API com o framewrok Swagger. E abordagem nesses posts será totalmente mão na massa. É isso aí bons estudos.

Cerca de 5 minutos
Qualquer IDE de preferência o Eclipse
JDK 1.8 ou superior
Maven 3.33+



Onde baixar os códigos do projeto

Você pode baixar o código aqui e descompactar o arquivo zip e importar não sua IDE de preferencia ou clonar usando Git:

git clone https://github.com/leandrocgsi/simple-rest-example.git



Para mais detalhes e para evoluir este projeto acesse a página de guias de inicialização da fundação Spring. Além disso serão feitos mais 2 posts fechando uma série sobre Spring Boot e RESTful abordando os 4 principais verbos REST e como documentar API’s com o framework Swagger. O código dos próximos posts já está implementado e você pode acessar o de verbos aqui e o com Swagger aqui.



E a teoria como fica?


Se você está lendo este post eu acredito que você conheça o mínimo de teoria sobre REST e Web-Services mas se não conhece temos 3 posts que abordam esses temas de forma teórica sendo um sobre Web Services, outro sobre RESTful Web Services e outro sobre os HTTP Status Codes em Serviços REST mais comuns.

Hora de codar



Então chega de conversa e vamos botar a mão na massa ou melhor no código. Com o Eclipse aberto clique em novo escolha a opção Maven Project como na imagem abaixo.

1



Na próxima janela selecione a opção “Create a simple project(skyp archetype selection)”. Isso “diz” ao Maven que você irá construir seu projeto do zero com uma estrutura padrão Maven mas sem usar nenhum Archetype pronto.

2



Na próxima tela defina o Goup Id do seu projeto, no nosso caso “br.com.erudio”. Defina também o Artifact Id (nome) do seu projeto e a versão. Feito isto clique em next.

3



Se tudo tiver corrido bem você terá um projeto com uma estrutura similar à imagem abaixo. Abra o arquivo “pom.xml” e vamos fazer algumas alterações nele.

4



A estrutura original do pom deve ser algo similar a esta:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>br.com.erudio</groupId>
    <artifactId>simple-rest-example</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    
</project>



Primeiro informamos o “parentesco” do nosso projeto em relação ao Spring boot. Logo abaixo adicionamos a dependência do Spring Boot Starter Web que como o próprio nome diz é o responsável por inicializar nossa aplicação. Definimos também a versão do Java no nosso caso 1.8. Depois precisamos configurar o processo de build que é extremamente simples. E por fim adicionamos os repositórios de onde o Maven irá baixar as dependências e plug-ins necessários ao projeto. Feito isso nos já temos a estrutura básica de um projeto Spring Boot.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>br.com.erudio</groupId>
    <artifactId>simple-rest-example</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    
    <!-- Adicionando o Spring Boot ao projeto -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.3.RELEASE</version>
    </parent>
    
    <!-- Adicionando a dependencia do Spring Boot Starter Web -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <!-- Configurando a versão do Java -->
    <properties>
        <java.version>1.8</java.version>
    </properties>
    
    <!-- Configurando o processo de build da aplicação -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    
    <!-- Adicionando o repositório do Spring de onde o Maven irá baixar as dependências -->
    <repositories>
        <repository>
            <id>spring-releases</id>
            <url>https://repo.spring.io/libs-release</url>
        </repository>
    </repositories>
    
    <!-- Adicionando o repositório do Spring de onde o Maven irá baixar os plugins -->
    <pluginRepositories>
        <pluginRepository>
            <id>spring-releases</id>
            <url>https://repo.spring.io/libs-release</url>
        </pluginRepository>
    </pluginRepositories>
    
</project>



Como se pode ver o nosso projeto está com um marker de erro e a versão do Java está como 1.5 e não 1.8 como definimos no pom.xml.

7



Clique com o direito sobre o projeto escola a opção Build Path >> Configure Build Path

8



Na aba libraries selecione sua JRE System Library e clique em editar.

9



Na proxima janela selecione o radio Alternate JRE e escolha sua versão do Java e clique em Finish.

10



Como se pode ver agora a versão esta correta, então clique em OK.

11



Além disso temos um Mavem problem etratanto isso é apenas um bug do Eclipse e apesar do warning o projeto executa normalmente. Para remover basta escolher a opção quick fix.

12



Na janela a seguir escolha a opção Update project configuration clique em Finish e adeus warning.

13



Agora que eliminamos todos os warnings o ambiente está pronto. Selecione o source folder src/main/java.

14



Clique com o direito New >> Package

15



Na próxima janela defina o nome do pacote no nosso caso “br.com.erudio”.

16



Feito isso abra o souce folder e clicando sobre o pacote com o botão direito New >> Class

17



Na próxima janela defina o nome Greeting(Saudação em inglês já que é um Hello World) e insira o código abaixo. Como você pode perceber é um simples POJO que representa o objeto que será retornado aos clientes de nossa API.


package br.com.erudio;

public class Greeting {

    private final long id;
    private final String content;

    public Greeting(long id, String content) {
        this.id = id;
        this.content = content;
    }

    public long getId() {
        return id;
    }

    public String getContent() {
        return content;
    }
}



Agora crie uma nova classe com o nome GreetingController que é o nosso endpoit que receberá as requisições REST. Como se pode ver as requisições para a url {{contexto}}/greeting invocarão o método greeting que recebe um @RequestParam com um nome. Quando esse valor não é informado o valor padrão é “World”. As requisições para esse endpoint retornam uma saudação com um id automático simulando um acesso a um banco de dados e uma string com a saudação.


package br.com.erudio;

import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

    @RequestMapping("/greeting")
    public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) {
        return new Greeting(counter.incrementAndGet(), String.format(template, name));
    }
}



Agora vamos definir a classe de inicialização de nossa aplicação chamada Application. Acredite ou não com apenas o trecho de código abaixo você tem sua aplicação pronta sem necessidade de container ou server. Sim o Spring Boot te liberta de Tomcat, Jetty ou os “obesos” JBoss e GlassFish e seus EJB’s.


package br.com.erudio;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

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



Com a aplicação pronta clique com o direito dobre a classe Application Run As >> Java Application. Caso você esteja usando a Spring Source Tool Suite (ferramenta baseada no Eclipse com foco em desenvolvimento Spring) como é o meu caso pode excolher a opção Spring Boot App.

18



Se você tiver feito tudo corretamente terá um console parecido com a imagem abaixo observe que o endpoint /greeting foi mapeado e que nossa aplicação iniciou em apenas 4 segundos.

19



Vá no browser de sua preferencia e acesse localhost:8080/greeting e terá uma resposta parecida com a imagem abaixo.

20



Agora adicione um parametro a mais a nossa url localhost:8080/greeting?name=Olá Semeru Blog ou outro parametro de sua preferência e terá uma resposta similar à imagem abaixo.

21



Fique ligado no blog, por que, como já foi dito, nos próximos 2 posts entraremos em maiores detalhes sobre a sopa de letrinhas dos verbos REST, POST, PUT, GET e DELETE na prática e depois documentaremos a nossa API com o framewrok Swagger. E abordagem nesses posts será totalmente mão na massa. É isso aí bons estudos.

Tags: , ,

Usando código Groovy (o Java com esteróides) juntamente com código Java em um projeto com Spring Boot

Mais um post em que explico como integrar código Groovy junto ao seu código Java em um projeto com Spring Boot usando o gerenciador de dependencias Maven. No outro post usamos o ‘Groovy Eclipse Compiler Plugin‘ mas nunca consegui fazer ele funcionar corretamente com o Spring Boot então o substituimos pelo ‘GMaven Plugin‘. Além disso o ‘Groovy Eclipse Compiler Plugin‘ tem problemas de backward compatibility com o Java 8 diferentemente do ‘GMaven Plugin‘.
Então mãos a obra, adicione as configurações abaixo ao seu pom.xml e tenha todo poder do Groovy junto ao seu código Java.

	
	<!-- Adicione o Groovy às dependências do seu projeto -->
	<dependencies>
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <scope>compile</scope>
        </dependency>
	</dependencies>		
     
        .
        .
        .       
     
	<!-- Será necessário fazer algumas mudanças no seu processo de build --> 		
	<build>
		<resources>
			<resource>
				<directory>${basedir}/src/main/resources</directory>
			</resource>
		</resources>
		
		<!-- Adicione o GMaven Plugin -->
		<plugins>
			<plugin>
				<groupId>org.codehaus.gmaven</groupId>
				<artifactId>gmaven-plugin</artifactId>
				<version>1.5</version>
				<configuration>
					<providerSelection>2.0</providerSelection>
				</configuration>
				
				<!-- Adicione as dependencias 'gmaven-runtime-2.0' e 'groovy-all' ao plugin -->
				<dependencies>
					<dependency>
						<groupId>org.codehaus.gmaven.runtime</groupId>
						<artifactId>gmaven-runtime-2.0</artifactId>
						<version>1.5</version>
					</dependency>
					<dependency>
						<groupId>org.codehaus.groovy</groupId>
						<artifactId>groovy-all</artifactId>
						<version>2.1.8</version>
					</dependency>
				</dependencies>
				
				<!-- Defina suas metas de execução -->
				<executions>
					<execution>
						<goals>
							<goal>generateStubs</goal>
							<goal>compile</goal>
							<goal>generateTestStubs</goal>
							<goal>testCompile</goal>
						</goals>
					</execution>
				</executions>
			</plugin>

			<!-- Adicione o plugin do 'spring-boot-maven-plugin' -->			
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			
		</plugins>
	</build>

Caso você tenha dúvidas poderá se basear em um projeto completo no Github o Erudio API OAUTH2 utilizando essas tecnologias juntas. Lets Groovy guys, bons estudos.

Tags: , , , ,

Resolvendo problemas de configuração do SpringMVC

Salve, salve pessoal se você está trabalhando com Spring MVC e se deparou com a exception org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation este artigo visa ajudar a resolver este problema.
Isso se deve ao fato do HttpMessageConverter não estar configurado ou configurado com erros. A solução é editar sua classe de configurações WebMvcConfig adicionando dois converters ResourceHttpMessageConverter e MappingJackson2HttpMessageConverter. Isso é bastante simples e basta que você adicione o trecho de código abaixo:


    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    	converters.add(converterResourceHttpMessageConverter());
        converters.add(converterJackson2Http());
        super.configureMessageConverters(converters);
    }
    
    @Bean
    public MappingJackson2HttpMessageConverter converterJackson2Http() {
    	MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    	//do your customizations here...
    	return converter;
    }
    
    @Bean
    public ResourceHttpMessageConverter converterResourceHttpMessageConverter() {
    	ResourceHttpMessageConverter converter = new ResourceHttpMessageConverter();
    	//do your customizations here...
    	return converter;
    }

Bom mas pode ser que você se depare ainda com a exception java.lang.ClassNotFoundException: org.codehaus.jackson.JsonProcessingException. E a solução também é simples, certifique se de que as dependências jackson-core-asl, jackson-mapper-asl e jackson-jaxrs-xml-provider estejam adicionadas ao projeto, caso não estejam adicionem. Para quem usa Maven eu vou facilitar ainda mais as coisas, basta adicionar esse trecho de código ao seu pom.xml e ser feliz, para os demais é só sair catando jar na pata.


	<dependency>
		<groupId>org.codehaus.jackson</groupId>
		<artifactId>jackson-core-asl</artifactId>
		<version>XYZ</version>
	</dependency>
	<dependency>
		<groupId>org.codehaus.jackson</groupId>
		<artifactId>jackson-mapper-asl</artifactId>
		<version>XYZ</version>
	</dependency>
	<dependency>
		<groupId>com.fasterxml.jackson.jaxrs</groupId>
		<artifactId>jackson-jaxrs-xml-provider</artifactId>
		<version>XYZ</version>
	</dependency>

Feito isto é só inicializar novamente o projeto que as coisas irão funcionar.

Tags: , , ,