AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified Apache-2.0 Self-run

Kora Aop Validation

skill-kora-projects-kora-skills-kora-aop-validation · by kora-projects

Kora declarative validation via its own constraint annotations (@NotBlank, @NotEmpty, @Pattern, @Range, @Size), class/record validation with @Valid (generates Validator<T>), method argument and result validation with @Validate (AOP), custom constraints via @ValidatedBy + ValidatorFactory, and ViolationException handling mapped to HTTP 400 with ValidationHttpServerInterceptor. Use when validating…

No reviews yet
0 installs
37 views
0.0% view→install

Install

$ agentstack add skill-kora-projects-kora-skills-kora-aop-validation

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-kora-projects-kora-skills-kora-aop-validation)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Kora Aop Validation? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Kora AOP Validation

Kora validates classes/records and method arguments/results at compile time using its own constraint annotations and generated Validator components. There is no reflection: @Valid generates a Validator, @Validate weaves an aspect into a method.

Key fact: Kora validation annotations come from ru.tinkoff.kora.validation.common.annotation, NOT from jakarta.validation / JSR-380. The full constraint set is only these five: @NotBlank, @NotEmpty, @Pattern, @Range, @Size. There is no @NotNull constraint — every field/argument is implicitly required (null fails) unless marked @Nullable.


Quick Start

1. Dependency + module

Two setups exist — pick by whether you need HTTP integration. All Kora artifacts inherit their version from the kora-parent BOM; never pin individual ru.tinkoff.kora:* versions.

Plain validation (no HTTP) — artifact validation-common, module ValidatorModule:

dependencies {
    annotationProcessor "ru.tinkoff.kora:annotation-processors" // mandatory: generates validators + aspects
    implementation "ru.tinkoff.kora:validation-common"
}
import ru.tinkoff.kora.validation.common.constraint.ValidatorModule;

@KoraApp
public interface Application extends ValidatorModule { }

With HTTP-server integration (maps ViolationException → 400) — artifact validation-module, module ValidationModule:

dependencies {
    annotationProcessor "ru.tinkoff.kora:annotation-processors"
    implementation "ru.tinkoff.kora:validation-module"
}
import ru.tinkoff.kora.validation.module.ValidationModule;

@KoraApp
public interface Application extends ValidationModule, UndertowHttpServerModule, JsonModule { }

Kotlin: replace annotationProcessor/testAnnotationProcessor with ksp "ru.tinkoff.kora:symbol-processors".

2. Validated record — generates Validator

import jakarta.annotation.Nullable;
import ru.tinkoff.kora.validation.common.annotation.*;

@Valid
public record CreateUserRequest(
    @NotBlank @Size(min = 2, max = 100) String name,
    @NotBlank @Pattern("^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$") String email,
    @Range(from = 18, to = 120) Integer age,
    @Nullable String note                                // opt out of the implicit null check
) {}

3. Validate a method with @Validate

@Component
public class UserController {

    @HttpRoute(method = HttpMethod.POST, path = "/users")
    @Json
    @Validate
    public UserResponse createUser(@Valid @Json CreateUserRequest request) {
        return userService.create(request); // ViolationException thrown before the body runs if invalid
    }
}

4. Inject the generated validator directly (manual validation)

@Component
public final class Example {

    private final Validator validator;

    public Example(Validator validator) {
        this.validator = validator;
    }

    public void check(CreateUserRequest req) {
        validator.validateAndThrow(req); // collects all violations, then throws ViolationException
    }
}

How it works

| Annotation | Where | Effect | |------------|-------|--------| | @Valid on a type/record | type | Generates a Validator component in the graph | | @Valid on a field/parameter | field/param | Recurses into a nested validated type's Validator | | @Validate on a method | method | Weaves an aspect: validates @-annotated args (and the result if the method itself is annotated) before/after the body | | @NotBlank/@NotEmpty/@Pattern/@Range/@Size | field/param/method | The actual constraint checks | | @Nullable (any flavor) | field/param | Suppresses the implicit null check |

A Validator returns List. Use validate(value) to inspect, or validateAndThrow(value) to throw ViolationException on the first non-empty result. The @Validate aspect throws ViolationException automatically.


Class / record validation

Every field is implicitly required. Mark optional fields with any @Nullable annotation (jakarta.annotation.Nullable, javax.annotation.Nullable, org.jetbrains.annotations.Nullable).

@Valid
public record OrderRequest(
    @NotBlank String id,
    @Valid Customer customer,            // nested → uses generated Validator
    @Valid List items,        // elements validated via Validator
    @Nullable String comment
) {}

For a regular (non-record) class, getters must be at least package-private (getId()); records use the component accessor (id()).

Kotlin

@Valid
data class CreateUserRequest(
    @field:NotBlank @field:Size(min = 2, max = 100) val name: String,
    @field:NotBlank val email: String,
    val note: String?                    // Kotlin nullability marks it optional
)

