Valhalla breaks minimal-j framework
Ethan McCue
ethan at mccue.dev
Mon Dec 1 19:04:20 UTC 2025
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 <forax at univ-mlv.fr> wrote:
> ----- Original Message -----
> > From: "Bruno Eberhard" <bruno.eberhard at pop.ch>
> > To: "valhalla-dev" <valhalla-dev at openjdk.org>
> > 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-dev/attachments/20251201/07aeec71/attachment-0001.htm>
More information about the valhalla-dev
mailing list