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
  [![npm version](https://img.shields.io/npm/v/spring-boot4-skill.svg)](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.2.0**
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spring-boot4-skill",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Interactive CLI scaffold for Java 25 / Spring Boot 4.x projects — with a bundled Claude Code skill for AI-assisted development.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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.
@@ -92,6 +92,8 @@ public class PaymentService {
92
92
  }
93
93
  ```
94
94
 
95
+ For **time-window rate limiting** (e.g. requests per minute per IP or user), see `references/spring-boot-4.md` (Rate limiting).
96
+
95
97
  ---
96
98
 
97
99
  ## 4. Programmatic Bean Registration