Use the @field: prefix on constraints. A data class is fine for class validation. A class only needs open when it hosts a @Validate method (aspects require subclassing).


Method validation with @Validate

@Validate on a method validates its annotated arguments before the body and, if the method itself carries constraint annotations, its result afterward. The enclosing class must be non-final (Java) / open (Kotlin) so the aspect can subclass it.

@Component
public class UserService {

    @Validate
    public User create(@Valid CreateUserRequest request) { ... }

    // single-argument constraint, stop on the first error
    @Validate(failFast = true)
    public User getByEmail(@NotBlank @Pattern("^[^@\\s]+@[^@\\s]+$") String email) { ... }

    // result validation: @Validate enables it, @Valid validates the returned objects,
    // @Size constrains the list itself
    @Size(min = 1)
    @Valid
    @Validate
    public List getAllUsers() { ... }
}

failFast = true throws on the first violation; the default collects all violations into one ViolationException.

Supported method signatures: T, Optional, Mono/Flux (with reactor-core) in Java; T, suspend fun, Flow in Kotlin.


Mapping ViolationException to HTTP 400

Requires the validation-module artifact (ValidationModule). Register an interceptor tagged for the HTTP server plus a response mapper. Adapted from .kora-agent/kora-examples/guides/java/kora-java-guide-validation-app:

@KoraApp
public interface Application extends
        ValidationModule, UndertowHttpServerModule, JsonModule, LogbackModule {

    default ViolationExceptionHttpServerResponseMapper violationMapper(
            JsonWriter writer) {
        return (request, exception) -> HttpServerResponse.of(
            400,
            HttpBody.json(writer.toByteArrayUnchecked(
                ValidationErrorResponse.of(toErrors(exception.getViolations())))));
    }

    @Tag(HttpServerModule.class)
    default ValidationHttpServerInterceptor validationInterceptor(
            ViolationExceptionHttpServerResponseMapper mapper) {
        return new ValidationHttpServerInterceptor(mapper);
    }

    private static List toErrors(List violations) {
        return violations.stream()
            .map(v -> new ValidationErrorDetails(v.path().full(), v.message()))
            .collect(java.util.stream.Collectors.toList());
    }
}

Violation is an interface: message() and path() (a ValidationContext.Path whose full() returns the dotted path, e.g. customer.address.city). See [violation-exception-reference.md](references/violation-exception-reference.md).


References & assets

| File | Purpose | |------|---------| | [references/validation-annotations-reference.md](references/validation-annotations-reference.md) | The five constraints, @Range boundary enum, @Pattern int flags, @Nullable opt-out | | [references/custom-validators-reference.md](references/custom-validators-reference.md) | Custom constraints via Validator + ValidatorFactory + @ValidatedBy | | [references/violation-exception-reference.md](references/violation-exception-reference.md) | ViolationException, Violation, ValidationContext, HTTP 400 mapping, testing | | [assets/README.md](assets/README.md) | DTO / service / custom-validator / error-response templates (Java + Kotlin) |

Working example apps: .kora-agent/kora-examples/examples/java/kora-java-validation (plain validation) and .kora-agent/kora-examples/guides/java/kora-java-guide-validation-app (HTTP 400 mapping).


Common pitfalls

| Symptom | Fix | |---------|-----| | Validation never runs on a method | Add @Validate to the method; ensure the class is non-final (Java) / open (Kotlin) | | Nested object not validated | Add @Valid to the field/parameter holding it | | Field unexpectedly required | All fields are implicit-not-null; add @Nullable to make optional | | Looking for @NotNull | It does not exist in Kora — nullability is the default; opt out with @Nullable | | Reached for jakarta.validation.* | Use ru.tinkoff.kora.validation.common.annotation.* instead | | Caught the wrong exception | Catch ru.tinkoff.kora.validation.common.ViolationException | | HTTP 500 instead of 400 on bad input | Use validation-module; register ValidationHttpServerInterceptor + ViolationExceptionHttpServerResponseMapper | | Kotlin constraints ignored | Use the @field: prefix | | @Pattern(regexp = ...) won't compile | The attribute is the unnamed value: @Pattern("...") |


Testing

@KoraAppTest(Application.class)
class CreateUserValidationTest {

    @TestComponent
    private Validator validator;

    @Test
    void failsForBlankName() {
        var request = new CreateUserRequest("   ", "test@example.com", 25, null);

        ViolationException ex = assertThrows(ViolationException.class,
            () -> validator.validateAndThrow(request));

        assertTrue(ex.getViolations().stream()
            .anyMatch(v -> v.path().full().contains("name")));
    }
}

See .kora-agent/kora-examples/examples/java/kora-java-validation/src/test/java/... for the @KoraAppTest + @TestComponent pattern over ArgumentValidator / ResultValidator.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.