- Sobre o Mottu Mapping
- Estrutura do projeto
- Dependências instaladas
- Endpoints
- Tabela de Endpoints
- Modelo Relacional
- Execução do projeto localmente
- Deploy Azure Web App via Github Actions
Mottu Mapping é uma solução que por meio de um modelo de visão computacional integrado a um sistema de hardware e software, possibilitará um gerenciamento dos pátios da Mottu com mais agildiade e precisão.
- Integrantes:
- André Geraldi Marcolongo - RM555285 - 2TDSPV
- Felipe Gabriel Lopes Clarindo - RM554547 - 2TDSPF
Aplicação backend desenvolvida em Java utilizando o framework Spring Boot, estruturada com Maven. O sistema gerencia operações de cadastro, edição e exclusão de motos, setores, operadores e pátios, integrando funcionalidades de visão computacional para mapeamento de veículos. Os dados são persistidos em banco de dados, com controle de versões e migrações gerenciado pelo Flyway. A interface administrativa e operacional é construída com Thymeleaf, oferecendo páginas dinâmicas para CRUD de entidades e visualização de informações. O projeto inclui autenticação baseada em usuários e papéis (admin e operador), e separa camadas de API e web.
├───src
│ ├───main
│ │ ├───java
│ │ │ └───com
│ │ │ └───mottu
│ │ │ └───mapping
│ │ │ │ MottuMappingApiApplication.java
│ │ │ │
│ │ │ ├───api
│ │ │ │ ├───config
│ │ │ │ ├───controller
│ │ │ │ │ ModelController.java
│ │ │ │ │ MotoController.java
│ │ │ │ │ MotoYardController.java
│ │ │ │ │ SectorController.java
│ │ │ │ │ UserController.java
│ │ │ │ │
│ │ │ │ ├───dto
│ │ │ │ │ ├───request
│ │ │ │ │ │ ModelRequestDTO.java
│ │ │ │ │ │ MotoRequestDTO.java
│ │ │ │ │ │ MotoYardRequestDTO.java
│ │ │ │ │ │ SectorRequestDTO.java
│ │ │ │ │ │ UserRequestDTO.java
│ │ │ │ │ │
│ │ │ │ │ └───response
│ │ │ │ │ ModelResponseDTO.java
│ │ │ │ │ MotoResponseDTO.java
│ │ │ │ │ MotoYardResponseDTO.java
│ │ │ │ │ SectorResponseDTO.java
│ │ │ │ │ UserResponseDTO.java
│ │ │ │ │
│ │ │ │ ├───exception
│ │ │ │ │ ApiExceptionHandler.java
│ │ │ │ │ ModelNotFoundException.java
│ │ │ │ │ MotoNotFoundException.java
│ │ │ │ │ MotoYardNotFoundException.java
│ │ │ │ │ SectorNotFoundException.java
│ │ │ │ │ UserNotFoundException.java
│ │ │ │ │
│ │ │ │ ├───mapper
│ │ │ │ │ ModelMapper.java
│ │ │ │ │ MotoMapper.java
│ │ │ │ │ MotoYardMapper.java
│ │ │ │ │ SectorMapper.java
│ │ │ │ │
│ │ │ │ ├───model
│ │ │ │ │ Model.java
│ │ │ │ │ Moto.java
│ │ │ │ │ MotoYard.java
│ │ │ │ │ Sector.java
│ │ │ │ │ User.java
│ │ │ │ │
│ │ │ │ ├───repository
│ │ │ │ │ ModelRepository.java
│ │ │ │ │ MotoRepository.java
│ │ │ │ │ MotoYardRepository.java
│ │ │ │ │ SectorRepository.java
│ │ │ │ │ UserRepository.java
│ │ │ │ │
│ │ │ │ ├───security
│ │ │ │ │ SecurityConfig.java
│ │ │ │ │ UserDetailImplementation.java
│ │ │ │ │ UserDetailServiceImplementation.java
│ │ │ │ │
│ │ │ │ ├───service
│ │ │ │ │ ModelService.java
│ │ │ │ │ MotoService.java
│ │ │ │ │ MotoYardService.java
│ │ │ │ │ SectorService.java
│ │ │ │ │ UserService.java
│ │ │ │ │
│ │ │ │ └───util
│ │ │ │ EntityPair.java
│ │ │ │
│ │ │ └───web
│ │ │ └───controller
│ │ │ AdminController.java
│ │ │ OperatorController.java
│ │ │ PublicController.java
│ │ │
│ │ └───resources
│ │ │ application.properties
│ │ │ env.properties
│ │ │
│ │ ├───db
│ │ │ └───migration
│ │ │ V1__create_tables.sql
│ │ │ V2__insert__users.sql
│ │ │ V3__insert_moto_models.sql
│ │ │ V4__insert_moto_yards.sql
│ │ │ V5__insert_sectors.sql
│ │ │ V6__populate_motorcycles.sql
│ │ │
│ │ ├───static
│ │ │ style.css
│ │ │
│ │ └───templates
│ │ │ 403.html
│ │ │ fragments.html
│ │ │ index.html
│ │ │
│ │ ├───admin
│ │ │ cadastra-moto.html
│ │ │ cadastra-operador.html
│ │ │ cadastra-setor.html
│ │ │ dashboard.html
│ │ │ edita-setor.html
│ │ │ moto-details.html
│ │ │ users.html
│ │ │
│ │ └───operator
│ │ cadastra-moto.html
│ │ dashboard.html
│ │ moto-details.html<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Mapper -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.5.Final</version>
</dependency>
<!-- Data Persistence -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc11</artifactId>
<scope>runtime</scope>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.microsoft.sqlserver</groupId>-->
<!-- <artifactId>mssql-jdbc</artifactId>-->
<!-- <scope>runtime</scope>-->
<!-- </dependency>-->
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<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>
<!-- Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Flyway -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-oracle</artifactId>
<version>10.20.1</version>
</dependency>
<!-- Thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Thymeleaf Spring Security extras -->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
</dependencies>
</dependencies>- spring-boot-starter-data-jpa → Suporte a banco de dados via JPA/Hibernate.
- mapstruct → Framework de mapper para conversão entre DTOs e entidades.
- ojdbc11 → Driver JDBC para conectar ao banco Oracle.
- lombok → Geração automática de getters, setters, construtores e builders.
- spring-boot-starter-test → Ferramentas para testes automatizados (JUnit, Mockito, etc.).
- spring-boot-starter-validation → Validação de dados via anotações (ex:
@NotNull,@Email). - spring-boot-starter-cache → Suporte a cache para melhorar desempenho da aplicação.
- spring-boot-devtools → Hot reload para facilitar o desenvolvimento.
- spring-boot-starter-web → Suporte para APIs REST e servidor embutido (Tomcat).
- spring-boot-starter-actuator → Monitoramento e métricas da aplicação.
- spring-boot-starter-security → Segurança e autenticação/autorização na aplicação.
- flyway-database-oracle → Versionamento e migração de banco de dados Oracle.
- spring-boot-starter-thymeleaf → Suporte ao motor de templates Thymeleaf.
- thymeleaf-extras-springsecurity6 → Integração do Thymeleaf com Spring Security.
- URL:
/api/motoyards - Método: POST
- Descrição: Cria um novo MotoYard.
- Body (JSON):
{
"description": "Pátio de Pendências",
"capacity": 100
}-Exemplo cURL:
curl -X POST "http://localhost:8080/api/motoyards" \
-H "Content-Type: application/json" \
-d '{
"description": "Pátio de Pendências",
"capacity": 100
}'- URL:
/api/motoyards - Método: GET
- Descrição: Retorna uma lista de todos os MotoYards.
- Exemplo cURL:
curl -X GET "http://localhost:8080/api/motoyards"- URL:
/api/motoyards/{id} - Método: GET
- Descrição: Retorna os dados do MotoYard pelo ID.
- Exemplo cURL:
curl -X GET "http://localhost:8080/api/motoyards/1"- URL:
/api/motoyards/{id} - Método: PUT
- Descrição: Atualiza os dados do MotoYard pelo ID.
- Body (JSON):
{
"description": "Pátio Pendências",
"capacity": 150
}- Exemplo cURL:
curl -X POST "http://localhost:8080/api/motoyards" \
-H "Content-Type: application/json" \
-d '{
"description": "Pátio Pendências",
"capacity": 150
}'- URL: /api/motoyards/{id}
- Método: DELETE
- Descrição: Remove o MotoYard pelo ID. Retorna HTTP 204 (No Content) em caso de sucesso.
- Exemplo cURL:
curl -X DELETE "http://localhost:8080/api/motoyards/1"- URL:
/api/sectors - Método: POST
- Descrição: Cria um novo setor vinculado a um MotoYard.
- Body (JSON):
{
"yardId": 1,
"name": "Manutenção",
"description": "Setor de manutenção",
"colorRgb": "#FFA500",
"colorName": "orange"
}- Exemplo cURL:
curl -X POST "http://localhost:8080/api/sectors" \
-H "Content-Type: application/json" \
-d '{
"yardId": 1,
"name": "Manutenção",
"description": "Setor de manutenção",
"colorRgb": "#FFA500",
"colorName": "orange"
}'-
URL:
/api/sectors -
Método: GET
-
Descrição: Retorna uma lista de todos os setores.
-
Exemplo cURL:
curl -X GET "http://localhost:8080/api/sectors"- URL:
/api/sectors/{id} - Método: GET
- Descrição: Retorna os dados de um setor específico pelo ID.
Exemplo cURL:
curl -X GET "http://localhost:8080/api/sectors/1"- URL:
/api/sectors/{id} - Método: PUT
- Descrição: Atualiza os dados de um setor existente.
- Body (JSON):
{
"yardId": 1,
"name": "Liberadas",
"description": "Setor de motos liberadas",
"colorRgb": "#00FF00",
"colorName": "green"
}- Exemplo cURL:
curl -X PUT "http://localhost:8080/api/sectors/1" \
-H "Content-Type: application/json" \
-d '{
"yardId": 1,
"name": "Liberadas",
"description": "Setor de motos liberadas",
"colorRgb": "#00FF00",
"colorName": "green"
}'- URL:
/api/sectors/{id} - Método: DELETE
- Descrição: Remove o setor pelo ID. Retorna HTTP 204 (No Content) em caso de sucesso.
- Exemplo cURL:
curl -X DELETE "http://localhost:8080/api/sectors/1"- URL:
/api/models - Método: POST
- Descrição: Cria um novo modelo de moto.
- Body (JSON):
{
"modelName": "Mottu Pop"
}- Exemplo cURL:
curl -X POST "http://localhost:8080/api/models" \
-H "Content-Type: application/json" \
-d '{
"modelName": "Mottu Pop"
}'- URL:
/api/models - Método: GET
- Descrição: Retorna uma lista de todos os modelos.
- Exemplo cURL:
curl -X GET "http://localhost:8080/api/models"-
URL:
/api/models/{id} -
Método: GET
-
Descrição: Retorna modelo pelo Id
-
Exemplo cURL:
curl -X GET "http://localhost:8080/api/models/1"- URL:
/api/models/{id} - Método: PUT
- Descrição: Atualiza os dados do modelo pelo ID.
- Body (JSON):
{
"modelName": "Mottu Sport"
}- Exemplo cURL:
curl -X PUT "http://localhost:8080/api/models/1" \
-H "Content-Type: application/json" \
-d '{
"modelName": "Mottu Sport"
}'-
URL:
/api/models/{id} -
Método: DELETE
-
Descrição: Remove um modelo pelo ID. Retorna HTTP 204 (No Content) em caso de sucesso.
-
Exemplo cURL:
curl -X DELETE "http://localhost:8080/api/models/1"- URL:
/api/motos - Método: POST
- Descrição: Cria uma nova moto.
- Body (JSON):
{
"plate": "ABC1234",
"coordinates": "23.5505,-46.6333",
"modelId": 1,
"sectorId": 1
}- Exemplo cURL:
curl -X POST "http://localhost:8080/api/motos" \
-H "Content-Type: application/json" \
-d '{
"plate": "ABC1234",
"coordinates": "23.5505,-46.6333",
"modelId": 1,
"sectorId": 1
}'-
URL:
/api/motos -
Método: GET
-
Descrição: Retorna uma lista paginada de motos, podendo filtrar por placa, setor e ordenar os resultados.
-
Parâmetros de Query (opcionais):
plate— filtra motos pela placa (exemplo:/api/motos?plate=ABC1234)sectorId— filtra motos pelo setor (exemplo:/api/motos?sectorId=1)page— número da página (exemplo:/api/motos?page=0)size— tamanho da página (exemplo:/api/motos?size=10)sort— ordenação dos resultados (exemplo:/api/motos?sort=plate,ascou/api/motos?sort=plate,desc)
-
Exemplo cURL:
curl -X GET "http://localhost:8080/api/motos?plate=ABC1234§orId=1&page=0&size=10&sort=plate,asc"-
URL:
/api/motos/{id} -
Método: GET
-
Descrição: Retorna os dados da moto pelo ID.
-
Exemplo cURL:
curl -X GET "http://localhost:8080/api/motos/1"- URL:
/api/motos/{id} - Método: PUT
- Descrição: Atualiza os dados da moto pelo ID.
- Body (JSON):
{
"plate": "XYZ9876",
"coordinates": "23.4567,-46.7890",
"modelId": 2,
"sectorId": 3
}- Exemplo cURL:
curl -X PUT "http://localhost:8080/api/motos/1" \
-H "Content-Type: application/json" \
-d '{
"plate": "XYZ9876",
"coordinates": "23.4567,-46.7890",
"modelId": 2,
"sectorId": 3
}'-
URL:
/api/motos/{id} -
Método: DELETE
-
Descrição: Remove a moto pelo ID. Retorna status HTTP 204 (No Content) em caso de sucesso.
-
Exemplo cURL:
curl -X DELETE "http://localhost:8080/api/motos/1"| Entidade | Operação | Método | URL | Descrição |
|---|---|---|---|---|
| MotoYard | Criar pátio | POST | /api/motoyards |
Cria um novo pátio |
| Listar pátios | GET | /api/motoyards |
Lista todos os pátios | |
| Buscar pátio por ID | GET | /api/motoyards/{id} |
Retorna pátio pelo ID | |
| Atualizar pátio por ID | PUT | /api/motoyards/{id} |
Atualiza dados do pátio | |
| Deletar pátio por ID | DELETE | /api/motoyards/{id} |
Remove pátio pelo ID | |
| Sector | Criar setor | POST | /api/sectors |
Cria um novo setor vinculado a pátio |
| Listar setores | GET | /api/sectors |
Lista todos os setores | |
| Buscar setor por ID | GET | /api/sectors/{id} |
Retorna setor pelo ID | |
| Atualizar setor por ID | PUT | /api/sectors/{id} |
Atualiza dados do setor | |
| Deletar setor por ID | DELETE | /api/sectors/{id} |
Remove setor pelo ID | |
| Model | Criar modelo | POST | /api/models |
Cria um novo modelo |
| Listar modelos | GET | /api/models |
Lista todos os modelos | |
| Buscar modelo por ID | GET | /api/models/{id} |
Retorna modelo pelo ID | |
| Atualizar modelo por ID | PUT | /api/models/{id} |
Atualiza dados do modelo | |
| Deletar modelo por ID | DELETE | /api/models/{id} |
Remove modelo pelo ID | |
| Moto | Criar moto | POST | /api/motos |
Cria uma nova moto |
| Listar motos | GET | /api/motos |
Lista motos com filtros e paginação | |
| Buscar moto por ID | GET | /api/motos/{id} |
Retorna moto pelo ID | |
| Atualizar moto por ID | PUT | /api/motos/{id} |
Atualiza dados da moto | |
| Deletar moto por ID | DELETE | /api/motos/{id} |
Remove moto pelo ID |
A coleção de APIs está disponível em:
mottu-mapping-api-java/docs/insomnia-collection-mottu-mapping.yaml
-
Crie um projeto local, caso ainda não tenha feito.
Obs: lembre-se de criar um projeto local antes de importar a collection.

