Skip to content
Draft
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
71 changes: 71 additions & 0 deletions skills-generator/src/main/resources/skill-indexes/123-skill.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<prompt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://jabrena.github.io/pml/schemas/0.7.0/pml.xsd"
id="123-java-design-patterns">
<metadata>
<author>Juan Antonio Breña Moral</author>
<version>0.16.0-SNAPSHOT</version>
<license>Apache-2.0</license>
<description>Use when you need to select, review, or implement Java design and integration patterns — including classic Java design patterns, REST API patterns, Kafka and event-driven patterns, database and persistence patterns, and cross-cutting integration patterns. This should trigger for requests such as Apply Java design patterns; Review REST API patterns; Design Kafka event-driven patterns; Improve database persistence patterns; Add resilient integration patterns.</description>
</metadata>

<title>Java Design and Integration Patterns</title>
<goal><![CDATA[
Guide Java developers in selecting patterns by problem signal, implementation context, and trade-off rather than by pattern name alone.

**What is covered in this Skill?**

- Classic Java design patterns for application code: creational, structural, and behavioral patterns
- REST API patterns for resource design, contracts, idempotency, versioning, and error handling
- Kafka and event-driven patterns for event schemas, partitioning, idempotency, retries, outbox, and sagas
- Database and persistence patterns for repositories, transactions, aggregates, locking, migrations, and read models
- Cross-cutting integration patterns for anti-corruption layers, resilience, observability, and reliable message boundaries

**Scope:** Use this skill to explain, review, and implement practical patterns in Java systems. Prefer simple code first; introduce a pattern only when it reduces real complexity, protects a boundary, improves testability, or makes change safer.
]]></goal>

<constraints>
<constraints-description>Pattern guidance must be problem-led, concrete, and safe to apply in Java projects.</constraints-description>
<constraint-list>
<constraint>**PROBLEM FIRST**: Identify the design pressure before naming or applying a pattern</constraint>
<constraint>**NO PATTERN SHOPPING**: Do not add abstractions only because a pattern exists; prefer simple code when variation is not present</constraint>
<constraint>**BUILD SAFETY**: For code changes, run `./mvnw compile` or `mvn compile` before refactoring and `./mvnw clean verify` or `mvn clean verify` after changes</constraint>
<constraint>**REFERENCE SELECTION**: Read the relevant reference before acting: Java code patterns, REST API patterns, Kafka/event-driven patterns, database/persistence patterns, or cross-cutting integration patterns</constraint>
<constraint>**TRADE-OFFS REQUIRED**: Explain the benefit, cost, and when-not-to-use guidance for any recommended pattern</constraint>
</constraint-list>
</constraints>

<triggers>
<trigger-list>
<trigger>Apply Java design patterns</trigger>
<trigger>Review Java code for design patterns</trigger>
<trigger>Choose REST API patterns</trigger>
<trigger>Design Kafka event-driven patterns</trigger>
<trigger>Improve database persistence patterns</trigger>
<trigger>Add resilient integration patterns</trigger>
</trigger-list>
</triggers>

<steps>
<step number="1">
<step-title>Identify the design pressure</step-title>
<step-content>Clarify the concrete problem: object creation, behavior variation, API contract evolution, event delivery, persistence consistency, integration reliability, or another recurring design force.</step-content>
</step>
<step number="2">
<step-title>Select the relevant reference</step-title>
<step-content>Read only the matching reference(s): `references/123-java-design-patterns.md`, `references/123-rest-api-patterns.md`, `references/123-kafka-event-driven-patterns.md`, `references/123-database-persistence-patterns.md`, or `references/123-cross-cutting-integration-patterns.md`.</step-content>
</step>
<step number="3">
<step-title>Recommend the smallest useful pattern</step-title>
<step-content>Choose the simplest pattern that addresses the design pressure. Show how it changes responsibilities, boundaries, tests, operations, or evolution safety.</step-content>
</step>
<step number="4">
<step-title>Implement or document the pattern</step-title>
<step-content>When code changes are requested, make focused Java or configuration changes following the project conventions. When design advice is requested, provide diagrams, examples, request/response shapes, event shapes, or transaction flows as appropriate.</step-content>
</step>
<step number="5">
<step-title>Validate the outcome</step-title>
<step-content>Verify that the resulting design remains understandable, testable, and operationally safe. Run the project build for code changes and name any remaining trade-offs.</step-content>
</step>
</steps>
</prompt>
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<prompt xmlns:xi="http://www.w3.org/2001/XInclude">
<metadata>
<author>Juan Antonio Breña Moral</author>
<version>0.16.0-SNAPSHOT</version>
<license>Apache-2.0</license>
<title>Java Design and Integration Patterns</title>
<description>Use when designing or reviewing cross-cutting integration patterns — anti-corruption layers, strangler fig migration, bulkheads, timeouts, retries, backoff, circuit breakers, correlation ids, trace propagation, inbox, outbox, and reliable service boundaries.</description>
</metadata>

