Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Spring Conventions

ASecurity

Spring Boot coding conventions: REST controller design, service layer, dependency injection, configuration, DTO patterns, exception handling, and Bean Validation. Apply on any Spring Boot project. Works alongside spring-boot-plugin:spring-data-jpa for persistence and java-foundation:java-conventions for domain objects. Use this skill to: - Structure REST endpoints with @RestController, proper HTTP semantics, and DTO mapping. - Enforce constructor injection and @ConfigurationProperties over @...

35 stars
0 votes
0 copies
0 views
Added 9/22/2026
developmentjavaspringtestingapisecurity

Works with

api

Security Analysis

A100/100

Scanned 9/22/2026

Install to Claude Code

$npx -y skills add AratKruglik/claude-sdlc --skill spring-conventions --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Spring Conventions?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Spring Conventions
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/aratkruglik-spring-conventions/badge)](https://www.skillsdirectory.com/skills/aratkruglik-spring-conventions)

More formats (shields.io, HTML) on the badges page.

Download with Pro
Files
SKILL.md
---
name: spring-conventions
description: |
  Spring Boot coding conventions: REST controller design, service layer, dependency injection, configuration, DTO patterns, exception handling, and Bean Validation. Apply on any Spring Boot project. Works alongside spring-boot-plugin:spring-data-jpa for persistence and java-foundation:java-conventions for domain objects.

  Use this skill to:
  - Structure REST endpoints with @RestController, proper HTTP semantics, and DTO mapping.
  - Enforce constructor injection and @ConfigurationProperties over @Value on fields.
  - Write @Service classes with transactional boundaries at the right layer.
  - Handle errors consistently with @RestControllerAdvice and ProblemDetail (RFC 9457).

  Do NOT use this skill for:
  - JPA entity and repository patterns — see spring-boot-plugin:spring-data-jpa.
  - Spring Security configuration — see the security phase injection in stack.md.
  - Build tool configuration — see java-foundation:build-tooling.
user-invocable: false
paths: ["src/main/java/**", "src/main/resources/**"]
---

# Spring Boot Conventions

## REST Controller design

```java
@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor            // Lombok — generates constructor for final fields
public class UserController {

    private final UserService userService;

    @GetMapping("/{id}")
    public UserResponse getById(@PathVariable Long id) {
        return userService.findById(id)
            .orElseThrow(() -> new EntityNotFoundException("User", id));
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public UserResponse create(@RequestBody @Valid CreateUserRequest request) {
        return userService.create(request);
    }

    @PutMapping("/{id}")
    public UserResponse update(@PathVariable Long id,
                               @RequestBody @Valid UpdateUserRequest request) {
        return userService.update(id, request);
    }

    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void delete(@PathVariable Long id) {
        userService.delete(id);
    }
}
```

**Return DTO directly** (not `ResponseEntity<T>`) unless you need explicit control over headers or status codes beyond `@ResponseStatus`. `ResponseEntity` is valid for partial-update responses (202 Accepted + Location header) or conditional-GET (`ETag` / `If-None-Match`).

**HTTP semantics:**
- `GET` — idempotent, no body.
- `POST` — create, return `201 Created` + new resource.
- `PUT` — replace entire resource, return `200 OK` with updated resource.
- `PATCH` — partial update.
- `DELETE` — return `204 No Content`.

## DTO patterns

```java
// Request DTO — mutable, with Bean Validation
public record CreateUserRequest(
    @NotBlank @Email String email,
    @NotBlank @Size(min = 8) String password,
    @NotNull Role role
) {}

// Response DTO — immutable record, projection of domain data
public record UserResponse(
    Long id,
    String email,
    Role role,
    Instant createdAt
) {
    public static UserResponse from(User user) {
        return new UserResponse(user.id(), user.getEmail(), user.getRole(), user.getCreatedAt());
    }
}
```

**Separate request and response types.** Never expose the JPA entity directly from the controller — it leaks schema details and creates bidirectional serialization issues.

Use **static factory methods** (`from(Entity)`) on response records for clean mapping without a mapper library when the mapping is trivial. For complex mappings with many fields, introduce a `UserMapper` interface and implement with MapStruct or plain Java.

## Service layer

```java
@Service
@Transactional(readOnly = true)     // Default to read-only; override on write methods
@RequiredArgsConstructor
public class UserService {

    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;

    public Optional<UserResponse> findById(Long id) {
        return userRepository.findById(id).map(UserResponse::from);
    }

    @Transactional
    public UserResponse create(CreateUserRequest request) {
        if (userRepository.existsByEmail(request.email())) {
            throw new DuplicateEmailException(request.email());
        }
        var user = new User(request.email(), passwordEncoder.encode(request.password()), request.role());
        return UserResponse.from(userRepository.save(user));
    }

    @Transactional
    public void delete(Long id) {
        var user = userRepository.findById(id)
            .orElseThrow(() -> new EntityNotFoundException("User", id));
        userRepository.delete(user);
    }
}
```

`@Transactional(readOnly = true)` on the class sets a safe default; `@Transactional` on write methods overrides it. Avoid `@Transactional` on controllers — it spans too wide a scope and complicates error handling.

## Constructor injection

```java
// Prefer (with Lombok @RequiredArgsConstructor or explicit constructor)
@Service
public class OrderService {

    private final OrderRepository orderRepository;
    private final InvoiceService invoiceService;

    public OrderService(OrderRepository orderRepository, InvoiceService invoiceService) {
        this.orderRepository = orderRepository;
        this.invoiceService = invoiceService;
    }
}

// Avoid — field injection hides dependencies and makes testing harder
@Service
public class OrderService {
    @Autowired private OrderRepository orderRepository;  // DON'T
}
```

## Configuration with @ConfigurationProperties

```java
// application.yml
// app:
//   mail:
//     host: smtp.example.com
//     port: 587
//     from: noreply@example.com

@ConfigurationProperties(prefix = "app.mail")
public record MailProperties(String host, int port, String from) {}

// Register it
@SpringBootApplication
@EnableConfigurationProperties(MailProperties.class)
public class Application { ... }

// Inject like any bean
@Service
@RequiredArgsConstructor
public class MailService {
    private final MailProperties mailProperties;
}
```

Use `@ConfigurationProperties` records for any group of related configuration values. Avoid `@Value` on fields for groups — it scatters configuration and makes testing harder.

## Bean Validation on DTOs

```java
public record CreateProductRequest(
    @NotBlank(message = "name is required") String name,
    @NotNull @Positive BigDecimal price,
    @NotNull @Min(0) Integer stock,
    @NotBlank @Pattern(regexp = "[A-Z]{3}") String currencyCode
) {}
```

Activate in controllers with `@Valid` on `@RequestBody` / `@PathVariable` / `@ModelAttribute`. Spring Boot auto-configures `MethodArgumentNotValidException` handling — provide a `@RestControllerAdvice` to shape the error response.

## Error handling with @RestControllerAdvice

```java
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(EntityNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ProblemDetail handleNotFound(EntityNotFoundException ex) {
        var problem = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, ex.getMessage());
        problem.setTitle("Resource Not Found");
        return problem;
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
    public ProblemDetail handleValidation(MethodArgumentNotValidException ex) {
        var errors = ex.getBindingResult().getFieldErrors().stream()
            .map(e -> e.getField() + ": " + e.getDefaultMessage())
            .toList();
        var problem = ProblemDetail.forStatusAndDetail(
            HttpStatus.UNPROCESSABLE_ENTITY, "Validation failed");
        problem.setProperty("errors", errors);
        return problem;
    }
}
```

Use `ProblemDetail` (Spring Boot 3.x, RFC 9457) for structured error responses. For Spring Boot 2.x, return a custom `ErrorResponse` record.

## Domain exceptions

```java
public class EntityNotFoundException extends RuntimeException {
    public EntityNotFoundException(String entityName, Object id) {
        super(entityName + " not found: " + id);
    }
}

public class DuplicateEmailException extends RuntimeException {
    public DuplicateEmailException(String email) {
        super("Email already registered: " + email);
    }
}
```

Keep domain exceptions in a dedicated package (`exception` or `error`). Do not catch and re-throw `RuntimeException` unless translating (e.g., wrapping a JPA exception into a domain exception).

Attribution

AratKruglikAratKruglik
View sourceMore from AratKruglik →
SSkills DirectorySkills Directory

Know which skills are safe — weekly.

Best new skills + every skill we flagged as malicious. From the team that scanned 103,619.

Join free

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Know which skills are safe — weekly.

Best new skills + every skill we flagged as malicious. From the team that scanned 103,619.

Join free

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

284072 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2192 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →