6) Data Types

This chapter describes the default visualizations for domain objects.

6.1) Simple Data Types

The following basic data types are supported by this framework and are visualized as follows:

Java TypeHTML TagWicket ComponentSample (default validation applies)
byte<input type="number">NumberTextField
Byte<input type="number">NumberTextField
short<input type="number">NumberTextField
Short<input type="number">NumberTextField
int<input type="number">NumberTextField
Integer<input type="number">NumberTextField
long<input type="number">NumberTextField
Long<input type="number">NumberTextField
float<input type="number">NumberTextField
Float<input type="number">NumberTextField
double<input type="number">NumberTextField
Double<input type="number">NumberTextField
BigInteger<input type="number">NumberTextField
BigDecimal<input type="number">NumberTextField
boolean<input type="checkbox">CheckBox
Boolean<input type="checkbox">CheckBox
char<input type="text">TextField
Character<input type="text">TextField
String<input type="text">TextField
Date<input type="date">DateTextField (with DatePicker)
Calendar<input type="date">DateTextField (with DatePicker)
Enum (e.g. TimeUnit)<select>DropDownChoice

Click the date sample to show the date picker. Try changing some values to see the default validations in action (leave focus to apply change):

  • primitive types are not null validated
  • numbers and chars are validated by range limits
  • fractional digits are only allowed on appropriate number types
  • dates have to be in correct format
  • enum literals are validated against value manipulation (e.g. with Firebug)
  • rudimentary sql injection validation is performed on string values (try ";drop table users"); though don't mistake it for real security, it only works against script kitties, thus this feature can be disabled in the GeneratedBinding if desired

Currently there is no out of the box support for java.time, joda-time or any other custom type library for dates or numbers. This is because there is a simple workaround, just convert between the types in your getters/setters if you want a field of an unsupported type. You can still externalize the original type via @Hidden methods for your internal coding needs. Just make sure to convert to a supported type for the framework or completely handle the binding yourself with a BindingInterceptor and custom components.

By default the framework displays all properties of a class which have a public getter method defined. If there is also a public setter method defined, the displayed field is editable, otherwise it is read-only. You could also provide public fields (which is the same as a getter and a setter combined), even though this is rather unusual when following the JavaBeans pattern.

Every field is preceded by a label with a text that is derived from the property name. CamelCase syntax causes a whitespace splitting (e.g. getNumberOfChildren() is displayed as "Number Of Children"). These labels were explicitly removed from the above samples.

6.2) Collections & Arrays

If the property is a collection/array of a simple data type, it is always mapped to a select tag. This will show it as a combo box. You can set a size attribute to convert it to a list as done below (the lists are disabled because the properties do not have a setter). But what we are going for here are tables, not lists or combo boxes.

So to do it correct, you have to use the proper types. Arrays and collections for complex data types are by default mapped to tables. The table contains one row for each element of the collection/array. To achieve a detailed visualization of domain objects from a collection, the collection should be typed using Java generics. Otherwise the framework can only display "the least common denominator" which is toString() for all contained objects. The table displays only the data of the contained type. As a consequence, if the collection also contains objects of derived types, the additional properties of these types are not displayed. (e.g. a collection of vehicles contains cars and bikes with additional properties, but the generic type is of car. Thus the table displays only the properties of the vehicle base class). Also note that tables only allow shallow columns to be displayed, everything else is displayed as toString(). You see this below in the nested column that contains column3 in a structured type.

Wrong

public Iterable getObjectsIterable() { ... }
public Object[] getObjectsArray() { ... }
public Iterable<Byte> getBytesIterable() { ... }
public Byte[] getBytesArray() { ... }

Correct

Table Rows Iterable
Column1 Column2 Nested Action
1_1
1_2
TableRowNested[column3:1_3]
2_1
2_2
TableRowNested[column3:2_3]
3_1
3_2
TableRowNested[column3:3_3]
public Iterable<TableRow> getTableRowsIterable() { ... }
Table Rows Array
Column1 Column2 Nested Action
1_1
1_2
TableRowNested[column3:1_3]
2_1
2_2
TableRowNested[column3:2_3]
3_1
3_2
TableRowNested[column3:3_3]
public TableRow[] getTableRowsArray() { ... }



If you want to see a more realistic table example, please open the Ajax Data Table example from the Wicket Examples Rebuilt item in the top menu.

6.3) Structured Data Types

Domain objects may be structured by one class referencing another class. The related objects are in this case displayed within the UI of the referencing object. To separate the fields from each other, the fields for referenced objects are displayed under a separation line with the name of the reference as a caption.

The following example shows a more comprehensive model for a car. The motor with its methods for turning it off and on are implemented in a separate class. There is a number of additional attributes with different data types now. All trips which have been made with that car are associated by an array.

public class Car implements Serializable {
				
	private String licenseNumber;
	private CarBrand brand;
	private long kmMileage;
	private BigDecimal purchasePrice;
	private boolean technicalControl;
	private Date registrationDate;
	private Trip[] tripBook;
	private Motor motor;

	// constructor, getters/setters omitted here
	
}

public class Motor implements Serializable {

	private int powerInHP;
	private MotorState state;
	
	// constructor, getters/setters omitted here

	public void turnOn() { this.state = MotorState.on; }
	public void turnOff() { this.state = MotorState.off; }
	
}

public class Trip implements Serializable {

	private String from;
	private String to;
	private int distanceInKM;
	
	// constructor, getters/setters omitted here
	
}

This results in the following panel:

Motor
Trip Book
Distance In KM From To 
384,403
Earth
Moon
384,403
Moon
Earth

This looks better than the previous examples, but it allows logically incorrect input values. To fix this, the next chapter explains how to add validations.