@record is deprecated and ignored. The rewrite no longer reads it to bind a type to a backing Java class. The directive is still declared in directives.graphqls so existing schemas keep parsing, but it drives no behaviour. Leaving it on a reachable type produces a build warning that tells you to remove it. Remove @record from your schema.

What replaced it

A GraphQL OBJECT or INPUT_OBJECT is still backed by a Java class when it carries one; the rewrite just derives the class differently. Instead of reading @record(record: {className: …​}), the rewrite reflects on the field that produces the type and takes the backing class from that field’s Java signature:

  • Output / result types take their backing from the producing field’s return type: an @service method return, a @table resolution, a @tableMethod return, or a parent-accessor chain that threads the class down to child types.

  • Input types take their backing from the Java parameter type the input flows into (the @service / @condition / @tableMethod method parameter), or from @table.

The class shape still determines the variant the rewrite picks: a jOOQ TableRecord produces a JooqTableRecordType (output) / JooqTableRecordInputType (input), a jOOQ Record produces a JooqRecordType / JooqRecordInputType, and a plain Java record or POJO produces JavaRecordType / PojoResultType / JavaRecordInputType / PojoInputType. What changed is the trigger: reflection on the producing field, not the directive.

So a service method that returns a hand-written DTO binds the SDL payload type to that DTO automatically; you write the @service field and let its return type carry the class. No directive is needed, and none is consulted.

Migration

Delete the directive. The type keeps the same backing class as long as a producing field still supplies it by reflection:

# Before (the directive was read to bind the class):
type CreateFilmPayload @record(record: {className: "no.sikt.graphitron.rewrite.test.services.CreateFilmPayload"}) {
    films: [Film!]!
}

# After (the @service method that returns CreateFilmPayload supplies the class):
type CreateFilmPayload {
    films: [Film!]!
}

Nothing else about the type changes: child fields still reach further tables through @reference (jOOQ-record parents) or a typed accessor (plain-record parents), exactly as before. That joining was never part of @record; only the parent’s class binding moved to reflection.

The build warning

When a reachable type still carries @record, the rewrite emits one of three warnings at the type’s source location, all of which end "remove it":

  • Redundant: the directive’s className (or a bare @record with none) matches the class the rewrite already derives from the producing field. The directive adds nothing.

  • Shadowed by @table: the type also carries @table, which supplies the backing class; @record is ignored.

  • Disagrees: the directive’s className names a different class from the one the producing field reflects to. The rewrite uses the reflected class and ignores the directive’s claim.

A bare @record with no record: was previously rejected at classify time; it now folds into the redundant case, because className was the only field that ever participated in binding.

See also

  • @table is the catalog-bound counterpart: choose it when the type is a jOOQ table. A type that is neither @table-bound nor reached by a class-returning producer is a plain nesting type and generates no carrier of its own.

  • @service is the most common source of a class-backed output type: the method’s return type now carries the binding the directive used to declare.

  • How-to: Result-type variants covers JavaRecordType / PojoResultType / JooqRecordType / JooqTableRecordType and how the rewrite picks among them from the producer’s reflected type.

  • Deprecations indexes every deprecated and ignored surface element.