Can you elaborate more on how form.line($.address.city); uses the identity of city?
How does Backend.find(Person.class, By.field($.address.zip, 8000)); figure out that $.address.zip refers to the corresponding field in Address? On Mon, Dec 1, 2025 at 1:56 PM Remi Forax <[email protected]> wrote: > ----- Original Message ----- > > From: "Bruno Eberhard" <[email protected]> > > To: "valhalla-dev" <[email protected]> > > Sent: Wednesday, November 26, 2025 10:43:30 AM > > Subject: Valhalla breaks minimal-j framework > > > Hi, > > > > I really like the concepts and the gains you make with Valhalla. But it > > breaks some essential points of my framework called «minimal-j» (on > > https://github.com/BrunoEberhard/minimal-j ). I would kindly ask if you > > can provide a replacement for what is not possible in Valhalla anymore. > > > > Let me show the problem and then propose a solution. In the minimal > > design all fields of a class representing a business entity (only those) > > are public. No getter or setter. Then a static constant $ is defined > > like this: > > > > public class Person { > > public static final Person $ = Keys.of(Person.class); > > > > @NotEmpty > > public Integer number; > > > > @Size(100) > > @Searched > > @NotEmpty > > public String name; > > > > public final Address address = new Address(); > > } > > > > With the $ constant there is a reference to the fields of the class. > > With theses references a UI can be specified: > > > > var form = new Form<Person>(); > > form.line($.number); > > form.line($.name); > > form.line($.address.city); > > > > Or a query to the persistence layer can be formulated: > > > > Backend.find(Person.class, By.field($.name, "Bruno")); > > Backend.find(Person.class, By.field($.address.zip, 8000)); > > > > In the background the framework fills the fields of the $ constant with > > values that are later used to identify which field should be used. For > > this identity is vital. Things like "new String(..)" and "new > > Integer(..)" is used to make $.number unique. > > > > If Integers loose their identity this is now longer feasable. > > > > A possible replacement for this trick would be references to fields. > > Best in this way: > > > > Backend.find(Person.class, By.field(Person::name, "Bruno")); > > > > Person::name should result in a java.lang.reflect.Field > > > > Backend.find(Person.class, By.field(Person::address::zip, 8000)); > > > > Here Person::address::zip should result in a java.lang.reflect.Field[] > > or in a new class containing chained Fields. > > > > Of course I could instead write getter and setter and the use > > Person::getName . But Person::getAddress::getZip doesn't work. And I > > would really like not to have getter and setter (for which I have to > > check all names and parameters are correct). Lombok or Kotlin hide > > getter and setter. But I don't really like hiding something. Especially > > if it is not really needed. > > > > So if it is possible to add this construct to the java language it would > > make me really happy. Otherwise I would never be able to use a Java > > version which contains Valhalle for this kind of framework. > > Integers, and others are marked as value-based classes > ( > https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/doc-files/ValueBased.html > ) > since quite some time, so your framework is currently violating this > non-enforced spec. > > I don't blame you, not at all, i've done the same in ASM at some point in > time, but we have to fix the errors of the past ; Integer should be a > lightweight boxing with no identity guarantee ; because it improve 99.9% of > the existing codes. > > I've seen a mocking framework having the same issue a lot time ago before > and after Integers where cached. > > They moved to a representation using interfaces + dynamic proxies instead > of classes. > > public interface Person { > public static final Person $ = Keys.of(Person.class); > > @NotEmpty > public int number(); > > @Size(100) > @Searched > @NotEmpty > public String name(); > > public final Address address(); > } > > with the information being stored out of the line in ThreadLocal (I > believe you can now use ScopeValue for that) > instead of using a special return value. > > On the positive side, you do not have to use Integer anymore, you can use > int (see numbers()), > on the negative side, it's obviously not backward compatible with your > existing framework. > > > > > regards > > regards, > Rémi >