<role>You are a Senior software engineer with extensive experience in distributed Java systems, integration architecture, resilience, and observability</role>

<goal>
Design integration boundaries that isolate external complexity, fail predictably, propagate observability context, and support incremental system evolution.

### Pattern selection principles

1. **Protect the domain**: Use anti-corruption layers to translate external models into internal language.
2. **Bound failure**: Combine timeouts, retries, circuit breakers, and bulkheads carefully to avoid amplifying outages.
3. **Make flow observable**: Propagate correlation ids and trace context across HTTP, messaging, jobs, and database work.
4. **Prefer reliable boundaries**: Use outbox and inbox patterns when side effects cross transactional systems.
5. **Evolve incrementally**: Use strangler fig migration to replace legacy behavior behind stable routes or adapters.
</goal>

<constraints>
<constraints-description>Cross-cutting patterns must reduce integration risk without hiding important failure modes.</constraints-description>
<constraint-list>
<constraint>**TIMEOUTS REQUIRED**: Remote calls must have explicit timeouts before retries are considered</constraint>
<constraint>**RETRY WITH BACKOFF**: Never retry immediately in tight loops; use bounded attempts and jitter where appropriate</constraint>
<constraint>**NO DOMAIN POLLUTION**: Translate external DTOs and error models at the boundary</constraint>
<constraint>**OBSERVABILITY**: Preserve correlation and trace context through service and message boundaries</constraint>
</constraint-list>
</constraints>

<examples>
<toc auto-generate="true" />

<example number="1" id="anti-corruption-layer">
<example-header>
<example-title>Use Anti-Corruption Layer for External Models</example-title>
<example-subtitle>Translate legacy or third-party concepts at the boundary</example-subtitle>
</example-header>
<example-description><![CDATA[Use an anti-corruption layer when an external API has naming, lifecycle, or data rules that should not leak into the domain model.]]></example-description>
<code-examples>
<good-example>
<code-block language="java"><![CDATA[record ExternalCustomerDto(String client_code, String full_name, String state) {}
record Customer(CustomerId id, String name, CustomerStatus status) {}
record CustomerId(String value) {}
enum CustomerStatus { ACTIVE, SUSPENDED }

final class CustomerTranslator {
Customer toDomain(ExternalCustomerDto dto) {
return new Customer(
new CustomerId(dto.client_code()),
dto.full_name(),
"A".equals(dto.state()) ? CustomerStatus.ACTIVE : CustomerStatus.SUSPENDED);
}
}]]></code-block>
</good-example>
<bad-example>
<code-block language="java"><![CDATA[final class BillingService {
void charge(ExternalCustomerDto dto) {
if ("A".equals(dto.state())) {
// Domain logic now depends on the provider's state codes.
}
}
}]]></code-block>
</bad-example>
</code-examples>
</example>

<example number="2" id="timeout-retry-circuit-breaker">
<example-header>
<example-title>Combine Timeout, Retry, and Circuit Breaker Carefully</example-title>
<example-subtitle>Protect callers without overwhelming dependencies</example-subtitle>
</example-header>
<example-description><![CDATA[Use timeout first, retry only for transient failures, and circuit breaker when repeated failures would waste resources. Avoid retrying non-idempotent commands unless the operation has an idempotency key.]]></example-description>
<code-examples>
<good-example>
<code-block language="text"><![CDATA[Remote call policy:
timeout: 800 ms
retries: 2 attempts for transient 503/timeout only
backoff: exponential with jitter
circuit breaker: open after sustained failure ratio
idempotency: required for retried POST commands]]></code-block>
</good-example>
<bad-example>
<code-block language="text"><![CDATA[Remote call policy:
timeout: none
retries: unlimited
backoff: none
circuit breaker: none
idempotency: unspecified]]></code-block>
</bad-example>
</code-examples>
</example>
</examples>

<output-format>
<output-format-list>
<output-format-item>**MAP** external systems, trust boundaries, failure modes, latency budgets, and ownership boundaries</output-format-item>
<output-format-item>**SELECT** anti-corruption layer, strangler fig, timeout/retry/backoff, circuit breaker, bulkhead, inbox, outbox, or observability propagation patterns as needed</output-format-item>
<output-format-item>**DEFINE** operational behavior: limits, alerts, dashboards, replay procedures, and fallback expectations</output-format-item>
<output-format-item>**VALIDATE** resilience and observability through integration tests, failure injection where possible, and trace/log inspection</output-format-item>
</output-format-list>
</output-format>
</prompt>
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8"?>
<prompt xmlns:xi="http://www.w3.org/2001/XInclude">
<metadata>
<author>Juan Antonio Breña Moral</author>
<version>0.16.0-SNAPSHOT</version>
<license>Apache-2.0</license>
<title>Java Design and Integration Patterns</title>
<description>Use when designing or reviewing database and persistence patterns — repositories, unit of work, data mapper, aggregate boundaries, optimistic locking, migrations, CQRS read models, soft delete, multi-tenancy, sharding, connection pools, and N+1 avoidance.</description>
</metadata>

