Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions .cursor/skills/spring-boot-feature-delivery/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
name: spring-boot-feature-delivery
description: Delivers Java Spring Boot backend features using a concise workflow with architecture, API contract, validation, security, and testing gates. Use when the user asks to create or modify Spring Boot backend features in this repository.
---

# Spring Boot Feature Delivery

## Scope

Use this skill when implementing or changing backend features in a Java Spring Boot application.

## Default stack assumptions

- Spring Boot 3.x
- Maven + JUnit 5
- OpenAPI/Swagger enabled
- Layered + hexagonal style (domain isolated from adapters)

If the project differs, adapt to existing conventions first.

## Required workflow (short checklist)

Copy this checklist and keep it updated while working:

```md
Feature Progress:
- [ ] Clarify use case and acceptance criteria
- [ ] Define/update API contract (OpenAPI first)
- [ ] Design domain and application flow (hexagonal boundaries)
- [ ] Implement adapters (web/persistence/integration)
- [ ] Add validation and error mapping
- [ ] Apply security constraints
- [ ] Add/adjust tests (unit + integration)
- [ ] Run verification (tests/lints/build)
```

## Implementation rules

1. Start from contract:
- Define request/response and status codes before implementation.
- Keep OpenAPI updated with examples and error responses.

2. Respect hexagonal boundaries:
- Domain has no framework dependencies where possible.
- Controllers are thin adapters; no business logic in controllers.
- Repositories/gateways are adapter-side; domain depends on ports/interfaces.

3. Validation is mandatory:
- Validate inbound payloads with Bean Validation (`@Valid`, constraints).
- Return clear client errors for invalid inputs.

4. Security by default:
- Enforce authentication/authorization for new endpoints.
- Never hardcode secrets or tokens.
- Sanitize and constrain inputs; avoid leaking internals in error payloads.

5. Tests are required:
- Unit tests for domain/service logic.
- Integration tests for controller + persistence behavior.
- Include negative-path tests (validation/security/failures).

## Done criteria

A feature is complete only if all are true:

- OpenAPI reflects final behavior.
- New/changed endpoints are validated and secured.
- Tests pass and cover happy + unhappy paths.
- Build passes with no introduced linter/test failures.

## Response style for this skill

When reporting progress or final output:

- Keep it concise and actionable.
- Use:
- What changed
- Why
- How it was verified

## Additional resource

- For a reusable output template, see [templates.md](templates.md).
36 changes: 36 additions & 0 deletions .cursor/skills/spring-boot-feature-delivery/templates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Output Template

Use this format for implementation responses:

```md
Feature implemented: <name>

What changed
- <key change 1>
- <key change 2>

Why
- <business/technical reason>

Verification
- [ ] Unit tests: <result>
- [ ] Integration tests: <result>
- [ ] Build/lint: <result>

Notes
- <security/validation/openapi notes>
```

# Quick Design Prompt Template

Before coding, use:

```md
Use case:
Acceptance criteria:
API contract (request/response/errors):
Domain model:
Ports and adapters involved:
Security requirements:
Test plan:
```
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ antrun
.project
.classpath
.factorypath
*.jar
.vscode/
.cursor/*
!.cursor/skills/
!.cursor/skills/**
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ ENV BD_PORT '3306'
ENV BD_NAME ''
ENV BD_USER ''
ENV BD_PASS ''
ENV ENV dev

EXPOSE 8089

Expand Down
6 changes: 4 additions & 2 deletions compile_maven.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#!/bin/sh

# Ruta donde est'a instalado el SDK
#export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-17.0.3.1.jdk/Contents/Home
#export JAVA_HOME=/Library/Java/JavaVirtualMachines/openjdk.jdk/Contents/Home
# ac'a poner la ruta donde bajaron el ID
#export MAVEN_HOME=/home/jonnattan/utils/apache-maven-3.8.6
export MAVEN_HOME=/Users/jonnattangriffiths/tools/apache-maven-3.9.14
export PATH=$PATH:$MAVEN_HOME/bin

export ENV=local
export BD_ADDR=dev.jonnattan.com
export BD_PORT=3306
export BD_NAME=emulator
Expand All @@ -17,6 +18,7 @@ export CONTEXT=/emulator
export LOG_LEVEL=DEBUG
export AES_KEY=mAFaa23csdas5sdf12sght549u87y8adnjk


# Define un nombre al war que se genera
export JAR_NAME=server.jar
export JAR_COMPILED=server.app-1.2.0-SNAPSHOT.jar
Expand All @@ -33,4 +35,4 @@ then
echo "[INFO] El programa $JAR_NAME ha sido compilado exitosamente"
echo " \n\n\n"
java -Xmx1024m -Xms512m -jar $JAR_NAME
fi
fi
14 changes: 3 additions & 11 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,11 @@ services:
restart: always
deploy:
replicas: 1
environment:
PORT: 8089
CONTEXT: /emulator
BD_ADDR: bd.jonna.cl
BD_PORT: 3306
BD_NAME: emulator
BD_USER: jonnattan
BD_PASS: wsxzaq123
LOG_LEVEL: INFO
AES_KEY: mAFaa23csdas5sdf12sght549u87y8adnjk
env_file:
- ../envs/java_server.env
networks:
- db-net
ports:
- 8089:8089
networks:
db-net:
db-net:
42 changes: 37 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@
<url/>
</organization>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>17</java.version>
<java.version>21</java.version>
<test.version>1.2.0-SNAPSHOT</test.version>
<spring.boot.version>3.2.11</spring.boot.version>
<spring.boot.version>4.0.5</spring.boot.version>
<junit.version>4.13.1</junit.version>
<javax.json-api.version>1.1.4</javax.json-api.version>
<hibernate-types-52.version>2.6.1</hibernate-types-52.version>
<javax.json.version>1.1.4</javax.json.version>
<org.osgi.core.version>1.0.0</org.osgi.core.version>
<lombok.version>1.18.30</lombok.version>
<lombok.version>1.18.38</lombok.version>
<maven-bundle-plugin.version>4.2.1</maven-bundle-plugin.version>
</properties>

Expand Down Expand Up @@ -123,5 +123,37 @@
<filtering>true</filtering>
</testResource>
</testResources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>${maven-bundle-plugin.version}</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.15.0</version>
<configuration>
<fork>true</fork>
<release>${java.version}</release>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

/**
Expand All @@ -15,7 +14,6 @@
*/
@SpringBootApplication
@EnableJpaRepositories(basePackages = "cl.jonnattan.emulator.daos")
@EntityScan(basePackages = "cl.jonnattan.emulator")
public class Application {

public static void main(String[] args) {
Expand Down
49 changes: 49 additions & 0 deletions server.app/src/main/resources/application-local.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
spring:
application:
name: Emulador
datasource:
url: jdbc:h2:mem:emulador;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;NON_KEYWORDS=USER
username: sa
password:
driverClassName: org.h2.Driver
jpa:
show-sql: true
hibernate:
ddl-auto: update
h2:
console:
enabled: true
path: /h2-console

server:
address: 0.0.0.0
port: 8089
servlet:
context-path: /emulator

logging:
level:
springframework:
web: INFO
web: INFO
org:
hibernate:
SQL: INFO
cl.jonnattan: INFO

http:
timeout:
connect: 90
read: 90

app:
secure:
aes:
key: 1234567890123456

cxp:
select: 1
urls: http://localhost
otkeys: local-ot-key
geokeys: local-geo-key
cotkeys: local-cot-key
2 changes: 1 addition & 1 deletion server.app/src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
spring:
profiles:
active: dev
active: ${ENV}
2 changes: 1 addition & 1 deletion server.services/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.2.11</version>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package cl.jonnattan.emulator.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.fasterxml.jackson.databind.ObjectMapper;

@Configuration
public class JacksonConfig {

@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper().findAndRegisterModules();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable() // Deshabilitamos CSRF para pruebas de API
.authorizeHttpRequests()
.anyRequest().permitAll(); // Permitimos todas las peticiones sin autenticación
.csrf(csrf -> csrf.disable()) // Deshabilitamos CSRF para pruebas de API

Check failure

Code scanning / CodeQL

Disabled Spring CSRF protection High

CSRF vulnerability due to protection being disabled.
.authorizeHttpRequests(auth -> auth
.anyRequest().permitAll()); // Permitimos todas las peticiones sin autenticación

return http.build();
}
Expand Down
Loading