[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6NQ0T4M8TRSS85DMNKW253Q":3,"skill-same:01M6NQ0T4M8TRSS85DMNKW253Q":81},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":43,"linkOnly":44,"markdownContent":45,"markdownBody":46,"frontMatter":47,"refName":55,"commitSha":56,"skillDirectory":57,"forksCount":14,"repositoryHtmlUrl":58,"repositoryHomepageUrl":59,"ownerHtmlUrl":60,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":61,"install":62,"resources":75},"01M6NQ0T4M8TRSS85DMNKW253Q","java-patterns",null,"Modern Java 17+ — records, sealed types, pattern matching, streams, Spring Boot. Use when writing or reviewing Java 17+ code, modernizing legacy Java, or working in Spring Boot services.","projectious-work\u002Fprocesskit","projectious-work","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F263889726?v=4","01M6N97TJJ118WQ35CHRV8RD0E","projectious.work","01M6N97TPWJPF0BMKYQ4PBY5W8",0,"MIT","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fengineering\u002Fjava-patterns\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],"java patterns","java","patterns","use","streams","types","records","pattern matching","matching","pattern","Legacy","writing","work","spring","engineering","services","spring boot","code","boot","2026-11-10 10:12:30",false,"---\nname: java-patterns\ndescription: |\n  Modern Java 17+ — records, sealed types, pattern matching, streams, Spring Boot. Use when writing or reviewing Java 17+ code, modernizing legacy Java, or working in Spring Boot services.\nmetadata:\n  processkit:\n    apiVersion: processkit.projectious.work\u002Fv2\n    id: SKILL-java-patterns\n    version: \"1.1.0\"\n    created: 2026-04-06T00:00:00Z\n    category: engineering\n---\n\n# Java Patterns\n\n## Intro\n\nModern Java leans on records, sealed types, pattern matching, and\nstreams. Prefer immutable data carriers, exhaustive switches, and\nconstructor injection over the Java-EE-era boilerplate.\n\n## Overview\n\n### Language features (17+)\n\nUse `record` for immutable data carriers — you get `equals`,\n`hashCode`, `toString` for free. Use `sealed` interfaces to restrict\nhierarchies and unlock exhaustive `switch`. Use pattern matching\nwith `instanceof` to skip casts. Use text blocks (`\"\"\"...\"\"\"`) for\nmulti-line strings. Prefer `var` for locals when the right-hand\nside makes the type obvious.\n\n### Records and sealed classes\n\nRecords replace boilerplate DTOs. Validate in the compact\nconstructor:\n\n```java\nrecord Age(int value) {\n    Age {\n        if (value \u003C 0) throw new IllegalArgumentException();\n    }\n}\n```\n\nSealed hierarchies plus records create algebraic data types:\n\n```java\nsealed interface Result\u003CT> permits Success, Failure {}\nrecord Success\u003CT>(T value) implements Result\u003CT> {}\nrecord Failure\u003CT>(String error) implements Result\u003CT> {}\n```\n\nCombined with pattern-matching `switch`, the compiler enforces\nexhaustiveness — adding a variant breaks the build at every\nconsumer.\n\n### Stream API\n\nUse streams for transformations, not side effects. Prefer `toList()`\n(Java 16+) over `Collectors.toList()`. The common pipeline is\n`filter → map → collect`. Use `flatMap` to flatten nested\ncollections and `groupingBy`\u002F`partitioningBy` for aggregation. Drop\nback to a `for` loop when it reads more clearly than a stream.\n\n### Optional\n\nReturn `Optional\u003CT>` from methods that may not produce a result.\nNever use `Optional` as a field or parameter type. Chain with `map`,\n`flatMap`, and `filter` rather than `isPresent()` + `get()`. Use\n`orElseThrow(() -> new NotFoundException(...))` for required values\nand `Optional.empty()` instead of returning `null`.\n\n### Spring Boot conventions\n\nUse constructor injection, not field injection with `@Autowired`.\nKeep controllers thin — validate input, delegate to service, return\na response. Put `@Transactional` on the service layer, not the\ncontroller. Configure via `application.yml` with typed\n`@ConfigurationProperties` classes and environment-specific\nprofiles. Return `ResponseEntity\u003CT>` for explicit status codes and\ncentralize error handling in `@RestControllerAdvice`.\n\n### Testing\n\nUse JUnit 5 with `@DisplayName` for readable output. Use\n`@ParameterizedTest` with `@CsvSource` or `@MethodSource` for\ndata-driven cases. Mock with `@Mock` and `@ExtendWith(MockitoExtension.class)`\nrather than the legacy runner. Use AssertJ's fluent assertions\n(`assertThat(result).isEqualTo(expected)`). Use Spring test slices\n— `@WebMvcTest` for controllers, `@DataJpaTest` for repositories —\nto keep tests fast.\n\n## Gotchas\n\nAgent-specific failure modes — provider-neutral pause-and-self-check items:\n\n- **Field injection with `@Autowired` on fields.** Field injection hides dependencies, prevents immutability, and requires Spring's reflection to construct the object — making unit tests without Spring painful. Use constructor injection for all mandatory dependencies.\n- **`Optional.get()` without checking presence.** Calling `.get()` on an empty `Optional` throws `NoSuchElementException` — the same crash you were trying to avoid with null. Use `.orElseThrow(() -> new NotFoundException(...))` or `.ifPresent(...)` instead.\n- **Streams for trivial iteration.** A stream over a single-step `for` loop adds indirection and hurts readability. Use a `for` loop when it's clearer; reach for streams only when the pipeline — `filter → map → collect` — adds genuine expressiveness.\n- **Wide `@Transactional` on controllers.** Transactions should span a single unit of work inside the service layer. Annotating a controller method `@Transactional` creates a transaction that outlives the database interaction and crosses HTTP concern boundaries.\n- **Deep inheritance hierarchies over sealed types.** Adding a new subclass to an open hierarchy requires updating every consumer that switches on type. Model closed sets with sealed interfaces and pattern-matching `switch`; the compiler enforces exhaustiveness.\n- **`Collectors.toList()` on Java 16+.** The `Collectors.toList()` method returns a mutable list; `Stream.toList()` (Java 16+) returns an unmodifiable list and is shorter to write. Prefer `toList()` unless you need mutability.\n- **`Optional` as a field or method parameter.** `Optional` is designed for return types only. Using it as a field adds boxing overhead and breaks serialization; using it as a parameter forces callers to wrap values unnecessarily. Use overloads or nullable with explicit documentation for parameters.\n\n## Full reference\n\n### Dependency injection\n\nPrefer constructor injection — it makes dependencies explicit and\nenables testing without Spring. Inject interfaces, not concrete\nimplementations. Use `@Qualifier` or custom annotations to\ndisambiguate multiple beans. If a constructor has more than ~5\nparameters, the class is probably doing too much — split it.\n\n### Code organization\n\nPackage by feature (`com.app.order`, `com.app.user`), not by layer\n(`com.app.controllers`, `com.app.services`). Keep one primary\nresponsibility per class. Mark classes and fields `final` when you\nmean them to be immutable. Prefer composition and interfaces over\ndeep inheritance. For larger systems, use `module-info.java` to\nenforce explicit module boundaries.\n\n### Pattern matching switch\n\n```java\nString describe(Shape s) {\n    return switch (s) {\n        case Circle c    -> \"circle r=\" + c.radius();\n        case Rectangle r -> \"rect \" + r.width() + \"x\" + r.height();\n    };\n}\n```\n\nWith a sealed hierarchy, the compiler requires every permitted\ntype to be handled — no `default` branch needed.\n\n### Anti-patterns\n\n- Field injection with `@Autowired` — hides dependencies and\n  requires reflection to test.\n- `Optional` parameters or fields — use overloads or nullable with\n  documentation instead.\n- `.get()` on `Optional` without checking presence — use\n  `orElseThrow`.\n- Streams for trivial iteration where a `for` loop is clearer.\n- Deep inheritance hierarchies of abstract classes — prefer\n  composition and interfaces.\n- Wide `@Transactional` annotations on controllers that cross\n  business operations.\n- `Collectors.toList()` on Java 16+ — use `toList()`.\n\n### Common migrations\n\n- POJO with getters\u002Fsetters and equals\u002FhashCode → `record`.\n- Visitor pattern over an open hierarchy → sealed interface +\n  pattern-matching switch.\n- `if\u002Felse if` instanceof chains → pattern matching instanceof.\n- Manual null-checks → `Optional` chains.\n- Reflection-based DTO mappers between layers → records with\n  explicit conversion methods.\n","# Java Patterns\n\n## Intro\n\nModern Java leans on records, sealed types, pattern matching, and\nstreams. Prefer immutable data carriers, exhaustive switches, and\nconstructor injection over the Java-EE-era boilerplate.\n\n## Overview\n\n### Language features (17+)\n\nUse `record` for immutable data carriers — you get `equals`,\n`hashCode`, `toString` for free. Use `sealed` interfaces to restrict\nhierarchies and unlock exhaustive `switch`. Use pattern matching\nwith `instanceof` to skip casts. Use text blocks (`\"\"\"...\"\"\"`) for\nmulti-line strings. Prefer `var` for locals when the right-hand\nside makes the type obvious.\n\n### Records and sealed classes\n\nRecords replace boilerplate DTOs. Validate in the compact\nconstructor:\n\n```java\nrecord Age(int value) {\n    Age {\n        if (value \u003C 0) throw new IllegalArgumentException();\n    }\n}\n```\n\nSealed hierarchies plus records create algebraic data types:\n\n```java\nsealed interface Result\u003CT> permits Success, Failure {}\nrecord Success\u003CT>(T value) implements Result\u003CT> {}\nrecord Failure\u003CT>(String error) implements Result\u003CT> {}\n```\n\nCombined with pattern-matching `switch`, the compiler enforces\nexhaustiveness — adding a variant breaks the build at every\nconsumer.\n\n### Stream API\n\nUse streams for transformations, not side effects. Prefer `toList()`\n(Java 16+) over `Collectors.toList()`. The common pipeline is\n`filter → map → collect`. Use `flatMap` to flatten nested\ncollections and `groupingBy`\u002F`partitioningBy` for aggregation. Drop\nback to a `for` loop when it reads more clearly than a stream.\n\n### Optional\n\nReturn `Optional\u003CT>` from methods that may not produce a result.\nNever use `Optional` as a field or parameter type. Chain with `map`,\n`flatMap`, and `filter` rather than `isPresent()` + `get()`. Use\n`orElseThrow(() -> new NotFoundException(...))` for required values\nand `Optional.empty()` instead of returning `null`.\n\n### Spring Boot conventions\n\nUse constructor injection, not field injection with `@Autowired`.\nKeep controllers thin — validate input, delegate to service, return\na response. Put `@Transactional` on the service layer, not the\ncontroller. Configure via `application.yml` with typed\n`@ConfigurationProperties` classes and environment-specific\nprofiles. Return `ResponseEntity\u003CT>` for explicit status codes and\ncentralize error handling in `@RestControllerAdvice`.\n\n### Testing\n\nUse JUnit 5 with `@DisplayName` for readable output. Use\n`@ParameterizedTest` with `@CsvSource` or `@MethodSource` for\ndata-driven cases. Mock with `@Mock` and `@ExtendWith(MockitoExtension.class)`\nrather than the legacy runner. Use AssertJ's fluent assertions\n(`assertThat(result).isEqualTo(expected)`). Use Spring test slices\n— `@WebMvcTest` for controllers, `@DataJpaTest` for repositories —\nto keep tests fast.\n\n## Gotchas\n\nAgent-specific failure modes — provider-neutral pause-and-self-check items:\n\n- **Field injection with `@Autowired` on fields.** Field injection hides dependencies, prevents immutability, and requires Spring's reflection to construct the object — making unit tests without Spring painful. Use constructor injection for all mandatory dependencies.\n- **`Optional.get()` without checking presence.** Calling `.get()` on an empty `Optional` throws `NoSuchElementException` — the same crash you were trying to avoid with null. Use `.orElseThrow(() -> new NotFoundException(...))` or `.ifPresent(...)` instead.\n- **Streams for trivial iteration.** A stream over a single-step `for` loop adds indirection and hurts readability. Use a `for` loop when it's clearer; reach for streams only when the pipeline — `filter → map → collect` — adds genuine expressiveness.\n- **Wide `@Transactional` on controllers.** Transactions should span a single unit of work inside the service layer. Annotating a controller method `@Transactional` creates a transaction that outlives the database interaction and crosses HTTP concern boundaries.\n- **Deep inheritance hierarchies over sealed types.** Adding a new subclass to an open hierarchy requires updating every consumer that switches on type. Model closed sets with sealed interfaces and pattern-matching `switch`; the compiler enforces exhaustiveness.\n- **`Collectors.toList()` on Java 16+.** The `Collectors.toList()` method returns a mutable list; `Stream.toList()` (Java 16+) returns an unmodifiable list and is shorter to write. Prefer `toList()` unless you need mutability.\n- **`Optional` as a field or method parameter.** `Optional` is designed for return types only. Using it as a field adds boxing overhead and breaks serialization; using it as a parameter forces callers to wrap values unnecessarily. Use overloads or nullable with explicit documentation for parameters.\n\n## Full reference\n\n### Dependency injection\n\nPrefer constructor injection — it makes dependencies explicit and\nenables testing without Spring. Inject interfaces, not concrete\nimplementations. Use `@Qualifier` or custom annotations to\ndisambiguate multiple beans. If a constructor has more than ~5\nparameters, the class is probably doing too much — split it.\n\n### Code organization\n\nPackage by feature (`com.app.order`, `com.app.user`), not by layer\n(`com.app.controllers`, `com.app.services`). Keep one primary\nresponsibility per class. Mark classes and fields `final` when you\nmean them to be immutable. Prefer composition and interfaces over\ndeep inheritance. For larger systems, use `module-info.java` to\nenforce explicit module boundaries.\n\n### Pattern matching switch\n\n```java\nString describe(Shape s) {\n    return switch (s) {\n        case Circle c    -> \"circle r=\" + c.radius();\n        case Rectangle r -> \"rect \" + r.width() + \"x\" + r.height();\n    };\n}\n```\n\nWith a sealed hierarchy, the compiler requires every permitted\ntype to be handled — no `default` branch needed.\n\n### Anti-patterns\n\n- Field injection with `@Autowired` — hides dependencies and\n  requires reflection to test.\n- `Optional` parameters or fields — use overloads or nullable with\n  documentation instead.\n- `.get()` on `Optional` without checking presence — use\n  `orElseThrow`.\n- Streams for trivial iteration where a `for` loop is clearer.\n- Deep inheritance hierarchies of abstract classes — prefer\n  composition and interfaces.\n- Wide `@Transactional` annotations on controllers that cross\n  business operations.\n- `Collectors.toList()` on Java 16+ — use `toList()`.\n\n### Common migrations\n\n- POJO with getters\u002Fsetters and equals\u002FhashCode → `record`.\n- Visitor pattern over an open hierarchy → sealed interface +\n  pattern-matching switch.\n- `if\u002Felse if` instanceof chains → pattern matching instanceof.\n- Manual null-checks → `Optional` chains.\n- Reflection-based DTO mappers between layers → records with\n  explicit conversion methods.\n",{"name":5,"metadata":48,"description":54},{"processkit":49},{"id":50,"created":51,"version":52,"category":38,"apiVersion":53},"SKILL-java-patterns",1775433600000,"1.1.0","processkit.projectious.work\u002Fv2","Modern Java 17+ — records, sealed types, pattern matching, streams, Spring Boot. Use when writing or reviewing Java 17+ code, modernizing legacy Java, or working in Spring Boot services.\n","main","7231f100e266e30d2c1699ecde5c00602471dc3c","src\u002Fcontext\u002Fskills\u002Fengineering\u002Fjava-patterns","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit","https:\u002F\u002Fprojectious-work.github.io\u002Fprocesskit\u002F","https:\u002F\u002Fgithub.com\u002Fprojectious-work","2026-11-11 23:24:18",{"source":8,"skillName":5,"commands":63,"prompt":73,"zipAvailable":74},[64,67,70],{"tool":65,"command":66},"npx","npx skills add projectious-work\u002Fprocesskit --skill java-patterns",{"tool":68,"command":69},"bunx","bunx skills add projectious-work\u002Fprocesskit --skill java-patterns",{"tool":71,"command":72},"pnpm","pnpm dlx skills add projectious-work\u002Fprocesskit --skill java-patterns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fengineering\u002Fjava-patterns\u002FSKILL.md",true,[76],{"path":77,"resourceType":78,"resourceTypeDesc":79,"sizeBytes":14,"sourceHtmlUrl":80},"scripts\u002F.gitkeep","SCRIPT","脚本","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fengineering\u002Fjava-patterns\u002Fscripts\u002F.gitkeep",[82,109,129,150,167,185],{"skillNo":83,"name":84,"nameZh":6,"description":85,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":86,"categories":87,"keywords":93,"publishedAt":43},"01M6X5MTC89B4ZGXW3JVSQCPF8","skill-management","Manage Skill package manifests as v1 ontology entities.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fskill-management\u002FSKILL.md",[88],{"categoryNo":89,"categoryName":90,"taxonomyType":91,"taxonomyTypeDesc":92},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[94,95,96,97,98,99,36,100,101,102,84,103,104,105,106,107,108],"management","skill management","create","update","package","alpha","list","manage","ontology","get","as","manifests","v1","skill package","transition",{"skillNo":110,"name":111,"nameZh":6,"description":112,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":113,"categories":114,"keywords":116,"publishedAt":43},"01M6X5MCV74NHW5MEDNHZRF2C8","schema-management","Manage generated processkit schema contracts through deterministic MCP rebuild and inspection workflows.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fschema-management\u002FSKILL.md",[115],{"categoryNo":89,"categoryName":90,"taxonomyType":91,"taxonomyTypeDesc":92},[94,117,118,119,120,121,99,36,122,123,101,124,125,126,103,127,128],"schema","schema management","MCP","workflows","validation","generated","rebuild","contracts","wed","deterministic","contract","mode",{"skillNo":130,"name":131,"nameZh":6,"description":132,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":133,"categories":134,"keywords":135,"publishedAt":43},"01M6X5M5G6YJ96AMZGSCZJ1D13","proposition-management","Record claims, risks, beliefs, world facts, WSJF estimates, and assumptions through the Proposition interface.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fproposition-management\u002FSKILL.md",[],[94,136,137,96,97,138,99,36,139,140,141,142,103,143,144,145,146,147,148,149],"proposition","proposition management","index","log","world","record","query","creation","event","interface","updates","facts","claims","WSJF",{"skillNo":151,"name":152,"nameZh":6,"description":153,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":154,"categories":155,"keywords":156,"publishedAt":43},"01M6X5KMQ83QN9M6MPWZM7344F","ontology-management","Manage generated v1 ontology entities that do not require a dedicated domain server.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fontology-management\u002FSKILL.md",[],[94,102,157,96,99,158,159,122,160,139,101,161,162,103,163,164,144,165,106,166],"ontology management","lifecycle","archive","roadmap","do","domain","iteration","keep","measurement","generic",{"skillNo":168,"name":169,"nameZh":6,"description":170,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":171,"categories":172,"keywords":173,"publishedAt":43},"01M6X5KCY2DN3SM21RERSFNEBT","okf-compatibility","Import, export, and validate conformant Open Knowledge Format bundles.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fokf-compatibility\u002FSKILL.md",[],[174,175,176,177,99,178,179,180,36,181,182,183,184],"okf","compatibility","okf compatibility","validate","open","knowledge","format","export","bundles","bundle","import",{"skillNo":186,"name":187,"nameZh":6,"description":188,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":189,"categories":190,"keywords":191,"publishedAt":43},"01M6X5JA8S5PNGJVFW4EQY8T83","capability-management","Manage versioned Capability entities and their governed lifecycle.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fcapability-management\u002FSKILL.md",[],[94,192,193,96,97,138,99,158,36,100,139,194,101,141,103,164,144,145,195,108],"capability","capability management","queries","changes"]