skills/languages/java-patterns/SKILL.md
Comprehensive Java 17+ patterns for Spring Boot services — idioms, JPA, REST, Security (JWT/OAuth2), TDD, and verification.
npx skillsauth add bereniketech/claude_kit java-patternsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Production-grade Java 17+ patterns for Spring Boot services covering code standards, data access, REST APIs, security, and testing.
Use records for immutable DTOs, prefer final fields, and keep methods short and focused.
// Records for data carriers
public record MarketDto(Long id, String name, MarketStatus status) {}
// PascalCase classes, camelCase methods/fields, UPPER_SNAKE_CASE constants
private static final int MAX_PAGE_SIZE = 100;
private final MarketRepository marketRepository;
Use Optional with map/flatMap — never call .get() directly:
return marketRepository.findBySlug(slug)
.map(MarketResponse::from)
.orElseThrow(() -> new MarketNotFoundException(slug));
Use streams for transformations; keep pipelines short:
List<String> names = markets.stream()
.map(Market::name)
.filter(Objects::nonNull)
.toList();
Rule: Throw domain-specific unchecked exceptions (MarketNotFoundException), never broad catch (Exception ex) unless rethrowing centrally. Use @NotNull/@NonNull on inputs; use @Nullable only when unavoidable.
Project layout:
src/main/java/com/example/app/
config/ controller/ service/ repository/ domain/ dto/ util/
src/test/java/... (mirrors main)
Annotate entities with @Table indexes, use @Enumerated(EnumType.STRING), and enable JPA auditing:
@Entity
@Table(name = "markets", indexes = {
@Index(name = "idx_markets_slug", columnList = "slug", unique = true)
})
@EntityListeners(AuditingEntityListener.class)
public class MarketEntity {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true, length = 120)
private String slug;
@Enumerated(EnumType.STRING)
private MarketStatus status = MarketStatus.ACTIVE;
@CreatedDate private Instant createdAt;
@LastModifiedDate private Instant updatedAt;
}
Default to lazy loading; use JOIN FETCH to prevent N+1:
@Query("select m from MarketEntity m left join fetch m.positions where m.id = :id")
Optional<MarketEntity> findWithPositions(@Param("id") Long id);
Use projections for lightweight reads:
public interface MarketSummary { Long getId(); String getName(); MarketStatus getStatus(); }
Page<MarketSummary> findAllBy(Pageable pageable);
Paginate with PageRequest:
PageRequest page = PageRequest.of(pageNumber, pageSize, Sort.by("createdAt").descending());
Page<MarketEntity> markets = repo.findByStatus(MarketStatus.ACTIVE, page);
Rule: Use Flyway or Liquibase for migrations — never rely on Hibernate auto DDL in production. Add composite indexes matching query patterns (status, created_at). Configure HikariCP: maximum-pool-size=20, minimum-idle=5.
Keep controllers thin; inject services via constructor injection only:
@RestController
@RequestMapping("/api/markets")
@Validated
class MarketController {
private final MarketService marketService;
MarketController(MarketService marketService) { this.marketService = marketService; }
@GetMapping
ResponseEntity<Page<MarketResponse>> list(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size) {
return ResponseEntity.ok(marketService.list(PageRequest.of(page, size)).map(MarketResponse::from));
}
@PostMapping
ResponseEntity<MarketResponse> create(@Valid @RequestBody CreateMarketRequest request) {
return ResponseEntity.status(HttpStatus.CREATED).body(MarketResponse.from(marketService.create(request)));
}
}
Annotate service methods with @Transactional; use readOnly = true for reads:
@Service
public class MarketService {
@Transactional
public Market create(CreateMarketRequest request) { ... }
@Transactional(readOnly = true)
public Page<Market> list(Pageable pageable) { ... }
}
Handle exceptions centrally:
@ControllerAdvice
class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
ResponseEntity<ApiError> handleValidation(MethodArgumentNotValidException ex) {
String message = ex.getBindingResult().getFieldErrors().stream()
.map(e -> e.getField() + ": " + e.getDefaultMessage())
.collect(Collectors.joining(", "));
return ResponseEntity.badRequest().body(ApiError.validation(message));
}
@ExceptionHandler(Exception.class)
ResponseEntity<ApiError> handleGeneric(Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ApiError.of("Internal server error"));
}
}
Rule: Enable spring.mvc.problemdetails.enabled=true (Spring Boot 3+). Use @Async + @EnableAsync for fire-and-forget operations. Prefer constructor injection — avoid field injection.
Validate JWT tokens in a filter; set SecurityContextHolder before chain proceeds:
@Component
public class JwtAuthFilter extends OncePerRequestFilter {
private final JwtService jwtService;
public JwtAuthFilter(JwtService jwtService) { this.jwtService = jwtService; }
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
String header = request.getHeader(HttpHeaders.AUTHORIZATION);
if (header != null && header.startsWith("Bearer ")) {
Authentication auth = jwtService.authenticate(header.substring(7));
SecurityContextHolder.getContext().setAuthentication(auth);
}
chain.doFilter(request, response);
}
}
Enable method security and deny by default:
@EnableMethodSecurity
// In controller:
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/users")
public List<UserDto> listUsers() { ... }
Configure CORS at the security filter level, not per-controller:
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("https://app.example.com"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/api/**", config);
return source;
}
Always hash passwords with BCrypt (cost factor 12):
@Bean
public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(12); }
Rule: No secrets in source — use ${DB_PASSWORD} env placeholders or Spring Cloud Vault. Never concatenate strings in SQL queries — use :param bindings. Disable CSRF for stateless Bearer-token APIs; keep enabled for browser session apps. Never log secrets, tokens, or PAN data.
Follow RED → GREEN → REFACTOR. Write the test first, make it fail, implement the minimum to pass:
@ExtendWith(MockitoExtension.class)
class MarketServiceTest {
@Mock MarketRepository repo;
@InjectMocks MarketService service;
@Test
void createsMarket() {
when(repo.save(any())).thenAnswer(inv -> inv.getArgument(0));
Market result = service.create(new CreateMarketRequest("name", "desc", Instant.now(), List.of("cat")));
assertThat(result.name()).isEqualTo("name");
verify(repo).save(any());
}
@Test
void throwsWhenNotFound() {
when(repo.findBySlug("x")).thenReturn(Optional.empty());
assertThatThrownBy(() -> service.findBySlug("x"))
.isInstanceOf(MarketNotFoundException.class);
}
}
Test the web layer with @WebMvcTest:
@WebMvcTest(MarketController.class)
class MarketControllerTest {
@Autowired MockMvc mockMvc;
@MockBean MarketService marketService;
@Test
void returnsCreated() throws Exception {
when(marketService.create(any())).thenReturn(new Market(1L, "Test", MarketStatus.ACTIVE));
mockMvc.perform(post("/api/markets")
.contentType(MediaType.APPLICATION_JSON)
.content("""{"name":"Test","description":"Desc","endDate":"2030-01-01T00:00:00Z","categories":["general"]}"""))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.name").value("Test"));
}
}
Rule: Prefer AssertJ (assertThat) over JUnit assertions. Use @ParameterizedTest for input variants. Avoid partial mocks; prefer explicit stubbing. Target 80%+ coverage enforced via JaCoCo.
Use Testcontainers for real database tests:
@SpringBootTest
@Testcontainers
class UserRepositoryIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine");
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
@Autowired private UserRepository userRepository;
@Test
void findByEmail_existingUser_returnsUser() {
userRepository.save(new User("Alice", "[email protected]"));
assertThat(userRepository.findByEmail("[email protected]")).isPresent();
}
}
Run the full verification pipeline before PRs:
# 1. Build
mvn -T 4 clean verify -DskipTests
# 2. Static analysis
mvn -T 4 spotbugs:check pmd:check checkstyle:check
# 3. Tests + coverage
mvn -T 4 test && mvn jacoco:report # verify 80%+
# 4. Security scan
mvn org.owasp:dependency-check-maven:check
# 5. Format
mvn spotless:apply
Rule: Use @DataJpaTest with @AutoConfigureTestDatabase(replace = NONE) + Testcontainers to mirror production. Run ASan/sanitizer equivalents (SpotBugs, PMD) as part of CI. Treat warnings as defects in production systems.
testing
AUTHORIZED USE ONLY: This skill contains dual-use security techniques. Before proceeding with any bypass or analysis: > 1.
testing
Provide comprehensive techniques for attacking Microsoft Active Directory environments. Covers reconnaissance, credential harvesting, Kerberos attacks, lateral movement, privilege escalation, and domain dominance for red team operations and penetration testing.
development
Detects missing zeroization of sensitive data in source code and identifies zeroization removed by compiler optimizations, with assembly-level analysis, and control-flow verification. Use for auditing C/C++/Rust code handling secrets, keys, passwords, or other sensitive data.
development
Comprehensive guide to auditing web content against WCAG 2.2 guidelines with actionable remediation strategies.