kotlin-patterns

Kotlin Patterns for Backend Services

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "kotlin-patterns" with this command: npx skills add andvl1/claude-plugin/andvl1-claude-plugin-kotlin-patterns

Kotlin Patterns for Backend Services

Entity Pattern

data class EntityName( val id: UUID, val name: String, val createdAt: Instant, val updatedAt: Instant? )

Service Pattern

@Service class EntityNameService( private val repository: EntityNameRepository, private val relatedService: RelatedService ) { @Transactional(propagation = Propagation.NEVER) fun create(request: CreateRequest): Pair<EntityResponse, Boolean> { // Check exists, validate, create // Return Pair for idempotent operations }

fun findById(id: UUID): EntityName? =
    repository.findById(id)

fun findAll(): List&#x3C;EntityName> =
    repository.findAll()

}

Repository Pattern (JOOQ)

@Repository class EntityNameRepository( private val dsl: DSLContext ) { fun findById(id: UUID): EntityName? = dsl.selectFrom(ENTITY_NAME) .where(ENTITY_NAME.ID.eq(id)) .fetchOne() ?.toEntity()

fun findAll(): List&#x3C;EntityName> =
    dsl.selectFrom(ENTITY_NAME)
        .fetch()
        .map { it.toEntity() }

fun save(entity: EntityName): EntityName =
    dsl.insertInto(ENTITY_NAME)
        .set(ENTITY_NAME.ID, entity.id)
        .set(ENTITY_NAME.NAME, entity.name)
        .set(ENTITY_NAME.CREATED_AT, entity.createdAt)
        .returning()
        .fetchOne()!!
        .toEntity()

private fun EntityNameRecord.toEntity() = EntityName(
    id = id,
    name = name,
    createdAt = createdAt,
    updatedAt = updatedAt
)

}

Controller Pattern

@RestController class EntityNameController( private val service: EntityNameService ) : EntityNameApi {

override fun create(request: CreateRequest): ResponseEntity&#x3C;EntityResponse> {
    val (result, isNew) = service.create(request)
    return if (isNew) ResponseEntity.status(201).body(result)
    else ResponseEntity.ok(result)
}

override fun getById(id: UUID): ResponseEntity&#x3C;EntityResponse> {
    val entity = service.findById(id)
        ?: throw ResourceNotFoundRestException("EntityName", id)
    return ResponseEntity.ok(entity.toResponse())
}

}

API Interface Pattern

@Tag(name = "Entity Name") interface EntityNameApi {

@Operation(summary = "Create entity")
@PostMapping("/api/v1/entities")
fun create(@RequestBody @Valid request: CreateRequest): ResponseEntity&#x3C;EntityResponse>

@Operation(summary = "Get entity by ID")
@GetMapping("/api/v1/entities/{id}")
fun getById(@PathVariable id: UUID): ResponseEntity&#x3C;EntityResponse>

}

DTO Pattern

data class CreateRequest( @field:NotBlank val name: String,

@field:Size(max = 255)
val description: String?

)

data class EntityResponse( val id: UUID, val name: String, val description: String?, val createdAt: Instant )

Exception Pattern

// Use typed exceptions throw ResourceNotFoundRestException("EntityName", id) throw ValidationRestException("Name cannot be empty") throw ConflictRestException("Entity already exists")

Null Safety Guidelines

  • Use ?.let{} for optional operations

  • Use when for exhaustive matching

  • Instead of not-null assertion, use .single() or .firstOrNull()

  • Return Pair<Result, Boolean> for idempotent operations

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

kmp

No summary provided by upstream source.

Repository SourceNeeds Review
General

workmanager

No summary provided by upstream source.

Repository SourceNeeds Review
General

decompose

No summary provided by upstream source.

Repository SourceNeeds Review