You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 01f7265
Browse filesBrowse the repository at this point in the historyBrowse files
fix(kotlin): a required generated key blocked every create; conflicts 500'd; int-backed enum filters lied
Three defects in the generated Kotlin controller tier, found by building an
adopter estate's Kotlin backend from the published 8.0.5-rc.7 as the docs
describe - each with every in-repo lane green.
1. Create. The data class is also the create @RequestBody, and a @required
generated key made it a non-null ctor param with no default:
jackson-module-kotlin rejected every body that (correctly) omitted it, so
every create 400'd on the shape real models have (BaseEntity declares id
required). An increment key hid it - a missing Long binds 0 - a UUID
cannot. Behind it: the handler read a @generation: uuid key back from the
insert, which Exposed returns only for a value it inserted or an
autoIncrement column ("id is not in record set"). Now a server-owned-on-
create field (generated key, @autoset column) is nullable, default null,
no @field:NotNull - KotlinGenUtil.isServerOwnedOnCreate, mirroring Java's
SERVER_OWNED_ON_CREATE - and the handler mints a uuid key itself, as the
TS runtime does.
2. Conflicts. handleConstraintViolation was declared for RuntimeException;
Exposed raises ExposedSQLException, a CHECKED java.sql.SQLException, so it
never matched and every duplicate key / dangling reference was a 500. It
handles java.sql.SQLException too. Nothing had ever run it.
3. Int-backed enum filters. Every enum was compared as TEXT against the
member symbol; an @intValueMap column stores the integer, so eq/in matched
nothing and ne everything, with a 200. Now compared through the
enum-typed column (whose codec writes the integer).
Docs: docs/ports/kotlin.md's install block could not build a running app -
it now lists exposed-jdbc (runtime), exposed-java-time and exposed-json (the
tables import them), and says the controller needs KotlinRelationsGenerator
when the model has M:N. The config generator no longer claims a validator
runs when validatorEnabled=false.
Tests: UuidPkControllerRunTest now makes the uuid key @required, POSTs
without it (201, generated id) and POSTs a duplicate unique name (409);
EnumFilterControllerRunTest gains an int-backed enum (eq/ne/in/unknown).
Both failed before the fix. codegen-kotlin 394/0 (3 snapshots updated),
integration-tests-kotlin 161/0; the estate's Kotlin port 43/43 on this build.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EaGv4zNk4oT7FooD4eK5MD
Copy file name to clipboardExpand all lines: docs/ports/kotlin.md
+20-1Lines changed: 20 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -39,6 +39,25 @@ Two modules:
39
39
<artifactId>exposed-core</artifactId>
40
40
<version>${exposed.version}</version>
41
41
</dependency>
42
+
<!-- The generated tables import these two: instant (tz-aware timestamp) columns come from
43
+
exposed-java-time, jsonb columns from exposed-json. exposed-jdbc is what
44
+
`Database.connect(...)` needs at RUNTIME — without it the app starts and the first
45
+
query fails. -->
46
+
<dependency>
47
+
<groupId>org.jetbrains.exposed</groupId>
48
+
<artifactId>exposed-jdbc</artifactId>
49
+
<version>${exposed.version}</version>
50
+
</dependency>
51
+
<dependency>
52
+
<groupId>org.jetbrains.exposed</groupId>
53
+
<artifactId>exposed-java-time</artifactId>
54
+
<version>${exposed.version}</version>
55
+
</dependency>
56
+
<dependency>
57
+
<groupId>org.jetbrains.exposed</groupId>
58
+
<artifactId>exposed-json</artifactId>
59
+
<version>${exposed.version}</version>
60
+
</dependency>
42
61
<!-- Generated typed `field.object @storage:jsonb` / `field.map` columns serialize through a
43
62
generated per-package `MetaJsonbMapper.kt` Jackson `ObjectMapper` (no kotlinx-serialization
44
63
compiler plugin required). -->
@@ -87,7 +106,7 @@ The 15 generators registered in `codegen-kotlin` (`GeneratorRegistry.kt`):
87
106
|`KotlinValidatorGenerator`|`MetadataStartupValidator.kt` + `ExposedTableValidator.kt`| once per project |
88
107
|`KotlinSpringConfigGenerator`|`MetadataExposedConfig.kt` — `@Configuration` wiring `Database.connect()` + auto-validator | once per project |
89
108
|`KotlinStoredProcGenerator`| Stored-procedure call wrappers | entities with `source.rdb @kind="storedProc"`|
90
-
|`KotlinSpringControllerGenerator`|`<Entity>Controller.kt` — Spring `@RestController` (5 CRUD endpoints; cross-port API contract) | entities with `source.rdb @kind="table"`|
109
+
|`KotlinSpringControllerGenerator`|`<Entity>Controller.kt` — Spring `@RestController` (5 CRUD endpoints; cross-port API contract). **Select `KotlinRelationsGenerator` with it** when the model has a M:N relationship: the traversal routes call the `<rel>Query` helpers only that generator emits, and without it the controller does not compile| entities with `source.rdb @kind="table"`|
Copy file name to clipboardExpand all lines: server/java/codegen-kotlin/src/main/kotlin/com/metaobjects/generator/kotlin/KotlinSpringConfigGenerator.kt
+11-4Lines changed: 11 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -60,10 +60,17 @@ open class KotlinSpringConfigGenerator : MultiFileDirectGeneratorBase<MetaObject
60
60
61
61
val typeBuilder =TypeSpec.classBuilder(className)
62
62
.addKdoc(
63
-
"GENERATED — wires Exposed's `Database.connect()` from the Spring "+
64
-
"[DataSource] bean\nand runs [MetadataStartupValidator.validate] at "+
65
-
"app startup.\n\nIf you don't want the validator auto-call, set "+
66
-
"`metaobjects.validator.enabled=false`.\n"
63
+
if (validatorEnabled) {
64
+
"GENERATED — wires Exposed's `Database.connect()` from the Spring "+
65
+
"[DataSource] bean\nand runs [MetadataStartupValidator.validate] at "+
66
+
"app startup.\n\nIf you don't want the validator auto-call, set "+
67
+
"`metaobjects.validator.enabled=false`.\n"
68
+
} else {
69
+
// Generated with validatorEnabled=false: no validator hook is emitted, so the
70
+
// KDoc must not say one runs.
71
+
"GENERATED — wires Exposed's `Database.connect()` from the Spring "+
0 commit comments