Skip to main content

Kotlin



Introdução a API - Interface de Programação de Aplicações


API é a sigla para Application Programming Interface. É um conjunto de regras, protocolos e ferramentas que permite que diferentes softwares se comuniquem entre si, permitindo a troca de dados e a realização de operações específicas. Em termos simples, uma API define como os componentes de software devem interagir entre si.


Ela fornece um conjunto de métodos padronizados que um desenvolvedor pode usar para acessar os recursos ou funcionalidades de um sistema ou serviço, sem precisar entender todos os detalhes internos de sua implementação. Isso facilita a integração de sistemas e permite que desenvolvedores criem novas aplicações que se beneficiem dos recursos de outras plataformas ou serviços.


As APIs são essenciais para a construção de sistemas complexos e para a integração de diferentes tecnologias. Elas são amplamente utilizadas em diversas áreas, como desenvolvimento web, aplicativos móveis, computação em nuvem, Internet das Coisas (IoT), entre outras.


Normalmente todas as respostas são em JSON, não necessitando de interfaces desenvolvidas no front para usar elas. Com o NodeJS, podemos usar o Express para criar uma API.



REST


APIs REST (Representational State Transfer) e RESTful são abordagens para projetar e desenvolver interfaces de programação web que seguem os princípios do estilo arquitetural REST. O REST é um estilo arquitetural para projetar sistemas de software distribuídos, especialmente sistemas de hipermídia, como a World Wide Web. Ele enfatiza a escalabilidade, a simplicidade e a independência de componentes, o que o torna uma abordagem popular para o desenvolvimento de APIs web.


APIs REST são baseadas em quatro conceitos principais:

  1. Utilização dos métodos HTTP, como GET, POST, PUT e DELETE, para realizar operações em recursos.

  2. Uso de URLs (Uniform Resource Locators) para identificar recursos específicos.

  3. Transferência de dados entre cliente e servidor em um formato padrão, geralmente JSON.

  4. Manutenção do estado da aplicação no cliente, em vez de armazená-lo no servidor.


Já o RESTful é um termo usado para descrever sistemas ou serviços que seguem os princípios do REST. Um serviço RESTful é aquele que adere aos princípios de design do REST, incluindo a utilização de métodos HTTP de forma consistente, identificação de recursos por URIs e a utilização de representações de estado. Em resumo, REST é um estilo arquitetural para sistemas distribuídos, enquanto RESTful descreve sistemas ou serviços que adotam esse estilo, seguindo os princípios definidos pelo REST. APIs RESTful são comumente usadas para construir sistemas web que são escaláveis, flexíveis e fáceis de entender e manter.



Métodos HTTP


Os métodos HTTP, também conhecidos como verbos HTTP, são comandos que indicam a ação que está sendo solicitada para ser realizada em um recurso específico em um servidor. Eles são usados em solicitações HTTP para indicar a natureza da operação que está sendo realizada no recurso identificado pela URL. Os principais verbos HTTP incluem:

  1. GET: Solicita a representação de um recurso específico. É usado para recuperar dados do servidor. Por exemplo, ao digitar uma URL no navegador, uma solicitação GET é enviada para recuperar a página web correspondente.

  2. POST: Envia dados para o servidor para criar um novo recurso. É comumente usado para enviar dados de formulário para o servidor ou para enviar dados para serem processados e armazenados.

  3. PUT: Atualiza um recurso existente no servidor com os dados fornecidos. Geralmente, é usado para atualizar completamente um recurso.

  4. PATCH: Atualiza parcialmente um recurso existente no servidor. Ele envia apenas os dados que precisam ser alterados, em vez de enviar todos os dados do recurso.

  5. DELETE: Remove um recurso específico do servidor. É usado para excluir recursos existentes.

  6. HEAD: Solicita apenas os cabeçalhos de resposta de um recurso, sem a carga útil de dados. É útil para verificar a existência de um recurso e obter informações sobre ele sem baixar todo o conteúdo.

  7. OPTIONS: Solicita informações sobre as opções de comunicação disponíveis para um recurso, como os métodos HTTP suportados ou os cabeçalhos aceitos.