-
Clique em Import (botâo direito do painel do projeto).
Isso abrirá a tela abaixo: Clique em "Choose Files" e selecione o arquivo.yaml.
-
Uma pré-visualização da collection será exibida: Clique em Import para confirmar a importação.

-
Todos os endpoints com método POST possuem exemplos de payload já salvos na aba Docs:

git clone https://github.com/andremarko/mottu-mapping-api-java
cd mottu-mapping-api-javatouch env.propertiesDentro do env.properties insira as seguintes variáveis e seus respectivos valores, por exemplo:
CONFIGURADO PARA PERSISTIR EM SQL SERVER
JDBC_CONNECTION_STRING=connectionString
DB_ADMIN=seuUsuarioDb
DB_PASSWORD=suaSenha
mvn spring-boot:run
Para acessar o dashboard do administrador, acesse com o usuário ADMINISTRADOR e senhas cadastrados via script versionado no Flyway (V2):
username: admin
senha: admin123
Para acessar o dashboard do operador, acesse com o usuário OPERADOR e senhas cadastrados via script versionado no Flyway (V2):
username: operator
senha: oper123
git clone https://github.com/andremarko/mottu-mapping-api-java
cd mottu-mapping-api-java/deploys
Exporta variáveis de ambiente com configs do Azure (SQL, WebApp, GitHub) e monta o JDBC_CONNECTION_STRING -> variável que serve para definir a conexão com o banco de dados (src/main/resources/application.properties)
Cria no Azure um Resource Group, SQL Server, banco de dados e configura firewall (Azure e IP local). No fim, lista os recursos provisionados.
Esse script cria o App Service Plan e o Web App no Azure, configura permissões e variáveis de ambiente (DB e JDBC), reinicia o app e ativa o deploy via GitHub Actions.
Esse script garante login no GitHub CLI e cria secrets no repositório (JDBC connection string, usuário e senha do banco).
Ordem de execução:
01-create-sqlserver-instance.sh;02-deploy-mottu-mapping.sh;03-set-gh-secrets.sh
Não há a necessidade de executar o env-config.sh, ele só define as variáveis que são utilizadas nos scripts.
Após execução acesse: https://mottu-mapping-mvc.azurewebsites.net/
Na página inicial, haverá dois botões (dashboard do operador e dashboard do administrador)
Escolha um para acessar
Ambos os usuários de ambas ROLES (ROLE_OPERATOR e ROLE_ADMIN) estão cadastrados na tabela tb_user.
A tabela é populada automaticamente no build do projeto. Cheque o diretório ./src/main/resources/db/migration.
Nesse diretório fica o versionamento das tabelas pelo Flyway.
Todas as tabelas são criadas e populadas no build do projeto.
Acessos:
| Username | Senha |
|---|---|
| admin | admin123 |
| operator | oper123 |
Com esses acessos é possível acessar todos os recursos que cada usuário tem, tanto quanto um operador quanto o administrador de um pátio.