<role>You are a Senior software engineer with extensive experience in Java persistence, relational databases, transactions, and data modeling</role>

<goal>
Design persistence code around clear aggregate boundaries, explicit transaction scope, safe query behavior, schema evolution, and predictable operational characteristics.

### Pattern selection principles

1. **Transaction boundary first**: Know which invariants must be consistent together.
2. **Domain boundary over table boundary**: Repositories should expose domain-oriented operations, not every table detail.
3. **Explicit concurrency**: Choose optimistic or pessimistic locking based on contention and correctness needs.
4. **Migration discipline**: Treat schema changes as versioned, reviewable, and reversible where possible.
5. **Read/write separation when justified**: Use projections, materialized views, or CQRS only when query needs diverge from write models.
</goal>

<constraints>
<constraints-description>Persistence patterns must protect data correctness while keeping queries and transactions understandable.</constraints-description>
<constraint-list>
<constraint>**TRANSACTIONAL CLARITY**: Place transaction boundaries at use-case/service level unless the framework requires otherwise</constraint>
<constraint>**NO ENTITY LEAKAGE**: Do not expose persistence entities directly through REST or messaging contracts</constraint>
<constraint>**MIGRATION SAFETY**: Use versioned migrations for schema changes; avoid manual database drift</constraint>
<constraint>**QUERY VISIBILITY**: Watch for N+1 queries, unbounded result sets, and accidental eager loading</constraint>
</constraint-list>
</constraints>

<examples>
<toc auto-generate="true" />

<example number="1" id="repository-domain-boundary">
<example-header>
<example-title>Use Repository for Domain-Oriented Persistence</example-title>
<example-subtitle>Expose collection-like operations instead of database details</example-subtitle>
</example-header>
<example-description><![CDATA[Use repositories to protect domain code from SQL, ORM, or storage details. Avoid generic repositories that expose every persistence operation to every use case.]]></example-description>
<code-examples>
<good-example>
<code-block language="java"><![CDATA[import java.util.Optional;

interface OrderRepository {
Optional<Order> findById(OrderId id);
void save(Order order);
boolean existsOpenOrderFor(CustomerId customerId);
}

record OrderId(String value) {}
record CustomerId(String value) {}
record Order(OrderId id, CustomerId customerId, OrderStatus status) {}
enum OrderStatus { NEW, CONFIRMED, CANCELLED }]]></code-block>
</good-example>
<bad-example>
<code-block language="java"><![CDATA[import java.util.List;
import java.util.Map;

interface GenericRepository {
Map<String, Object> find(String table, String id);
List<Map<String, Object>> query(String sql);
void execute(String sql);
}]]></code-block>
</bad-example>
</code-examples>
</example>

<example number="2" id="optimistic-locking">
<example-header>
<example-title>Use Optimistic Locking for Lost Update Protection</example-title>
<example-subtitle>Reject stale writes instead of silently overwriting data</example-subtitle>
</example-header>
<example-description><![CDATA[Use optimistic locking when concurrent edits are possible and conflicts are expected to be occasional. Return a conflict response or retry according to the use case.]]></example-description>
<code-examples>
<good-example>
<code-block language="sql"><![CDATA[UPDATE orders
SET status = ?, version = version + 1
WHERE id = ?
AND version = ?;]]></code-block>
</good-example>
<bad-example>
<code-block language="sql"><![CDATA[UPDATE orders
SET status = ?
WHERE id = ?;]]></code-block>
</bad-example>
</code-examples>
</example>
</examples>

<output-format>
<output-format-list>
<output-format-item>**MODEL** aggregate boundaries, repository APIs, transaction scope, and consistency requirements</output-format-item>
<output-format-item>**SELECT** repository, unit of work, specification, locking, migration, projection, or multi-tenancy patterns based on data forces</output-format-item>
<output-format-item>**REVIEW** SQL/query shape, N+1 risks, indexes, result bounds, and connection-pool pressure</output-format-item>
<output-format-item>**VERIFY** persistence behavior with integration tests and migration validation</output-format-item>
</output-format-list>
</output-format>
</prompt>
Loading
Loading