Esses são os principais verbos HTTP, cada um com uma função específica na comunicação entre clientes e servidores web. Eles permitem uma variedade de operações para recuperar, criar, atualizar e excluir recursos em servidores web, formando a base da arquitetura RESTful comumente usada na web moderna.



Postman


O Postman é uma ferramenta usada no desenvolvimento de APIs. Ele oferece recursos que nos permite criar, testar e documentar APIs de maneira eficiente, mas o padrão de uso é mais no teste de API.


Para instalar ele execute os passos abaixo, os dados foram retirados do github do @nunesdaniel.

Terminal
# Baixe o código fonte do postman:
wget https://dl.pstmn.io/download/latest/linux_64 -O postman.tar.gz

# Extraia o conteúdo do arquivo zipado:
sudo tar -xzf postman.tar.gz -C /opt

# Crie um link simbólico para colocar o executável do postman no path do linux:
sudo ln -s /opt/Postman/Postman /usr/bin/postman

# Agora crie um ícone de desktop para o executável do postman:
cat > ~/.local/share/applications/postman.desktop <<EOL
[Desktop Entry]
Encoding=UTF-8
Name=Postman
Exec=postman
Icon=/opt/Postman/app/resources/app/assets/icon.png
Terminal=false
Type=Application
Categories=Development;
EOL


Introdução a MVC - Model View Controller


A arquitetura MVC (Model-View-Controller) é um padrão de design de software que é amplamente utilizado para desenvolver aplicativos web, para usar basta separar os arquivos em diretórios com os nomes dos componentes que serão explicados mais abaixo. Ela é composta por três componentes principais:


Model: O modelo representa a camada de dados do aplicativo. Ele lida com a manipulação de dados, como a interação com um banco de dados ou outros recursos externos. O modelo contém as regras de negócio e a lógica para manipular os dados.


View: A visão é responsável por exibir a interface do usuário. Ela renderiza a interface do aplicativo e apresenta os dados fornecidos pelo modelo. A visão não contém lógica de negócios, mas é responsável por exibir os dados de maneira agradável para o usuário.


Controller: O controlador é responsável por receber as solicitações do usuário, processá-las e coordenar a interação entre o modelo e a visão. Ele recebe os dados da solicitação, interage com o modelo para obter os dados necessários e, em seguida, determina qual visão deve ser renderizada para exibir a resposta ao usuário.


Estrutura com MVC:

  • controller
    Diretório onde ficam os arquivos de controle.

  • model
    Diretórios onde ficam os arquivos de Models, interação com banco de dados.

  • view
    Diretórios onde ficam os arquivos de View (Handlebars).


Exemplos usados nos códigos abaixo

Os códigos usados nos códigos abaixo são bem simples e servem apenas para demonstração, visto que não teremos nenhuma comunicação com banco de dados nessa etapa.



Controllers


No contexto específico do desenvolvimento web com Kotlin, os Controllers são classes que, recebem requisições HTTP e as encaminham para o tratamento adequado dentro do aplicativo e, por fim, enviar uma resposta de volta ao cliente que fez a requisição. Eles são tipicamente utilizados em frameworks como Spring Boot, que facilitam a criação de APIs RESTful.


Em termos gerais, controllers se referem a componentes que gerenciam o fluxo de dados e a interação entre a camada de visualização e a camada de modelo em arquiteturas como MVC e MVVM.


Você pode pensar no controller como um garçom em um restaurante. Um garçom recebe pedidos dos clientes e encaminha-os para a cozinha, depois do pedido ter sido processado, o garçom entrega os pratos prontos de volta aos clientes. Perceber que o garçom não prepara o pedido, ele apenas redireciona a solicitação para quem vai tratar aquele pedido.


Já o controller, vai recebe requisições dos clientes, as encaminha para quem vai tratar a solicitação e, por fim, retorna as respostas aos clientes. O Controller assim como o garçom pode acabar fazendo uma tarefa ou outra, mas ele não toma nenhuma decisão da regra de negócio, normalmente são coisas simples.



Criando o Controller


Em um projeto Kotlin que utiliza um framework web como o Spring Boot, a estrutura de diretórios pode variar de acordo com as convenções adotadas pela equipe de desenvolvimento, mas note que normalmente a organização dos controllers segue da seguinte forma:

