dilipsundarraj1/kafka-for-developers-using-spring-boot-v2/controller-skills

Claude Code and agent skill by dilipsundarraj1/kafka-for-developers-using-spring-boot-v2

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

REST controller patterns for this Spring Boot Kafka consumer project, including CRUD endpoints and companion integration tests.

Install

npx vskill@latest install dilipsundarraj1/kafka-for-developers-using-spring-boot-v2/controller-skills

SKILL.md

Controller Skill

Scope: Creating a new REST controller with full CRUD operations and its companion integration-test class.
Read AGENTS.md first for project-wide conventions.

Technology Stack

ComponentValue
Spring Boot4.0.x
Java25
Web frameworkSpring WebMVC (spring-boot-starter-webmvc)
ValidationJakarta Bean Validation (spring-boot-starter-validation)
PersistenceSpring Data JPA + PostgreSQL
Schema managementFlyway (JPA ddl-auto: none)
JSON (app)Jackson 3 — tools.jackson.databind.ObjectMapper
JSON (Kafka runtime)Jackson 2 — com.fasterxml.jackson (only for Kafka serializer)
TestingJUnit 5 + MockMvc + Testcontainers (PostgreSQL)
MockMvc importorg.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc (Spring Boot 4.0 package)

Files to Create Per Controller

When adding a new controller for entity {Entity}, create all of the following:

#FilePackage / PathPurpose
1{Entity}Dto.javacom.learnkafka.dtoRequest DTO — Java record with bean-validation annotations
2{Entity}ResponseDto.javacom.learnkafka.dtoResponse DTO — Java record, includes audit fields + any FK IDs
3Mapper method(s) in LibraryEventMapper.javacom.learnkafka.dtoStatic to{Entity}Entity(dto) and to{Entity}ResponseDto(entity) methods
4{Entity}Repository.javacom.learnkafka.repositoryJpaRepository<{Entity}, {IdType}>
5{Entity}Service.javacom.learnkafka.serviceBusiness logic — findAll, findById, create, update, delete
6{Entity}Controller.javacom.learnkafka.controllerREST endpoints under /v1/{entities}
7Flyway migrationsrc/main/resources/db/migration/V{N}__create_{entity}.sqlDDL for the new table
8{Entity}ControllerIntegrationTest.javacom.learnkafka.controller (test)Full integration-test class

1. Request DTO — {Entity}Dto.java

  • Java record in com.learnkafka.dto.
  • Annotate fields with @NotNull, @NotBlank, etc. from jakarta.validation.constraints.
  • No audit fields — those are entity-only.
Template
java
package com.learnkafka.dto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
public record {Entity}Dto(
@NotNull
{IdType} {entityId},
@NotBlank
String {field1},
@NotBlank
String {field2}
) {
}
Reference — BookDto.java
java
public record BookDto(
@NotNull Integer bookId,
@NotBlank String bookName,
@NotBlank String bookAuthor
) {}

2. Response DTO — {Entity}ResponseDto.java

  • Java record in com.learnkafka.dto.
  • Includes all fields the client should see: entity fields + FK IDs + createdAt / updatedAt.
Template
java
package com.learnkafka.dto;
import java.time.LocalDateTime;
public record {Entity}ResponseDto(
{IdType} {entityId},
String {field1},
String {field2},
Integer libraryEventId, // FK reference (if applicable)
LocalDateTime createdAt,
LocalDateTime updatedAt
) {
}

3. Mapper — add methods to LibraryEventMapper.java

  • All mapping is manual static methods — no MapStruct.
  • Add two methods: to{Entity}Entity({Entity}Dto) and to{Entity}ResponseDto({Entity}).
Template additions
java
public static {Entity} to{Entity}Entity({Entity}Dto dto) {
return new {Entity}(dto.{entityId}(), dto.{field1}(), dto.{field2}());
}
public static {Entity}ResponseDto to{Entity}ResponseDto({Entity} entity) {
Integer libraryEventId = entity.getLibraryEvent() != null
? entity.getLibraryEvent().getLibraryEventId()
: null;
return new {Entity}ResponseDto(
entity.get{EntityId}(),
entity.get{Field1}(),
entity.get{Field2}(),
libraryEventId,
entity.getCreatedAt(),
entity.getUpdatedAt()
);
}

4. Repository — {Entity}Repository.java

java
package com.learnkafka.repository;
import com.learnkafka.domain.{Entity};
import org.springframework.data.jpa.repository.JpaRepository;
public interface {Entity}Repository extends JpaRepository<{Entity}, {IdType}> {
}

5. Service — {Entity}Service.java

Conventions
  • Constructor injection — single constructor, no @Autowired.
  • Logging — private static final Logger log = LoggerFactory.getLogger({Entity}Service.class);
  • `@Transactional` on mutating methods (create, update, delete).
  • Use mapper for DTO ↔ Entity conversion.
  • delete() must break bidirectional OneToOne references before deleting (if the entity participates in one).
