Mis-using inheritance in Java UI frameworks

Gábor Farkas
DoctuSoft Coding Style
5 min readOct 30, 2015

Almost every Java UI framework I know is flawed in its class inheritance tree. This is mostly caused by the fact that Java only has single inheritance, so:

you should carefully choose which aspect of your classes to consider when designing the inheritance tree, and keep that in mind.

Having common methods and/or properties between two classes should not in itself be the reason for creating a common superclass for them. Every class in the inheritance tree should have a clear meaning.

The problem with UI frameworks is that in component classes there are at least three distinct responsibilities:

  • Rendering — what the user actually sees.
  • Behavior — handling the inner state of components. Date pickers, for example, have complex inner behaviors.
  • Data binding — what type of data does the component have and how is it validated and converted.

JSF

Now let’s take a look at a part of the JSF component tree:

The component tree is arranged mainly around the data binding aspect, and only the leaves of the tree have an actual look.

For example, this implies that you should not extend HtmlOutputText to specialize something in its look, for example HtmlMarkdownOutputText. You would create subclasses taking the rendering aspect of components into account, while other parts of the tree would be arranged based on data binding.

Of course, you can easily create the desired markdown text output using facelets components (the templating engine mostly used with JSF), and that’s the correct way to go with JSF. (As with other UI frameworks you should also use composition, not subclassing to define reusable UI parts.)

For other examples, take HtmlInputText and HtmlInputTextArea. If want to customize how these are rendered (by adding custom styles, some info labels above or below) I can easily go with creating facelets components. But what if I want to customize their data binding aspect? I’d like to specify that they are required and validated to contain only ascii characters and to have a specific message when the value is not given (requiredMessage). I could create two facelets components for them and specify this behavior for both. Well, using f:attribute and more facelets template hacking I might be able to reduce code duplication, but in that case I’m using a view templating engine to specify the data binding aspects of the components — which might not be the best idea, but actually this is by far the most convenient way with JSF.

Composite inputs

There’s a fundamental problem already with the JSF class tree itself. From one part, it subclasses to specify how components handle data: UIOutput and UIInput. These classes also specify how they behave in forms: validation, conversion. But the leaves of the class tree suddenly break this logic and add a rendered look to these components. What are the consequences of this?

You cannot create a reusable UI part that binds to a single data value and embeds properly to the form — because data binding and form validation behavior resides in UIInput and you should extend it to use that behavior.

Let’s suppose you want to create a component that selects a person from either a pre-defined list or an autocomplete (myself, my boss, other: …). This would be composed from various basic components. With JSF, you either create an own component for this extending UIInput and hack the composition in the renderer. Or you can try to solve the entire thing on the client side and just use a hidden input to ensure that the value is properly handled within a form.

Vaadin

Now let’s take a look at Vaadin’s class hierarchy:

With AbstractField, things are similar to the situation in JSF. It’s extremely strange though that Table extends AbstractSelect . This can be functionally correct of course: the selected row(s) of the table can be bound as a field value. I find it quite rare however, that you use a table to let the user select from a list of values. You use it to display values. It’s just a coincidence that a table’s selection can be considered a value inside a form. But what if you want an input table where the user can add notification recipients for example, and you want the form to be valid only if the user has added at least one value?

Another strange part is the DateField: InlineDateField and PopupDateField extend it and specialize how the component is rendered. There’s also the subtree under AbstractComponentContainer, where classes reflect how their children are arranged, which again is a totally different aspect.

By having AbstractField, Vaadin has the same problem JSF has. Vaadin, however, solves this by adding the CustomField class. This was only added in 7.0 (it existed as an addon earlier), and it is quite clear how little this class fits anywhere semantically.

Form as a component

The Form class is also quite an exception. It doesn’t actually have a look (although it’s a leaf on the tree). It’s purely behavior. It looks at its children and checks for AbstractFields, and these field components will be included in validation and all the stuff. This restricts that all your fields are visually inside one rectangle (the final html element that is rendered by the component). This is rarely a problem of course, but this restriction is completely unnecessary.

To sum up

These kind of `hybrid` class hierarchies will always have their limitations, because different aspects of these objects are mixed in the class hierarchy. Of course, they work well in most of the cases, and you might consider the limitations I came up with as corner cases.

To show off a little, I’d like to note that when designing dsweb (a gwt-based UI framework with data-binding, see its quick intro) I tried to keep the class hierarchy clean. Components only have bindable model properties. Forms, validation, and conversion are handled in separate classes.

--

--