meu-projeto/
├── src/
│ ├── main/
│ │ ├── kotlin/
│ │ │ ├── meu/
│ │ │ │ ├── pacote/
│ │ │ │ │ ├── controllers/ <- Diretório dos controllers
│ │ │ │ │ │ ├── MeuController.kt <- Exemplo de um controller
│ │ │ │ │ │ ├── OutroController.kt
│ │ │ │ │ │ └── ...

Em frameworks como o Spring Boot em Kotlin, é tipicamente utilizado anotações para indicar que uma classe é um controller. No caso do Spring Boot, é usado @RestController ou @Controller na sua classe de controller para indicar que aquela classe é um controller. Segue um exemplo:

package meu.pacote.controller

import org.springframework.web.bind.annotation.*
//import org.springframework.web.bind.annotation.GetMapping
//import org.springframework.web.bind.annotation.RequestMapping
//import org.springframework.web.bind.annotation.RestController

@RestController // Por padrão referente a raiz '/'.
//RequestMapping("path") - define uma Subpages (rota com prefixo padrão).
class MeuController {

@GetMapping("/recurso")
fun obterRecurso(): String {
return "Conteúdo do recurso"
}

@GetMapping
fun Cliente(): String {
return "Customer 1"
}

}

  • A classe MeuController é marcada com a anotação @RestController, indicando que esta classe é um controller responsável por lidar com requisições HTTP.

  • O método obterRecurso() é mapeado para a rota /recurso usando a anotação @GetMapping("/recurso"). Quando esta rota é acessada via método GET, este método é chamado e retorna "Conteúdo do recurso".

  • O método Cliente() é mapeado para a raiz do caminho, que é /, usando a anotação @GetMapping. Quando a raiz é acessada via método GET, este método é chamado e retorna "Customer 1".


Além disso, a linha package meu.pacote.controller é uma declaração de pacote (package declaration). Ela define o pacote ao qual a classe pertence.



Criando o Model


Vamos criar o model da seguinte forma:

meu-projeto/
├── src/
│ ├── main/
│ │ ├── kotlin/
│ │ │ ├── meu/
│ │ │ │ ├── pacote/
│ │ │ │ │ ├── controller/ <- Diretório dos controllers
│ │ │ │ │ │ ├── MeuController.kt <- Exemplo de um controller
│ │ │ │ │ │ ├── OutroController.kt
│ │ │ │ │ │ └── ...
│ │ │ │ │ ├── model/ <- Diretório dos models
│ │ │ │ │ │ ├── MeuModel.kt <- Exemplo de um model

O Model é um modelo, inicialmente criaremos um modelo simples:

src/main/kotlin/meu/pacote/model/CustomerModel.kt
package meu.pacote.model

data class CustomerModel(
var id: String,
var name: String,
var email: String
)

Agora vamos usar ele no controller:

src/main/kotlin/meu/pacote/controller/CustomerController.kt
package meu.pacote.controller

import meu.pacote.model.CustomerModel
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("customer")
class CustomerController {

@GetMapping
fun getCustomer(): CustomerModel {
return CustomerModel("1000", "Eduard", "joao@selvik.net")
}

}



Implementando o Post


Vamos ver como implementar o Post:

src/main/kotlin/meu/pacote/controller/request/PostCustomerRequest.kt
package meu.pacote.controller.request

data class PostCustomerRequest (
var name: String,
var email: String
)

Agora vamos no controller implementar o uso do request:

src/main/kotlin/meu/pacote/controller/CustomerController.kt
package meu.pacote.controller

import meu.pacote.controller.request.PostCustomerRequest
import meu.pacote.model.CustomerModel
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("customer")
class CustomerController {

val customers = mutableListOf<CustomerModel>() // Vamos salvar todo conteúdo do Post nessa lista.

@GetMapping
fun getCustomer(): List<CustomerModel> {
return customers
}

@PostMapping // Define que o verbo do HTTP será Post.
@ResponseStatus(HttpStatus.CREATED) // Muda o status do http para o método Post, no caso, ele vai retornar 201.
fun create(@RequestBody customer: PostCustomerRequest) {
val id = if(customers.isEmpty()) { // Se a lista 'costumer' estiver vazia
1 // Retorna 1
} else{
customers.last().id.toInt() + 1 // Se não, retorna o campo 'id' da lista convertido em INT somando + 1.
}.toString() // O valor salvo na variável 'id' é convertido para string.
customers.add(CustomerModel(id, customer.name, customer.email)) // A lista customers adiciona valores usando 'CustomerModel' como template.
}
}

