KAudit — variante Java (APT)¶
KSP solo procesa Kotlin. Para clases Java existe kaudit-apt, un annotation processor de
javac (javax.annotation.processing) que reutiliza el mismo dominio (kaudit-core) y el
mismo runtime (FieldChange), pero con un frontend distinto (kspkit-apt:
javax.lang.model → kspkit-model) y un emisor JavaPoet (simétrico a KotlinPoet en el lado
Kotlin, ambos aislados en kspkit-emit).
Es el pago concreto de la arquitectura hexagonal: se cambia el adaptador de entrada y el de salida; el núcleo de diff no se toca.
Instalación¶
// build.gradle.kts (proyecto Java)
dependencies {
implementation("io.github.kuroxbyte:kaudit-annotations:0.2.0")
implementation("io.github.kuroxbyte:kaudit-runtime:0.2.0")
annotationProcessor("io.github.kuroxbyte:kaudit-apt:0.2.0")
}
El processor se auto-registra por META-INF/services; annotationProcessor(...) basta.
Qué genera¶
Por cada tipo Java @Auditable se genera una clase <Type>Auditor con un método estático:
public static List<FieldChange> diff(Account a, Account b) { ... }
(Java no tiene funciones de extensión; de ahí la estática en vez de la extensión Kotlin.) El
List<FieldChange> de salida es exactamente el tipo del runtime compartido: renderízalo con tu
propio código o persístelo como en la variante Kotlin.
Records y POJOs¶
Funciona con ambos:
// Record → accesor component()
@Auditable
public record Person(String email) {}
// POJO → getters getX()/isX()
@Auditable
public final class Product {
private final String name; private final int price;
public Product(String name, int price) { this.name = name; this.price = price; }
public String getName() { return name; }
public int getPrice() { return price; }
}
Anotaciones¶
Las anotaciones de propiedad de KAudit declaran @Target con FIELD/METHOD además de la
posición Kotlin, así que se aplican directo sobre componentes de record, campos o getters:
@Auditable
public record Account(
@AuditKey long id, // identidad para diff de colecciones por clave
String name,
@Sensitive String apiKey, // redactado: old/new en null
@AuditIgnore long updatedAt,// fuera del diff
Person owner // @Auditable → recorre en cascada (owner.email)
) {}
Paridad completa con la variante Kotlin¶
La variante Java cubre todas las estrategias del dominio:
| Caso | Java (APT) |
|---|---|
Escalar / @Sensitive / ignore |
✅ igual que Kotlin |
Anidado @Auditable |
✅ recursión por delegación (owner.email) |
Colección opaca (sin @AuditKey) |
✅ un FieldChange con la lista entera |
Colección por @AuditKey |
✅ diff por identidad (members[42]), clave simple o compuesta |
Map<K, V> |
✅ diff por clave natural (settings[clave]) |
Tipos sealed |
✅ vía instanceof pattern (mismo subtipo → recorre; distinto → objeto entero) |
Normalización de tipos: el frontend APT traduce los nombres Java a los canónicos Kotlin
(java.lang.String → kotlin.String, int → kotlin.Int, java.util.List →
kotlin.collections.List…), de modo que las reglas de dominio (escritas contra FQNs Kotlin)
aplican sin cambios a la entrada Java.
Un detalle: tipos anidados¶
El emisor deriva el paquete del generado del FQN del tipo. Declara los tipos @Auditable
top-level (un record por archivo); los records anidados producirían un paquete inválido.
Verificación¶
kaudit-apt trae 5 tests end-to-end que corren javac con el processor y ejecutan el auditor
generado (escalar/sensitive/anidado, Map, colección por @AuditKey, sealed, POJO). Ver
también los ejemplos ejecutables.