Skip to content
Jörg Hohwiller edited this page Apr 11, 2024 · 16 revisions

Reinventing the wheel

  • Yes, this project is "reinventing the wheel"!

  • Yes, it is usually not a good idea to do that.

Why?

So why are we doing this? First of all, the "wheels" in Java suck! We want to race at light-speed and the existing "wheels" only give us a tricycle. So we need new "wheels" that are very much better! Java Beans also known as POJOs suck heavily and the entire Java ecosystem (JEE, JPA, spring, etc.) is build around this design flaw! Furhter, all these grown frameworks rely on deep reflection at runtime what results in bad performance and memory utilization. However, trends like cloud-native with GraalVM, etc. bring the death to deep-reflection at runtime. Besides reactive programming also brings a huge shift into programming (see R2DBC or JOOQ). As an alternative project Loom brings virtual threads to Java so the days of limited thread-pools are over. However, this also means that ThreadLocal is dead and has to be replaced by ScopedValue. So if the frameworks, standards and libraries we have been used to are in question and start to fall into pieces it may actually be a good point in time for something new and innovative…​

Further, we are the first framework that brings the original promise of Java back to reality:

Write once, run anywhere

— Sun Microsystems
https://en.wikipedia.org/wiki/Write_once%2C_run_anywhere

Our code is designed to run on any JVM, as cloud-native binary with GraalVM and compiled to JavaScript or WebAssembly using TeaVM. The approach is a little similar to Blazor for .NET and C# but more sophisticated. Read the following chapters (maybe skipping the next one) if you want to try understanding our point of view.

Vision

We have a vision to make Java coding fun again while being highly efficient and expressive with less code. Therefore, we created this framework to be able to share this vision and make it happen. We never had the intention to be ignorant and we actually started with a lot of reuse instead or rebuilding everything from scratch. But we hit walls everywhere that where about to kill our vision. Therefore, we step by step replaced existing solutions and rebuild them from scratch. If you are an influental member of JakartaEE, OpenJDK, JavaFx, Oracle, or the like and you happen to give our approach a chance before judging our potential ignorance and if it additionally might happen that you like (some of) the ideas, please get in touch. The main goal of this project is to boost Java and make Java coding better. We are more than open and happy to donate our code, to refactor it, to re-integrate into or with existing solutions and frameworks. However, if we would have tried to do all the things within OpenJDK, JavaFx, Jakarta EE, etc. our vision would have been dead before it was born! Innovation can not happen if you are fenced and framed by huge walls. If we could re-integrate our advanced features back into JavaFx properties and make them become a Java standard that exists completely decoupled from JavaFx we are more than happy to drop our own properties and move to that. If experts from JavaFx, and maybe all the other UI frameworks would join in and improve, redesign, optimize, and polish our ui-api to make it a real Jakarata EE standard and maybe OpenJFX would become a native implementation of that standard our dreams would have been surpassed. If people show up that want to integrate Bean validation back into this framework we are also open for discussion.

Boilerplate code

One problem is that you have to write a lot of boilerplate code with getters, setters, equals, hashCode, etc. You might say, to get rid of boilerplate code, you can use Lombok or alternative languages like Kotlin. Indeed this helps to cure the problem but that is not it!!! You need to understand the full problem because there are tons of frameworks that need to instrospect and map Java Beans. You might argue that the new Java records can solve the problem as they have lightweight reflection support what is really great. However, they are immutable and take all property values as one constructor what disqualifies them for generic construction and dynamic binding. Further you need to implement AttributeConverters for JPA, JsonSerializers and JsonDeserializers for Jackson, XmlAdapters for JAX-B, ConstraintValidators and Constraint-Annotations for Bean-Validation, etc. that is also lots of boilerplate code. Java missed out the real problems and never defined a standard that solves the problems from the root.

JPA

We do not want to offend anybody but IMHO the entire design of JPA is flawed. The "call-by-reference" approach with auto-comitting managed entities after dirty check on transaction commit might have been initially an idea to make life of developers most simple. However, exactly the opposite is the case: When building large and complex data-models and systems you will either end up with transfer-objects or with a messy and unmaintainable app. Finally, the idea of building relations as getters to other entity objects does not go well with avoiding transfer-objects for (REST) services. And transfer-objects mean again a lot of boilerplate code. How do you implement search queries? You can not express them on top of your POJOs so what do you do? Create even more boilerplate code to implement search criteria transfer-objects for each entity. After 20 years of doing all this non-sense we have to deeply question the "given" and the "way we work" and seek for better answers to solve our problems.

Properties

We really have started using JavaFx properties (see old traces). Most things of JavaFx properties are designed really well. We have "copied" all the good things but we changed some small things we did not like and espcially we added lots of missing features. So here is a list of features we added:

  • getValueClass() and getValueType() gives generic access to determine the type of the value contained in the property even if the value is null. This is a very important feature required for dynamic binding of beans to UI, etc.

  • Build in copy and getReadOnly() support.

  • Generic and extendable metadata support.

  • Build in criteria support (see SelectTest to get the entire idea).

  • Build in validation support designed in a holistic and consistent way (Do you know the @Valid hell with BV?).

  • Build in marshalling support to (de)serialize to JSON, XML, etc.

And here is a list of things we changed (API incompatibilities):

  • Simplified listeners to only one type (ObservableEventListener instead of InvalidationListener, ChangeListener, ListChangeListener, etc.) that is designed smart enough to solve all in one with lazy handling.

  • get() and set methods to access the non-primitive value to be compliant with java.util.function.Supplier

  • Always internally store object type to stay consistent (get returns what has been provided to set so value is null if actually set to null what is not possible with JavaFx properties).

  • Make observable collections less invasive and allow using regular lists as value.

  • Simplified observable collections to avoid over-engineering

Beans

For beans we have never seen a convincing solution in Java so there was nothing to reuse.

Validation

Bean validation (BV) is a nice standard. We still think about re-integrating it. However, it is by design based on deep-reflection and POJOs. You can not remove this from the design and it makes some things odd when using it without all this: ConstraintValidator is by design taking an annotation as configuration. Further, BV does not address complex validations on entire beans ("if property A is true then property B is mandatory" or "the sum of property A and property B has to be less than X").

We designed validation from scratch with minimalistic but powerful ideas and also integrated it with our great native language support (NLS) for i18n.

UI

Are you implementing clients (desktop, web and mobile) with Java? Most probably not. However, this will bring boilerplate coding and waste to its extreme. As the user-interface (UI) part is a really big story of its own, please read this article to understand what we have done and why.

Clone this wiki locally