Property Annotations

The idea here is to annotate properties of business classes in order to influence to some extent how webby presents properties in the UI.

Annotate properties with form component to be used?

The issue is that when using webby you do not have a possibility to influence what form component will be used inside the edit bean form. (This is of course in general the dilemma of a tool like webby: It makes adding functionality to your application quicker at the cost of losing (some) flexibility.)

However it might be desirable (and easy) to define e.g. for a String attribute to choose between using a TextField or a TextArea. Or for a Date attribute to use a more sophisticated form component which contains support for a special date/time format or which contains a date picker.

How to solve this? First, it should depend on the PropertyDescriptor, because it is the purpose of the PropertyDescriptor to describe the property and how the property shall be presented. Part of this description should then be a method which returns a class whose instances are suitable to be used as form components:

PropertyDescriptor (i.e. subclass thereof (or interface?)):
  Class getFormComponentClass();

What is a bit ugly here is that PropertyDescriptor is a class (and not an interface): We cannot add a method to this class defined in the Java standard (but we could define an interface that contains this method):

interface FormComponentFactory {
  Class getFormComponentClass();
  // or even better:
  FormComponent createFormComponent(String id, IModel model);
}

Then we can also use annotations which are interpreted by the UtilProperties class: For each annotated property in the business class UtilProperties creates a PropertyDescriptor which does implement FormComponentFactory and instantiates the specified FormComponent. The annoation interface could look like this:

public @interface Property {
    Class formComponent() default TextField;
}

This results in the following usage:

class Project {

  @Property(formComponent=TextArea)
  String getDescription() {
    ...
  }
}

Oh, we need more: Currently, the markup simply says:

<input wicket:id="property"/>

And for e.g. a TextArea it would need to say:

<textarea wicket:id="property">[text]</textarea>

So we must be more flexible with the markup. We can do this by replacing the direct instantiation of a FormComponent with instantiating a Panel. This panel then should contain the FormComponent. Thus the FormComponentFactory should be renamed to PropertyPanelFactory. In order to avoid confusion, the component with id "propertyPanel" should be renamed to "propertyRow", which is more appropriate, as this panel is responsible for showing a row in the property form.

So we need the following new classes:

  • TextFieldPropertyPanel
  • TextAreaPropertyPanel
  • ... and maybe more

Allow showing/hiding attributes (and/or relations) via annotations?

Pro: Could be easy to use when creating a prototypical applcation.

Con: Maybe a more sophisticated way of (statefully) configuring the view is more appropriate? (See #doesNotFit.)