O @RequestBody é uma anotação usada em aplicativos Spring Boot para indicar que um parâmetro de método deve ser extraído do corpo (body) da requisição HTTP. No contexto do Spring Boot, quando um endpoint é acionado, os dados enviados na requisição podem ser mapeados para parâmetros do método. A anotação @RequestBody diz ao Spring Boot para mapear o corpo da requisição diretamente para um objeto Java ou Kotlin. Isso é comum ao lidar com dados enviados no formato JSON em requisições POST ou PUT.


O customer é o nome do parâmetro do método create. Neste contexto, ele representa o objeto que será extraído do corpo da requisição e mapeado para um objeto Kotlin. O nome customer é arbitrário e pode ser qualquer nome válido em Kotlin. No entanto, é uma convenção usar nomes descritivos que reflitam o tipo de dados que está sendo recebido.


O PostCustomerRequest é a classe que criamos, ela representa a estrutura dos dados esperados no corpo da requisição HTTP POST. Normalmente, isso é usado para desserializar automaticamente os dados JSON enviados no corpo da requisição em um objeto Kotlin.


Dentro do método create, o código simplesmente imprime o objeto customer recebido no console (println(customer)).



Implementando o envio de variáveis por URL


Vamos ver como criar uma rota /id onde o ID deve existir e será retornado para o cliente via método Get.

src/main/kotlin/meu/pacote/controller/CustomerController.kt
package meu.pacote.controller

import meu.pacote.controller.request.PostCustomerRequest
import meu.pacote.model.CustomerModel
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("customer")
class CustomerController {

val customers = mutableListOf<CustomerModel>() // Vamos salvar todo conteúdo do Post nessa lista.

@GetMapping
fun getAll(): List<CustomerModel> {
return customers
}

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
fun create(@RequestBody customer: PostCustomerRequest) {
val id = if(customers.isEmpty()) {
1
} else{
customers.last().id.toInt() + 1
}.toString()

customers.add(CustomerModel(id, customer.name, customer.email))
}

@GetMapping("/{id}")
fun getCustomer(@PathVariable id: String): CustomerModel {
return customers.filter { it.id == id }.first()

}
}

A anotação @GetMapping("/{id}") indica que esta função será chamada quando uma requisição GET for feita para um endpoint que espera um parâmetro na URL, especificamente um parâmetro chamado id, esse ID possui chaves {}, isso indica que o valor desse parâmetro id será extraído da própria URL.

Pode pensar que /{id} é uma variável que será obtida pela URL.


A anotação @PathVariable id: String indica que o parâmetro id do método getCustomer será extraído da URL. O Spring Boot automaticamente associa o valor do parâmetro na URL ao parâmetro id do método, porque eles compartilham o mesmo nome.


A expressão customers.filter { it.id == id }.first() faz uma busca na lista de clientes (customers) filtrando os elementos cujo id corresponde ao id passado na URL. O método filter retorna uma lista de todos os elementos que satisfazem o critério de filtro, e first() retorna o primeiro elemento dessa lista.


