spring-boot4-skill 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.3.0] - 2026-02-21
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Skill:** spring-boot-4.md: new section 12 (Rate limiting — Bucket4j, time-window vs @ConcurrencyLimit) and section 13 (Resources & performance — HikariCP/R2DBC pools, Actuator pool metrics, Caffeine cache, performance tuning summary).
|
|
13
|
+
- **Skill:** SKILL.md Reference Files "Load when" extended for rate limiting, connection pools, resource metrics, caching, performance tuning; Quick decision mermaid node for "Rate limit / resources / performance?".
|
|
14
|
+
- **Skill:** spring-framework-7.md Resilience section: note linking to spring-boot-4.md for time-window rate limiting.
|
|
15
|
+
- **README:** Skill reference table: spring-boot-4.md description now includes rate limiting, connection pools, caching, performance.
|
|
16
|
+
|
|
17
|
+
[1.3.0]: https://github.com/AyrtonAldayr/agent-skill-java-spring-framework/compare/v1.2.0...v1.3.0
|
|
18
|
+
|
|
8
19
|
## [1.2.0] - 2026-02-21
|
|
9
20
|
|
|
10
21
|
### Added
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/spring-boot4-skill)
|
|
4
4
|
|
|
5
5
|
> **2026-standard** project scaffolder + Claude Code AI skill for Java / Spring development.
|
|
6
|
-
> By [AyrtonAldayr](https://github.com/AyrtonAldayr) · **v1.
|
|
6
|
+
> By [AyrtonAldayr](https://github.com/AyrtonAldayr) · **v1.3.0**
|
|
7
7
|
|
|
8
8
|
This repository provides two tools in one:
|
|
9
9
|
|
|
@@ -134,7 +134,7 @@ Once installed, Claude Code acts as a **Senior Spring Boot 4 architect**:
|
|
|
134
134
|
| File | Contents |
|
|
135
135
|
|---|---|
|
|
136
136
|
| `skills/java-spring-framework/references/spring-framework-7.md` | All Spring 7 APIs with code examples |
|
|
137
|
-
| `skills/java-spring-framework/references/spring-boot-4.md` | Boot 4: native, virtual threads, testing (Testcontainers), reactive stack |
|
|
137
|
+
| `skills/java-spring-framework/references/spring-boot-4.md` | Boot 4: native, virtual threads, testing (Testcontainers), reactive stack, rate limiting, connection pools, caching, performance |
|
|
138
138
|
| `skills/java-spring-framework/references/spring-security-7.md` | OAuth2 Resource Server, JWT, method security, CORS |
|
|
139
139
|
| `skills/java-spring-framework/references/spring-messaging.md` | Kafka, event-driven, @KafkaListener, producer/consumer |
|
|
140
140
|
| `skills/java-spring-framework/references/spring-modulith.md` | Module structure, events, integration testing, common pitfalls |
|
package/package.json
CHANGED
|
@@ -42,6 +42,8 @@ flowchart TD
|
|
|
42
42
|
K -->|Yes| L[troubleshooting-migration.md]
|
|
43
43
|
A --> M{Messaging / Kafka?}
|
|
44
44
|
M -->|Yes| N[spring-messaging.md]
|
|
45
|
+
A --> O{Rate limit / resources / performance?}
|
|
46
|
+
O -->|Yes| P[spring-boot-4.md]
|
|
45
47
|
```
|
|
46
48
|
|
|
47
49
|
## Mandatory Workflow
|
|
@@ -79,7 +81,7 @@ Load these as needed — do not load all at once:
|
|
|
79
81
|
| Topic | File | Load when |
|
|
80
82
|
|---|---|---|
|
|
81
83
|
| Spring Framework 7 APIs | `references/spring-framework-7.md` | Framework-level features: versioning, resilience, JSpecify, SpEL, streaming |
|
|
82
|
-
| Spring Boot 4 features | `references/spring-boot-4.md` | Boot auto-config, Actuator, native images, testing, virtual threads |
|
|
84
|
+
| Spring Boot 4 features | `references/spring-boot-4.md` | Boot auto-config, Actuator, native images, testing, virtual threads, rate limiting, connection pools, resource metrics, caching, performance tuning |
|
|
83
85
|
| Spring Security 7 | `references/spring-security-7.md` | OAuth2 Resource Server, JWT, method security, CORS, authentication/authorization |
|
|
84
86
|
| Messaging (Kafka) | `references/spring-messaging.md` | Kafka, event-driven, messaging, @KafkaListener, producer/consumer |
|
|
85
87
|
| Spring Modulith | `references/spring-modulith.md` | Domain-driven module design, event-driven architecture |
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
9. [Docker Compose Support](#9-docker-compose-support)
|
|
17
17
|
10. [Spring Security 7 Basics](#10-spring-security-7-basics)
|
|
18
18
|
11. [Reactive Stack (R2DBC + WebFlux)](#11-reactive-stack-r2dbc--webflux)
|
|
19
|
+
12. [Rate Limiting](#12-rate-limiting)
|
|
20
|
+
13. [Resources & Performance](#13-resources--performance)
|
|
19
21
|
|
|
20
22
|
---
|
|
21
23
|
|
|
@@ -446,3 +448,153 @@ Use `Netty` as the default server (Boot chooses it when `spring-boot-starter-web
|
|
|
446
448
|
### R2DBC repositories and WebFlux controllers
|
|
447
449
|
|
|
448
450
|
Define reactive repositories (`ReactiveCrudRepository`) and inject them into `@RestController` or handler functions. Use `ServerWebExchange`, `Mono`, and `Flux` for reactive types. For **RestClient** in a reactive app, use the reactive variant and streaming; see `references/spring-framework-7.md` (Streaming Support) for alignment with Spring 7 APIs.
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
## 12. Rate Limiting
|
|
455
|
+
|
|
456
|
+
**Concurrency vs time-based:** For **limiting concurrent calls per method**, use Spring 7’s built-in `@ConcurrencyLimit(maxConcurrentCalls = N)` — see `references/spring-framework-7.md` (Resilience Annotations). For **rate limiting by time window** (e.g. 100 requests per minute per IP or per user), use an in-app filter/interceptor with a token-bucket implementation or a gateway.
|
|
457
|
+
|
|
458
|
+
### Time-based rate limit (in application)
|
|
459
|
+
|
|
460
|
+
Use **Bucket4j** (token bucket) with a key per client (e.g. IP or authenticated user). Apply it in a `Filter` or `HandlerInterceptor` and return `429 Too Many Requests` when the bucket is exhausted.
|
|
461
|
+
|
|
462
|
+
**Dependency:**
|
|
463
|
+
|
|
464
|
+
```kotlin
|
|
465
|
+
// build.gradle.kts
|
|
466
|
+
implementation("com.bucket4j:bucket4j-core:8.10.1")
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
**Example: filter keyed by IP**
|
|
470
|
+
|
|
471
|
+
```java
|
|
472
|
+
import io.github.bucket4j.Bandwidth;
|
|
473
|
+
import io.github.bucket4j.Bucket;
|
|
474
|
+
import io.github.bucket4j.Refill;
|
|
475
|
+
import jakarta.servlet.FilterChain;
|
|
476
|
+
import jakarta.servlet.ServletException;
|
|
477
|
+
import jakarta.servlet.http.HttpServletRequest;
|
|
478
|
+
import jakarta.servlet.http.HttpServletResponse;
|
|
479
|
+
import org.springframework.core.annotation.Order;
|
|
480
|
+
import org.springframework.stereotype.Component;
|
|
481
|
+
import org.springframework.web.filter.OncePerRequestFilter;
|
|
482
|
+
|
|
483
|
+
import java.io.IOException;
|
|
484
|
+
import java.time.Duration;
|
|
485
|
+
import java.util.Map;
|
|
486
|
+
import java.util.concurrent.ConcurrentHashMap;
|
|
487
|
+
|
|
488
|
+
@Component
|
|
489
|
+
@Order(1)
|
|
490
|
+
public class RateLimitFilter extends OncePerRequestFilter {
|
|
491
|
+
|
|
492
|
+
private final Map<String, Bucket> buckets = new ConcurrentHashMap<>();
|
|
493
|
+
private static final int CAPACITY = 100;
|
|
494
|
+
private static final Duration REFILL_DURATION = Duration.ofMinutes(1);
|
|
495
|
+
|
|
496
|
+
@Override
|
|
497
|
+
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
|
498
|
+
FilterChain filterChain) throws ServletException, IOException {
|
|
499
|
+
String key = clientKey(request); // e.g. request.getRemoteAddr() or principal name
|
|
500
|
+
Bucket bucket = buckets.computeIfAbsent(key, k -> newBucket());
|
|
501
|
+
if (bucket.tryConsume(1)) {
|
|
502
|
+
filterChain.doFilter(request, response);
|
|
503
|
+
} else {
|
|
504
|
+
response.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
|
|
505
|
+
response.getWriter().write("Rate limit exceeded");
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
private static String clientKey(HttpServletRequest request) {
|
|
510
|
+
return request.getRemoteAddr();
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
private static Bucket newBucket() {
|
|
514
|
+
Bandwidth limit = Bandwidth.classic(CAPACITY, Refill.greedy(CAPACITY, REFILL_DURATION));
|
|
515
|
+
return Bucket.builder().addLimit(limit).build();
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
For **per-user** limits, use a key derived from `SecurityContextHolder.getContext().getAuthentication()` (e.g. principal name) and exempt unauthenticated or health endpoints from the filter if needed.
|
|
521
|
+
|
|
522
|
+
**When to use which:** Use `@ConcurrencyLimit` to cap concurrent executions of a specific method. Use a filter with Bucket4j (or similar) for API-level limits per time window (per IP or per user). If traffic is fronted by **Spring Cloud Gateway**, rate limiting can also be implemented at the edge; that is outside the scope of this reference.
|
|
523
|
+
|
|
524
|
+
---
|
|
525
|
+
|
|
526
|
+
## 13. Resources & Performance
|
|
527
|
+
|
|
528
|
+
### Connection pools (HikariCP, R2DBC)
|
|
529
|
+
|
|
530
|
+
**HikariCP (blocking JDBC)** — Spring Boot configures it by default. Tune in `application.yaml`:
|
|
531
|
+
|
|
532
|
+
```yaml
|
|
533
|
+
spring:
|
|
534
|
+
datasource:
|
|
535
|
+
hikari:
|
|
536
|
+
maximum-pool-size: 20
|
|
537
|
+
minimum-idle: 5
|
|
538
|
+
connection-timeout: 30000
|
|
539
|
+
idle-timeout: 600000
|
|
540
|
+
max-lifetime: 1800000
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
See [Spring Boot Data Access](https://docs.spring.io/spring-boot/docs/current/reference/html/data.html#data.sql.datasource.hikari) for all options.
|
|
544
|
+
|
|
545
|
+
**R2DBC** — For reactive apps, configure the connection pool similarly (e.g. `spring.r2dbc.pool.*`). DB health is included in health groups (section 4); use readiness to avoid sending traffic to instances that cannot get a connection.
|
|
546
|
+
|
|
547
|
+
### Metrics for resources
|
|
548
|
+
|
|
549
|
+
Actuator exposes **HikariCP** metrics (e.g. `hikaricp.connections.active`, `hikaricp.connections.idle`, `hikaricp.connections.pending`). Use these in Prometheus/Grafana to size pools and alert on exhaustion. R2DBC pool metrics follow a similar pattern when the reactive stack is used.
|
|
550
|
+
|
|
551
|
+
### Caching
|
|
552
|
+
|
|
553
|
+
Use **Spring Cache** with **Caffeine** for in-process caching. Reduces repeated work and database load.
|
|
554
|
+
|
|
555
|
+
**Dependencies:**
|
|
556
|
+
|
|
557
|
+
```kotlin
|
|
558
|
+
// build.gradle.kts
|
|
559
|
+
implementation("org.springframework.boot:spring-boot-starter-cache")
|
|
560
|
+
implementation("com.github.ben-manes.caffeine:caffeine")
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
**Enable and configure:**
|
|
564
|
+
|
|
565
|
+
```java
|
|
566
|
+
@SpringBootApplication
|
|
567
|
+
@EnableCaching
|
|
568
|
+
public class Application { ... }
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
```yaml
|
|
572
|
+
# application.yaml
|
|
573
|
+
spring:
|
|
574
|
+
cache:
|
|
575
|
+
cache-names: products,users
|
|
576
|
+
caffeine:
|
|
577
|
+
spec: maximumSize=1000,expireAfterWrite=300s
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
**Usage:**
|
|
581
|
+
|
|
582
|
+
```java
|
|
583
|
+
@Service
|
|
584
|
+
public class ProductService {
|
|
585
|
+
|
|
586
|
+
@Cacheable(cacheNames = "products", key = "#id")
|
|
587
|
+
public Product findById(Long id) {
|
|
588
|
+
return productRepository.findById(id).orElseThrow();
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
Use short TTLs or size limits to avoid stale or unbounded caches.
|
|
594
|
+
|
|
595
|
+
### Performance tuning (summary)
|
|
596
|
+
|
|
597
|
+
- **Virtual threads** (section 6): Enable for high concurrency with blocking I/O; no need to size a large thread pool.
|
|
598
|
+
- **Pool sizing:** Set HikariCP (or R2DBC pool) size based on observed metrics (connections in use, pending); avoid over-provisioning.
|
|
599
|
+
- **N+1:** Avoid N+1 queries in JPA (e.g. `@EntityGraph`, fetch joins, or DTO projections) so a single request does not open many statements.
|
|
600
|
+
- **Observability:** Use Actuator/Prometheus and traces (section 4) to find bottlenecks (slow endpoints, DB, or external calls) and tune accordingly. No JVM-level tuning (heap, GC) is covered here.
|