Skip to content

Latest commit

 

History

History
71 lines (51 loc) · 9.18 KB

JEP.adoc

File metadata and controls

71 lines (51 loc) · 9.18 KB

Java Enhancement Proposal on Properties and Beans

This is far from being a JEP but just a starting point to open the discussion about goals, requirements, and features on the topic of properties and beans.

tl;dr

I have completely reinvented the wheel to come up with a free OSS solution that fills all the gaps I was facing after more than 20 years of Java coding. I tried my best to design it well but before you get lost in details of my code and reject any further investigation saying "this is too complex, too ignorant, …​" I would love to share the vision via some real world use-cases and make a statement what I am lacking in Java and would love to see properly addressed some day in the future (intentionally in reverse order from advanced to basic):

  1. Typesafe DSLs without code-generators: See SQL example with City bean. This is what we developers love to have: low code with high expressiveness but still flexibility for extension.

  2. Validation like bean-validation but seamlessly integrated and designed for CWA. See Validation test with low-level approach in TestBuildersBean and even more sophisticated via bean as interface with annotations.

  3. Marshalling as universal solution for things like JSON-P, JSON-B, Jackson, snakeyaml, etc. So you only implement your mapping once making it work for any serialization format like JSON, YAML, XML, protobuf, etc. and implement your service and add or remove support for serialization formats with just a dependency/module. See the beauty in BeanMarshallingTest.

  4. Real Beans as new Java citizens. To avoid deep reflection entirely, I created support for Beans as class. To further reduce boilerplate code and allow multi-inheritance I prefer my approach as Bean as interface. Ideally beans would become new Java type constructs just like records had been introduced (see Real beans section).

  5. Real Properties like JavaFx properties - see Real Properties section).

The problem with Java Beans

  • Java Beans suck! Every developer hates them with their pointless boilerplate code (getters, setters, equals, hashCode, toString)

  • Even though you could heal some of this pain with tools like lombok, you still have no real beans that allow to iterate their properties, etc. Further, I have seen many projects and developers struggling with code-generation being in sync after code-changes so features directly integrated into the Java language are always way more seamless.

  • As a result tons of frameworks have been created that all workaround this problem with deep reflection. This includes all JPA vendors, JAXB implementations, JSON-B implementations, Bean-Validation implementations, and Bean-Mappers (MapStruct, Dozer, Orika, etc.) just to name a few.

  • All these frameworks solve this complex problem on their own and almost all of them have bugs as this is a very underestimated problem. E.g. to determine the type of a property with support for generics is nothing an average Java developer can implement without errors.

  • Approaches like GraalVM with native image, TeaVM, GWT, etc. do not support deep reflection. As a workaround every of these frameworks has to provide configurations, generators or workarounds to make it work or even worse are simply not supported.

  • Each of the frameworks listed above needs custom logic for mapping (e.g. custom datatypes). So the great idea of strong datatypes (e.g. from DDD) gives you a very high burden. For every custom datatype, you have to implement AttributeConverter, JsonSerializer, JsonDeserializer, XmlAdapter, and many more. As a result developers do not do it ending up with poor data-models and use-case signatures (everything of type String instead of CustomerNumber, Iban, MonetaryAmount, etc.). Also bean validation (JSR 303) is IMHO flawed as it suggests to write a custom validator based on deeper reflection and requires annotation introspection by design and creating a constraint annotation (e.g. @Iban and annotate it on String properties) rather than building real data-types.

  • The biggest pain is data-binding that is mainly a concern of UI-technologies and therefore JavaFX has created its own solution for the problem. See Real Properties section below for further details.

The proposal and RfC

Real properties

IMHO the "decision" no properties in the Java language has to be revisited after GraalVM and CWP for the future of Java.

JavaFX has invented very well-designed properties. However, they have been invented in the namespace of JavaFX preventing them to be used in other contexts. I based my code initially on pure JavaFx properties but after hitting some limitations I created my own implementation just to escape the fence to get my vision working. I am more than happy to consider this a PoC and start something new (collaboratively with Java & OpenJFX experts) with an JavaFX compatible approach that still addresses these lacking features. But my plea would be to consider something to have in a namespace like java.util.property.

Real beans

IMHO Java definitely needs proper beans to address the above problems.

I created a powerful but maybe complex solution for this with pure Java and am working on a generator to make it work in CWA contexts like GraalVM or TeaVM. I am happy to discuss and question every detail of this approach. Also, I am totally happy to discuss alternative approaches like beans as mutable records or a builder-pattern for records based on their properties as a Java language feature. Records are a great feature but IMHO they currently still disqualify as a replacement for Java beans as frameworks (e.g. hibernate) can not easily be adopted to support Records. Immutability may not be the major problem but fabrication is since framework would need really complex reflection magic in order to determine the proper constructor and order of constructor arguments to instantiate recrods from their properties (say a map from property name to their values). But also maybe something like RecordComponent could also be the "Real Property" (if not already too deeply bundled with reflection). I can also think of data-types (including valhalla) as monads so instead of null we always have a real neutral instance representation that could act as factory of the datatype to address marshalling and support type decisions even for empty properties.

Open the road to avoid deep reflection

With CWA I see a trend to eliminate deep-reflection entirely from Java at runtime. IMHO the best way towards this road is to give strong answers from the Java language itself.

Just as a thought try to imagine that something like my approach for properties, beans, validation, marshalling, etc. would have been part of the JDK since tiger (1.5). How would JPA, spring, quarkus, etc. look like today and run as native image or in the browser (cross-compiled with a potential future GraalVM Java to wasm compiler). And assuming this would be a native feature of Java it could be implemented much more efficient (without internal Map<String, Property>, etc.).

How to proceed

From my PoV this article is just a starting point to get into discussion. In case you agree on some ideas and would like to start a discussion, I would be extremely happy. My hope is that this goes beyond 1-2 email ping pongs, I would love to use any collaborative discussion platform like github discussions, JIRA, or whatever you may suggest.

Side note

I use to think big and with my UI framework PoC I might show a tendency for megalomania, but please be aware that I am totally open and happy to be patient and make small steps applying to KISS principle. So even if we come down to just 1% of my vision ending up in a real JEP, that would already make me happy.