Essa função retorna um objeto do tipo CustomerModel. Usar uma função cujo tipo de retorno é uma classe, como em fun getCustomer(@PathVariable id: String): CustomerModel {, é comum em aplicativos web construídos com frameworks como o Spring Boot. Isso é especialmente útil em endpoints de API RESTful, onde os dados precisam ser enviados de volta ao cliente em um formato estruturado, como JSON.



Implementando o update via PUT


Vamos ver como usar o PUT para atualizar dados. Primeiro crie uma requisição para o PUT, ela será igual ao PutCustomerRequest, mas será um outro template para termos mais liberdade.

src/main/kotlin/meu/pacote/controller/request/PutCustomerRequest.kt
package meu.pacote.controller.request

data class PutCustomerRequest (
var name: String,

var email: String
)

Agora vamos corrigir o Controller:

src/main/kotlin/meu/pacote/controller/CustomerController.kt
package meu.pacote.controller

import meu.pacote.controller.request.PostCustomerRequest
import meu.pacote.controller.request.PutCustomerRequest
import meu.pacote.model.CustomerModel
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("customer")
class CustomerController {

val customers = mutableListOf<CustomerModel>() // Vamos salvar todo conteúdo do Post nessa lista.

@GetMapping
fun getAll(): List<CustomerModel> {
return customers
}

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
fun create(@RequestBody customer: PostCustomerRequest) {
val id = if(customers.isEmpty()) {
1
} else{
customers.last().id.toInt() + 1
}.toString()

customers.add(CustomerModel(id, customer.name, customer.email))
}

@GetMapping("/{id}")
fun getCustomer(@PathVariable id: String): CustomerModel {
return customers.filter { it.id == id }.first()
}

@PutMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT) // Não retorna nada
fun update(@PathVariable id: String, @RequestBody customer: PutCustomerRequest) {
customers.filter { it.id == id }.first().let {
it.name = customer.name
it.email = customer.email
}
}

}

Sobre a linha update(@PathVariable id: String, @RequestBody customer: PutCustomerRequest), veja a explicação abaixo.


O @PathVariable id: String indica que o método espera receber um parâmetro chamado id na URL.


O @RequestBody customer: PutCustomerRequest indica que o método espera receber um corpo (body) na requisição HTTP, que será mapeado para o parâmetro customer.

O @RequestBody é usado para mapear o corpo da requisição HTTP para um objeto Java ou Kotlin.

PutCustomerRequest é o tipo esperado do corpo da requisição, é a classe que contém os dados que serão usados para atualizar as informações do cliente.



Implementando o query params


O Query params são aos elementos opcionais de uma URL que são usados para transmitir informações entre uma página da web e seu servidor. Eles aparecem após o ponto de interrogação (?) na URL e são compostos por pares chave-valor, separados por &. Por exemplo, considere a seguinte URL:

https://www.exemplo.com/pagina?nome=usuario&idade=25

Neste exemplo, nome e idade são os query params, e seus valores são "usuario" e "25", respectivamente. Os query params podem ser usados para passar informações como filtros de pesquisa, identificadores de sessão, tokens de autenticação e outras informações relevantes para a interação entre o cliente (navegador) e o servidor web.


Vamos implementer um query param como sendo opcional no nosso código:

src/main/kotlin/meu/pacote/controller/CustomerController.kt
package meu.pacote.controller

import meu.pacote.controller.request.PostCustomerRequest
import meu.pacote.controller.request.PutCustomerRequest
import meu.pacote.model.CustomerModel
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("customer")
class CustomerController {

val customers = mutableListOf<CustomerModel>() // Vamos salvar todo conteúdo do Post nessa lista.

@GetMapping
fun getAll(@RequestParam name: String?): List<CustomerModel> {
name?.let {
return customers.filter { it.name.contains(name, true) }
}
return customers
}

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
fun create(@RequestBody customer: PostCustomerRequest) {
val id = if(customers.isEmpty()) {
1
} else{
customers.last().id.toInt() + 1
}.toString()

customers.add(CustomerModel(id, customer.name, customer.email))
}

@GetMapping("/{id}")
fun getCustomer(@PathVariable id: String): CustomerModel {
return customers.filter { it.id == id }.first()
}

@PutMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
fun update(@PathVariable id: String, @RequestBody customer: PutCustomerRequest) {
customers.filter { it.id == id }.first().let {
it.name = customer.name
it.email = customer.email
}
}

}

No trecho @RequestParam name: String? estamos criando uma query param que recebe o argumento name do tipo String, esse argumento é opcional (pode ser declarado ou não), graças ao ?.


