{"id":19719358,"url":"https://github.com/vhnegrisoli/processador-csv","last_synced_at":"2026-04-08T11:32:42.201Z","repository":{"id":127127688,"uuid":"311312242","full_name":"vhnegrisoli/processador-csv","owner":"vhnegrisoli","description":"Projeto de uma API de processamento de CSV em batch utilizando Spring Boot com Spring Batch, e persistindo os dados processados no PostgreSQL e no ElasticSearch, monitorando e consultando dados com Kibana em um ambiente Docker com docker-compose","archived":false,"fork":false,"pushed_at":"2020-11-12T14:07:35.000Z","size":732,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-16T13:54:29.454Z","etag":null,"topics":["api-rest","csv","docker","docker-compose","elasticsearch","kibana","postgresql","spring-batch","spring-boot"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vhnegrisoli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-11-09T11:08:54.000Z","updated_at":"2020-11-12T14:07:38.000Z","dependencies_parsed_at":null,"dependency_job_id":"fe907ed4-9fbe-4248-9f88-b0930de043ad","html_url":"https://github.com/vhnegrisoli/processador-csv","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/vhnegrisoli/processador-csv","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vhnegrisoli%2Fprocessador-csv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vhnegrisoli%2Fprocessador-csv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vhnegrisoli%2Fprocessador-csv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vhnegrisoli%2Fprocessador-csv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vhnegrisoli","download_url":"https://codeload.github.com/vhnegrisoli/processador-csv/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vhnegrisoli%2Fprocessador-csv/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31554091,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T10:21:54.569Z","status":"ssl_error","status_checked_at":"2026-04-08T10:21:38.171Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-rest","csv","docker","docker-compose","elasticsearch","kibana","postgresql","spring-batch","spring-boot"],"created_at":"2024-11-11T23:07:57.231Z","updated_at":"2026-04-08T11:32:42.174Z","avatar_url":"https://github.com/vhnegrisoli.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Projeto: Processador de CSV com Spring Batch, ElasticSearch e Kibana\n\n## Resumo\n\nProjeto de uma API de processamento de CSV em batch utilizando Spring Boot com Spring Batch, e persistindo os dados processados no PostgreSQL e no ElasticSearch, monitorando e consultando dados com Kibana em um ambiente Docker com docker-compose.\n\n## Tecnologias\n\n* **Java 11**\n* **Spring Boot 2**\n* **Spring Data JPA**\n* **Spring Data ElasticSearch**\n* **Spring Security**\n* **OAuth2.0 Authentication**\n* **ElasticSearch 7.9.3**\n* **Kibana 7.9.3**\n* **PostgreSQL**\n* **REST Api**\n* **Docker**\n* **Docker-compose**\n\n### Pré-requisitos\n\nÉ possível inicializar o projeto localmente via Docker ou rodando a aplicação completa na máquina.\n\n#### Para rodar via Docker com *docker-compose*\n\nProcesso de criação:\n\nO projeto está composto por um `Dockerfile` que contém um `Multi-Stage Build` da aplicação, que roda primeiramente \numa imagem do `Gradle`, que por fim instala todas as dependências necessárias, roda os testes automatizados (unitários e de integração) e\npor fim gera um `jar` de execução.\n \nO segundo estágio do `Dockerfile` copia o `jar` gerado pelo primeiro estágio ao segundo estágio, que por fim expõe\na porta `8080` e o executa. Há também no projeto um arquivo `docker-compose.yml`, que, ao ser executado, executa os containers:\n\n```   \n* elasticsearch       (ElasticSearch)\n* kibana              (Kibana)\n* processador-csv-api (Aplicação Spring)\n* processador-csv-db  (Banco de dados PostgreSQL 11)\n```\n\nProcesso de execução:\n\nPara realizar o build das imagens e inicializar todos os containers, basta executar:\n\n`docker-compose up --build`\n\nPara não acompanhar os logs, apenas execute com a flag `-d` ao fim do comando. Para não realizar o build, apenas remova a flag `--build`.\n\nPara parar todos os containers:\n\n`docker-compose stop`\n\nPara apagar todos os containers parados:\n\n`docker container prune`\n\nEm seguida, aperte `y` para confirmar a exlcusão.\n\nPara apagar todas as imagens geradas (caso os containers estejam parados):\n\n`docker image prune`\n\nEm seguida, aperte `y` para confirmar a exlcusão.\n\nPara acompanhar os logs de qualquer container, basta executar:\n\n`docker logs --follow NOME_DO_CONTAINER`\n\n#### Para rodar localmente via IDE ou Maven\n\nÉ necessário ter as seguintes ferramentas para inicializar o projeto:\n\n```\nJava 11\nGradle\ngradlew\nDocker (para inicializar o ElasticSearch e o Kibana)\n```\n\n### Instalação\n\nPrimeiramente, rode a instalação através da mvn, sem os testes:\n\n```\ngradle build\n```\n\n## Iniciando a aplicação\n\nApós instalar a aplicação, dar o build e gerar o jar, basta, na raiz, executar:\n\n```\ngradle bootRun\n```\n\nOu então:\n\n```\ncd build/libs/java -jar nome_do_jar.jar\n```\n\nA aplicação estará disponível em:\n\n```\nhttp://localhost:8080\n```\n\n## Autenticação (OAuth2.0)\n\nPara acessar os endpoints, é necessário ter um usuário e realizar um login.\n\nAo iniciar a aplicação, é criado um usuário padrão:\n\nE-mail: USUARIO@GMAIL.COM\nSenha: 123456\n\n### Endpoint /oauth/token\n\nPara se autenticar, realize o seguinte request:\n\n```\ncurl -i -X POST \\\n   -H \"Content-Type:application/x-www-form-urlencoded\" \\\n   -d \"client_id=processador-csv-client\" \\\n   -d \"client_secret=processador-csv-secret\" \\\n   -d \"username=usuario@gmail.com\" \\\n   -d \"password=123456\" \\\n   -d \"grant_type=password\" \\\n 'http://localhost:8080/oauth/token'\n```\n\nOu então, via algum testador de APIs:\n\nEndpoint: `http://localhost:8080/oauth/token`\nMétodo: `POST`\nHeaders: `Content-Type: application/x-www-form-urlencoded`\nBody (tipo Form): \n```\nclient_id: processador-csv-client\nclient_secret: processador-csv-secret\nusername: usuario@gmail.com\npassword: 123456\ngrant_type: password\n```\n\nCaso as credenciais estejam corretas, a resposta será:\n\n```\n{\n    \"access_token\": \"fd03aab5-c701-4266-8786-7849f0cc80fc\",\n    \"token_type\": \"bearer\",\n    \"expires_in\": 59999,\n    \"scope\": \"read write trust\"\n}\n```\n\n### Como sei que estou logado?\n\nAo receber seu `access token`, basta bater em qualquer ``endpoint``\nprivado, ou seja, que não possua ``public`` em sua URI.\n\nPara que qualquer request com o `access token` seja válido, será\nnecessário colocar um `Header`:\n\n`Authorization: Bearer token`\n\nExemplo de request:\n\n```\ncurl -i -X GET \\\n   -H \"Authorization:Bearer 4687e3af-ba46-4115-b283-ea2d6d05bd53\" \\\n 'http://localhost:8080/api/usuarios/autenticado'\n```\n\nExemplo de resposta: \n\n```\n{\n    \"id\": 1,\n    \"nome\": \"USUÁRIO EXEMPLO\",\n    \"email\": \"USUARIO@GMAIL.COM\",\n    \"permissoes\": [\n        \"ROLE_ADMIN\",\n        \"ROLE_USER\"\n    ]\n}\n```\n\nCaso envie sem o ``Header`` de autorização, a resposta será:\n\n```\n{\n    \"error\": \"unauthorized\",\n    \"error_description\": \"Full authentication is required to access this resource\"\n}\n```\n\n## Fluxo de atividade\n\nDentro do diretório `process`, logo na raiz do projeto, há um arquivo chamado `data.csv`, sendo um CSV sobre a descrição de personagens de quadrinhos da DC e Marvel Comics, contendo exatamente 23.272 linhas de dados, com algumas inválidas, por exemplo, quando o campo YEAR for vazio.\n\nExemplo de CSV utilizado: \n\n|page_id|name                          |urlslug                               |ID             |ALIGN          |EYE       |HAIR      |SEX              |GSM|ALIVE            |APPEARANCES|FIRST APPEARANCE|YEAR|\n|-------|------------------------------|--------------------------------------|---------------|---------------|----------|----------|-----------------|---|-----------------|-----------|----------------|----|\n|1422   |Batman (Bruce Wayne)          |\\/wiki\\/Batman_(Bruce_Wayne)          |Secret Identity|Good Characters|Blue Eyes |Black Hair|Male Characters  |   |Living Characters|3093       |1939, May       |1939|\n|23387  |Superman (Clark Kent)         |\\/wiki\\/Superman_(Clark_Kent)         |Secret Identity|Good Characters|Blue Eyes |Black Hair|Male Characters  |   |Living Characters|2496       |1986, October   |1986|\n|1458   |Green Lantern (Hal Jordan)    |\\/wiki\\/Green_Lantern_(Hal_Jordan)    |Secret Identity|Good Characters|Brown Eyes|Brown Hair|Male Characters  |   |Living Characters|1565       |1959, October   |1959|\n|1659   |James Gordon (New Earth)      |\\/wiki\\/James_Gordon_(New_Earth)      |Public Identity|Good Characters|Brown Eyes|White Hair|Male Characters  |   |Living Characters|1316       |1987, February  |1987|\n|1576   |Richard Grayson (New Earth)   |\\/wiki\\/Richard_Grayson_(New_Earth)   |Secret Identity|Good Characters|Blue Eyes |Black Hair|Male Characters  |   |Living Characters|1237       |1940, April     |1940|\n|1448   |Wonder Woman (Diana Prince)   |\\/wiki\\/Wonder_Woman_(Diana_Prince)   |Public Identity|Good Characters|Blue Eyes |Black Hair|Female Characters|   |Living Characters|1231       |1941, December  |1941|\n|1486   |Aquaman (Arthur Curry)        |\\/wiki\\/Aquaman_(Arthur_Curry)        |Public Identity|Good Characters|Blue Eyes |Blond Hair|Male Characters  |   |Living Characters|1121       |1941, November  |1941|\n|1451   |Timothy Drake (New Earth)     |\\/wiki\\/Timothy_Drake_(New_Earth)     |Secret Identity|Good Characters|Blue Eyes |Black Hair|Male Characters  |   |Living Characters|1095       |1989, August    |1989|\n|71760  |Dinah Laurel Lance (New Earth)|\\/wiki\\/Dinah_Laurel_Lance_(New_Earth)|Public Identity|Good Characters|Blue Eyes |Blond Hair|Female Characters|   |Living Characters|1075       |1969, November  |1969|\n\nAo iniciar a aplicação, será definido um `Job` do `Spring Batch` que irá rodar a cada 1 hora. O `Job` será responsável por definir um `Reader` para ler os dados do CSV e transformar em um objeto Java do tipo `PersonagemCsvDTO`, um `Processor` para processar e converter o objeto criado anteriormente em um objeto do tipo `Personagem` (uma entidade JPA), e por fim, chamar o `Writer` que irá realizar a operação de `INSERT` dos dados no PostgreSQL. \n\nO `Job` foi definido com um `chunk` com tamanho 100, ou seja, o processamento será executado de 100 em 100 lotes de processamento.\n\nAo fim do `Job`, será chamado o `Listener` de finalização, e, neste processo, será realizada a inserção dos dados que estão inseridos no `PostgreSQL` para dentro do `ElasticSearch`, filtrando apenas por dados que estiverem válidos. Por fim, caso existam dados inválidos no `PostgreSQL`, serão removidos.\n\n#### Iniciar um Job manualmente via endpoint\n\nNa API, há um endpoint que permite iniciar o ``job`` manualmente.\n\nVia endpoint por um testador de API:\n\nEndpoint: ``http://localhost:8080/api/jobs/personagem/iniciar``\nMétodo: ``POST``\nHeaders: ``Authorization: Bearer 6fbbb711-8a84-43e1-9dff-e512d37a0212``\n\nVia cURL:\n\n````\ncurl -i -X POST \\\n   -H \"Authorization:Bearer 6fbbb711-8a84-43e1-9dff-e512d37a0212\" \\\n   -H \"Content-Type:application/json\" \\\n   -d \\\n'' \\\n 'http://localhost:8080/api/jobs/personagem/iniciar'\n````\n\n#### Configurações iniciais do ElasticSearch\n\nÉ necessário alterar a quantidade máxima de itens permitidos a serem retornados\nno resultado de uma busca acima de 10.000 itens. Vamos alterar para 1.000.000 itens.\n\nPara isso, caso esteja usando o `Kibana`, execute a consulta:\n\n````\nPUT personagem/_settings\n{\n  \"index\" : { \n     \"max_result_window\" : 1000000 \n   } \n}\n````\n\nCaso esteja usando uma aplicação para teste de APIs, utilize assim:\n\nEndpoint: `http://localhost:9200/personagem/_settings`\n\nMétodo: `PUT`\n\nBody: \n\n```\n{\n  \"index\" : { \n     \"max_result_window\" : 1000000\n   } \n}\n```\n\nOu então, via cURL:\n\n```\ncurl -i -X PUT \\\n   -H \"Content-Type:application/json\" \\\n   -d \\\n    '{\n      \"index\" : { \n         \"max_result_window\" : 1000000 \n       } \n    }' \\\n 'http://localhost:9200/personagem/_settings'\n```\n\nA resposta em qualquer caso será:\n\nHTTP Status Code: `200`\n\nResposta: \n\n```\n{\n    \"acknowledged\" : true\n}\n```\n\n## Documentação dos endpoints da API com Swagger\n\nA documentação estará disponível em: ``http://localhost:8080/swagger-ui.html``\n\n![Documentação Swagger](https://github.com/vhnegrisoli/processador-csv/blob/main/imagens/Documenta%C3%A7%C3%A3o%20Swagger.png)\n\n## Autores\n\n* **Victor Hugo Negrisoli** - *Desenvolvedor Back-End Sênior* - [vhnegrisoli](https://github.com/vhnegrisoli)\n\n## Licença\n\nEste projeto possui a licença do MIT. Veja mais em: [LICENSE](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvhnegrisoli%2Fprocessador-csv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvhnegrisoli%2Fprocessador-csv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvhnegrisoli%2Fprocessador-csv/lists"}