Understood. Thanks @Stephen Colebourne <[email protected]>. And yes @Attila Kelemen <[email protected]>, I agree that it being an annotation does make it less ideal. Plus, I lose out on other things that the compiler might one day give us, like exhaustiveness checking. All in all, it is still the best solution, but not one I am a fan of.
On Mon, Dec 1, 2025, 4:55 AM Attila Kelemen <[email protected]> wrote: > There are some other downsides as well: You will have to force your > clients to specifically design their records to your API (i.e., annotate > it, and configure the annotation processor). Though, in your case that is > probably not too bad, because likely they want to design their DTO for your > API anyway. The other downside is that you will have to write the IDE > support as well (e.g., Idea's editor will have red curlys around without > it). Which, aside from the additional maintenance cost, can be a problem > for a user who is not allowed to install arbitrary IDE plugins. Also, > compared to the original outline, you probably want an additional generic > argument for the record type on `RecordComponentWrapper` for type safety. > > David Alayachew <[email protected]> ezt írta (időpont: 2025. dec. > 1., H, 1:53): > >> Thanks Stephen. >> >> Hmmmmm, so this is definitely the best solution I have seen thus far. The >> only real downside is that the static final field has a different name than >> the actual record component. But I can probably fix that by making it an >> inner class or something, as opposed to sharing the same namespace as the >> record itself. >> >> Can you link me to the annotation code? >> >> On Sun, Nov 30, 2025 at 4:05 PM Stephen Colebourne <[email protected]> >> wrote: >> >>> There is a way to do this, but it isn't pretty. Use annotation >>> processing. >>> >>> @GeneratedRecordComponentInterface >>> record User(String firstName, String lastName, ComplexObject >>> complexColumn) implements UserColumns {} >>> >>> // annotation processor generates: >>> public interface UserColumns { >>> public static final RecordComponentWrapper<String> >>> FIRST_NAME_COMPONENT = new RecordComponentWrapper(User.class, >>> "firstName"); >>> public static final RecordComponentWrapper<String> >>> LAST_NAME_COMPONENT = new RecordComponentWrapper(User.class, >>> "lastName"); >>> public static final RecordComponentWrapper<ComplexObject> >>> COMPLEX_COLUMN_COMPONENT = new RecordComponentWrapper(User.class, >>> "complexColumn"); >>> } >>> >>> where `RecordComponentWrapper` is some suitable type-safe wrapper for >>> record components. >>> >>> Although there is a string for each record component, it is in >>> generated code, thus won't get out of sync. >>> >>> (This is the annotation processing equivalent to how Joda-Beans >>> meta-properties have worked for many years) >>> Stephen >>> >>>
