

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
12345# Java Patterns67> This file extends [common/patterns.md](../common/patterns.md) with Java-specific content.89## Repository Pattern1011Encapsulate data access behind an interface:1213```java14public interface OrderRepository {15 Optional<Order> findById(Long id);16 List<Order> findAll();17 Order save(Order order);18 void deleteById(Long id);19}20```2122Concrete implementations handle storage details (JPA, JDBC, in-memory for tests).2324## Service Layer2526Business logic in service classes; keep controllers and repositories thin:2728```java29public class OrderService {30 private final OrderRepository orderRepository;31 private final PaymentGateway paymentGateway;3233 public OrderService(OrderRepository orderRepository, PaymentGateway paymentGateway) {34 this.orderRepository = orderRepository;35 this.paymentGateway = paymentGateway;36 }3738 public OrderSummary placeOrder(CreateOrderRequest request) {39 var order = Order.from(request);40 paymentGateway.charge(order.total());41 var saved = orderRepository.save(order);42 return OrderSummary.from(saved);43 }44}45```4647## Constructor Injection4849Always use constructor injection — never field injection:5051```java52// GOOD — constructor injection (testable, immutable)53public class NotificationService {54 private final EmailSender emailSender;5556 public NotificationService(EmailSender emailSender) {57 this.emailSender = emailSender;58 }59}6061// BAD — field injection (untestable without reflection, requires framework magic)62public class NotificationService {63 @Inject // or @Autowired64 private EmailSender emailSender;65}66```6768## DTO Mapping6970Use records for DTOs. Map at service/controller boundaries:7172```java73public record OrderResponse(Long id, String customer, BigDecimal total) {74 public static OrderResponse from(Order order) {75 return new OrderResponse(order.getId(), order.getCustomerName(), order.getTotal());76 }77}78```7980## Builder Pattern8182Use for objects with many optional parameters:8384```java85public class SearchCriteria {86 private final String query;87 private final int page;88 private final int size;89 private final String sortBy;9091 private SearchCriteria(Builder builder) {92 this.query = builder.query;93 this.page = builder.page;94 this.size = builder.size;95 this.sortBy = builder.sortBy;96 }9798 public static class Builder {99 private String query = "";100 private int page = 0;101 private int size = 20;102 private String sortBy = "id";103104 public Builder query(String query) { this.query = query; return this; }105 public Builder page(int page) { this.page = page; return this; }106 public Builder size(int size) { this.size = size; return this; }107 public Builder sortBy(String sortBy) { this.sortBy = sortBy; return this; }108 public SearchCriteria build() { return new SearchCriteria(this); }109 }110}111```112113## Sealed Types for Domain Models114115```java116public sealed interface PaymentResult permits PaymentSuccess, PaymentFailure {117 record PaymentSuccess(String transactionId, BigDecimal amount) implements PaymentResult {}118 record PaymentFailure(String errorCode, String message) implements PaymentResult {}119}120121// Exhaustive handling (Java 21+)122String message = switch (result) {123 case PaymentSuccess s -> "Paid: " + s.transactionId();124 case PaymentFailure f -> "Failed: " + f.errorCode();125};126```127128## API Response Envelope129130Consistent API responses:131132```java133public record ApiResponse<T>(boolean success, T data, String error) {134 public static <T> ApiResponse<T> ok(T data) {135 return new ApiResponse<>(true, data, null);136 }137 public static <T> ApiResponse<T> error(String message) {138 return new ApiResponse<>(false, null, message);139 }140}141```142143## References144145See skill: `springboot-patterns` for Spring Boot architecture patterns.146See skill: `jpa-patterns` for entity design and query optimization.147
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| ThanhTrunggDEV/DontBeLazy.cursor/rules/zh-agents.mdc · 6 | Cursor rules | no sections | 50/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/zh-patterns.mdc · 6 | Cursor rules | api | 30/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.agent/AGENTS.md · 6 | AGENTS.md | buildteststylearch+4 | 77/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/AGENTS.md · 6 | AGENTS.md | buildteststylearch+4 | 77/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/common-agents.mdc · 6 | Cursor rules | agent-behaviour | 50/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/common-code-review.mdc · 6 | Cursor rules | styletesting-strategygitsecurity+3 | 65/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/common-coding-style.mdc · 6 | Cursor rules | style | 54/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/common-development-workflow.mdc · 6 | Cursor rules | gitagent-behaviour | 39/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/common-git-workflow.mdc · 6 | Cursor rules | lint-formatgitagent-behaviour | 43/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/common-hooks.mdc · 6 | Cursor rules | styletypessecuritydo-not | 36/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/common-patterns.mdc · 6 | Cursor rules | lint-formatstyleapi | 52/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/common-performance.mdc · 6 | Cursor rules | buildperformance | 48/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/common-security.mdc · 6 | Cursor rules | security | 39/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/common-testing.mdc · 6 | Cursor rules | testtesting-strategyagent-behaviour | 34/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/cpp-coding-style.mdc · 6 | Cursor rules | lint-formatstyle | 52/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/cpp-hooks.mdc · 6 | Cursor rules | buildlint-formatdeployment | 60/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/cpp-patterns.mdc · 6 | Cursor rules | style | 54/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/cpp-security.mdc · 6 | Cursor rules | securityperformancedo-not | 73/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/cpp-testing.mdc · 6 | Cursor rules | testtesting-strategy | 55/100 | 14 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/csharp-coding-style.mdc · 6 | Cursor rules | lint-formatstyletypes | 66/100 | 14 days ago |
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126 | Cursor rules | setupbuildtestlint-format+6 | 100/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 45 | Cursor rules | testlint-formatstylearch+5 | 100/100 | 14 days ago | |
| dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| markstev/mark-starter.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+6 | 99/100 | 14 days ago | |
| Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| langflow-ai/langflow.cursor/rules/docs_development.mdc · 153k | Cursor rules | setupbuildtestlint-format+7 | 97/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 45 | Cursor rules | teststyletesting-strategysecurity+3 | 97/100 | 14 days ago |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/thanhtrunggdev-dontbelazy-cursor-rules-java-patterns)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.