Template
java
package com.learnkafka.service;
import com.learnkafka.domain.{Entity};
import com.learnkafka.dto.{Entity}Dto;
import com.learnkafka.dto.{Entity}ResponseDto;
import com.learnkafka.dto.LibraryEventMapper;
import com.learnkafka.repository.{Entity}Repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
@Service
public class {Entity}Service {
private static final Logger log = LoggerFactory.getLogger({Entity}Service.class);
private final {Entity}Repository {entity}Repository;
public {Entity}Service({Entity}Repository {entity}Repository) {
this.{entity}Repository = {entity}Repository;
}
public List<{Entity}ResponseDto> findAll() {
log.info("Fetching all {entities}");
return {entity}Repository.findAll()
.stream()
.map(LibraryEventMapper::to{Entity}ResponseDto)
.toList();
}
public Optional<{Entity}ResponseDto> findById({IdType} {entityId}) {
log.info("Fetching {entity} with id: {}", {entityId});
return {entity}Repository.findById({entityId})
.map(LibraryEventMapper::to{Entity}ResponseDto);
}
@Transactional
public {Entity}ResponseDto create({Entity}Dto dto) {
log.info("Creating {entity}: {}", dto);
{Entity} entity = LibraryEventMapper.to{Entity}Entity(dto);
{Entity} saved = {entity}Repository.save(entity);
log.info("Successfully created {entity}: {}", saved);
return LibraryEventMapper.to{Entity}ResponseDto(saved);
}
@Transactional
public Optional<{Entity}ResponseDto> update({IdType} {entityId}, {Entity}Dto dto) {
log.info("Updating {entity} with id: {}", {entityId});
return {entity}Repository.findById({entityId})
.map(existing -> {
existing.set{Field1}(dto.{field1}());
existing.set{Field2}(dto.{field2}());
{Entity} updated = {entity}Repository.save(existing);
log.info("Successfully updated {entity}: {}", updated);
return LibraryEventMapper.to{Entity}ResponseDto(updated);
});
}
@Transactional
public boolean delete({IdType} {entityId}) {
log.info("Deleting {entity} with id: {}", {entityId});
return {entity}Repository.findById({entityId})
.map(entity -> {
// Break bidirectional references if applicable
if (entity.getLibraryEvent() != null) {
entity.getLibraryEvent().set{Entity}(null);
}
{entity}Repository.delete(entity);
log.info("Successfully deleted {entity} with id: {}", {entityId});
return true;
})
.orElse(false);
}
}

6. Controller — {Entity}Controller.java

Conventions
  • `@RestController` + `@RequestMapping("/v1/{entities}")`.
  • Constructor injection of the service.
  • Logging — private static final Logger log = LoggerFactory.getLogger({Entity}Controller.class);
  • Use @Valid on @RequestBody params for request DTOs.
  • Return ResponseEntity<{Entity}ResponseDto> for single-entity endpoints.
  • Return ResponseEntity<List<{Entity}ResponseDto>> for list endpoints.
  • HTTP status conventions:
  • GET → 200 OK
  • POST → 201 Created
  • PUT → 200 OK (or 404 if not found)
  • DELETE → 204 No Content (or 404 if not found)
  • Not found → ResponseEntity.notFound().build()
Template
java
package com.learnkafka.controller;
import com.learnkafka.dto.{Entity}Dto;
import com.learnkafka.dto.{Entity}ResponseDto;
import com.learnkafka.service.{Entity}Service;
import jakarta.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/v1/{entities}")
public class {Entity}Controller {
private static final Logger log = LoggerFactory.getLogger({Entity}Controller.class);
private final {Entity}Service {entity}Service;
public {Entity}Controller({Entity}Service {entity}Service) {
this.{entity}Service = {entity}Service;
}
@GetMapping
public ResponseEntity<List<{Entity}ResponseDto>> getAll{Entities}() {
log.info("GET /v1/{entities}");
List<{Entity}ResponseDto> items = {entity}Service.findAll();
return ResponseEntity.ok(items);
}
@GetMapping("/{entityId}")
public ResponseEntity<{Entity}ResponseDto> get{Entity}ById(@PathVariable {IdType} {entityId}) {
log.info("GET /v1/{entities}/{}", {entityId});
return {entity}Service.findById({entityId})
.map(ResponseEntity::ok)
.orElseGet(() -> ResponseEntity.notFound().build());
}
@PostMapping
public ResponseEntity<{Entity}ResponseDto> create{Entity}(@RequestBody @Valid {Entity}Dto dto) {
log.info("POST /v1/{entities} - {}", dto);
{Entity}ResponseDto created = {entity}Service.create(dto);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}
@PutMapping("/{entityId}")
public ResponseEntity<{Entity}ResponseDto> update{Entity}(@PathVariable {IdType} {entityId},
@RequestBody @Valid {Entity}Dto dto) {
log.info("PUT /v1/{entities}/{} - {}", {entityId}, dto);
return {entity}Service.update({entityId}, dto)
.map(ResponseEntity::ok)
.orElseGet(() -> ResponseEntity.notFound().build());
}

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
114
Repository forks
215
7-day trend score
0

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/dilipsundarraj1/kafka-for-developers-using-spring-boot-v2/controller-skills/badge)](https://verified-skill.com/skills/dilipsundarraj1/kafka-for-developers-using-spring-boot-v2/controller-skills)

Something wrong with this skill or its page? Tell us.