Em name?.let { informa que name pode receber um valor ou pode não receber (graças ao ?), caso ele receba, um trecho de código será executado (por isso usamos .let {). Já em return customers.filter { it.name.contains(name, true) } estamos verificando se o nome de cada cliente (acessado através de it.name) contém a string name.


O segundo argumento (true) é usado que a comparação seja feita de forma não sensível a maiúsculas e minúsculas, ou seja, independentemente de o texto estar em maiúsculas ou minúsculas, será considerado um match.



Data classes


Em Kotlin, uma data class é uma classe especial que é projetada principalmente para armazenar dados. Elas são frequentemente usadas para representar entidades de dados simples que contêm principalmente propriedades e não têm muita lógica de negócios associada a elas. Algumas características das data classes incluem:

  1. Geração automática de métodos: O compilador Kotlin automaticamente gera métodos como equals(), hashCode(), toString(), componentN() e copy() com base nas propriedades declaradas na classe.

  2. Imutabilidade por padrão: As propriedades declaradas em uma data class são geralmente imutáveis por padrão, embora isso possa ser alterado se necessário.

  3. Desestruturação: As data classes suportam desestruturação, o que significa que você pode facilmente extrair os valores de suas propriedades em variáveis individuais.


As data classes são muito úteis para modelar dados simples e são uma das características distintivas da linguagem Kotlin, permitindo que você escreva menos código repetitivo ao lidar com classes de dados.



Camada de Serviço


A camada de serviço é uma parte fundamental da arquitetura de software, comumente usada em arquiteturas em camadas, como a arquitetura de três camadas (apresentação, lógica de negócios e dados). Sua principal função é conhecer toda a regra de negócio e fornecer uma abstração entre a camada de apresentação (ou interface do usuário) e a camada de acesso a dados (como bancos de dados).


Quando chega uma nova requisição para o controller, ele vai encaminhar essa requisição para a camada de serviço.



Criando o Service


Vamos criar nosso pacote de serviço da seguinte forma:

meu-projeto/
├── src/
│ ├── main/
│ │ ├── kotlin/
│ │ │ ├── meu/
│ │ │ │ ├── pacote/
│ │ │ │ │ ├── controller/
│ │ │ │ │ ├── model/
│ │ │ │ │ ├── service/
│ │ │ │ │ │ ├── MeuModel.kt

Abaixo segue um código de exemplo:

src/main/kotlin/meu/pacote/controller/service/CustomerService.kt
package meu.pacote.service

// Importing my own modules
import meu.pacote.controller.request.PostCustomerRequest
import meu.pacote.controller.request.PutCustomerRequest
import meu.pacote.model.CustomerModel

// Importing modules from spring boot
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Service // importa a "definição" de '@Service', é usada para marcar classes que desempenham o papel de serviços na arquitetura de uma aplicação.
import org.springframework.web.bind.annotation.*

@Service // é usada para marcar classes que representam serviços na arquitetura de uma aplicação, facilitando sua gerência e injeção de dependências
class CustomerService {

val customers = mutableListOf<CustomerModel>()

fun getAll(name: String?): List<CustomerModel> { // recebe a requisição do controller
name?.let {
return customers.filter { it.name.contains(name, true) }
}
return customers
}


fun create(customer: PostCustomerRequest) {
val id = if(customers.isEmpty()) {
1
} else{
customers.last().id.toInt() + 1
}.toString()

customers.add(CustomerModel(id, customer.name, customer.email))
}

fun getCustomer(id: String): CustomerModel {
return customers.filter { it.id == id }.first()
}

fun update(id: String, customer: PutCustomerRequest) {
customers.filter { it.id == id }.first().let {
it.name = customer.name
it.email = customer.email
}
}

fun delete(id: String) {
customers.removeIf { it.id == id }
}

}

Agora atualize o controller:

src/main/kotlin/meu/pacote/controller/CustomerController.kt
package meu.pacote.controller

import meu.pacote.controller.request.PostCustomerRequest
import meu.pacote.controller.request.PutCustomerRequest
import meu.pacote.model.CustomerModel
import meu.pacote.service.CustomerService

import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("customer")
class CustomerController(
val customerService : CustomerService
) {

@GetMapping
fun getAll(@RequestParam name: String?): List<CustomerModel> { // Quando chegar a requisição aqui
return customerService.getAll(name) // chama o service no método 'getAll(name)'
}

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
fun create(@RequestBody customer: PostCustomerRequest) {
customerService.create(customer)
}

@GetMapping("/{id}")
fun getCustomer(@PathVariable id: String): CustomerModel {
return customerService.getCustomer(id)
}

@PutMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
fun update(@PathVariable id: String, @RequestBody customer: PutCustomerRequest) {
customerService.update(id, customer)
}

@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
fun delete(@PathVariable id: String) {
customerService.delete(id)
}

}