Beyond the base issue of inspecting an object and its properties, a number of inspectors are focussed on
third-party annotations. These annotation inspectors all extend BaseObjectInspector,
and so inherit its features, but in addition they inspect the following frameworks.
BeanValidationInspector inspects Bean Validation (JSR 303) annotations. It returns the following
attributes for the following business properties:
| Metawidget Attribute | Bean Validation Annotation |
|---|---|
maximum-fractional-digits |
@Digits(fraction=...) |
maximum-integer-digits |
@Digits(integer=...) |
maximum-length |
@Size(max=...) |
maximum-value |
@Max |
minimum-length |
@Size(min=...) |
minimum-value |
@Min |
required |
@NotNull |
FacesInspector inspects Java Server Faces-specific annotations. It returns the following
attributes for the following business properties:
| Metawidget Attribute | Annotation |
|---|---|
| (any) |
@UiFacesAttributes and @UiFacesAttribute -annotates
an arbitrary Metawidget attribute, based on a Java Server Faces EL expression.
Unlike |
currency-code,
currency-symbol,
number-uses-grouping-separators,
minimum-integer-digits,
maximum-integer-digits,
minimum-fractional-digits,
maximum-fractional-digits,
locale,
number-pattern and
number-type
|
@UiFacesNumberConverter - annotates the field should use the standard Faces
NumberConverter.
Note: the |
date-style,
locale,
datetime-pattern,
time-style,
time-zone and
datetime-type
|
@UiFacesDateTimeConverter - annotates the field should use the standard Faces DateTimeConverter |
faces-component |
@UiFacesComponent - annotates the field should be rendered using the
given Faces UIComponent in the UI.
Use of this annotation does not bind the business class to the UI quite as tightly
as it may appear, because JSF has a loosely coupled relationship between
|
faces-converter-id |
UiFacesConverter - annotates the field should use the given Faces converter
in the UI.
This annotation uses the converter Id, not the class. Whilst it is possible to
specify the class through the XML (see
|
faces-lookup |
@UiFacesLookup - annotates the value in the field should
belong to the set returned by the given EL expression
|
faces-suggest |
@UiFacesSuggest - annotates the value in the field should
be 'suggested' (ie. using a pop-up box) using the set returned by the given EL expression
|
HibernateValidatorInspector inspects Hibernate Validator annotations. It returns the following
attributes for the following business properties:
| Metawidget Attribute | Hibernate Validator Annotation |
|---|---|
maximum-fractional-digits |
@Digits(fractionalDigits=...) |
maximum-integer-digits |
@Digits(integerDigits=...) |
maximum-length |
@Length(max=...) |
maximum-value |
@Max |
minimum-length |
@Length(min=...) |
minimum-value |
@Min |
required |
@NotNull or @NotEmpty |
JexlInspector inspects @UiJexlAttribute annotations and
sets arbitrary attributes based on the result of evaluating an Apache Commons JEXL expression. It can
be used to introduce declarative UI scripting into environments that lack their own expression language
(ie. JSP has an EL, Swing does not). For example:
import org.metawidget.inspector.commons.jexl.*; public class Person { public boolean retired; @UiJexlAttribute( name = "hidden", value = "!this.retired" ) public BigDecimal pension; }
This code returns a hidden attribute based on evaluating the JEXL expression
!this.retired (where this refers to the runtime instance of
the Person being inspected). It could be used to show/hide the pension
field in response to the retired checkbox being checked.
The JEXL expression language also supports branching statements. For example:
import org.metawidget.inspector.commons.jexl.*; public class PersonController { @UiJexlAttribute( name = "label", value = "if ( this.readOnly ) 'Back'" ) public void cancel() { ... } }
This code overrides the label of an action to be either 'Back' or 'Cancel', depending
on whether the Person was being edited. It is taken from the Swing Address Book
sample (see Section 1.2.1, “Desktop Address Book”).
JpaInspector inspects Java Persistence Architecture annotations. It returns the following
attributes for the following business properties:
| Metawidget Attribute | JPA Annotation |
|---|---|
hidden |
@Id, unless JpaInspectorConfig.setHideIds is false |
large |
@Lob |
maximum-length |
@Column(length=...) |
required |
@Column(nullable=false) or @ManyToOne(optional=false) |
As much as possible, Metawidget tries to inspect metadata from existing sources, without
introducing new concepts. Where that is not sufficient, MetawidgetAnnotationInspector adds
a handful of annotations:
| Metawidget Attribute | Metawidget Annotation |
|---|---|
| (any) | @UiAttributes and @UiAttribute - a 'catch all' for denoting arbitrary UI metadata |
| (order of fields) | @UiComesAfter |
action |
@UiAction |
dont-expand |
@UiDontExpand - denotes a value should not be inspected and expanded into sub-widgets. This
can be useful if, say, you have a read-only field and just want to display its top-level toString()
rather than all its child properties
|
hidden |
@UiHidden - denotes a value should be hidden in the UI. The value may
still be rendered on the client, depending on the Metawidget (ie. for Web clients,
may use a HTML hidden field)
|
label |
@UiLabel - denotes the label to used in the UI. Can be a resource
key if the UI is using resource bundles, or
an EL expression if the UI has an expression language (ie. JSF)
|
large |
@UiLarge - denotes the field should be 'large' in the UI (ie. a multi-line textbox) |
lookup |
@UiLookup - denotes the value in the field should belong to the given set of Strings |
masked |
@UiMasked - denotes a value should be masked in the UI (eg. a password field) |
read-only |
@UiReadOnly - denotes a value should be read-only in the UI |
read-only |
@UiReadOnly - denotes a value should be read-only in the UI |
section |
@UiSection - denotes the start of a logical grouping in the UI |
wide |
@UiWide - denotes the field should be 'wide' in the UI, spanning all columns in a multi-column layout.
'Wide' is different to 'large', because 'large' implies a data size (ie. BLOB or CLOB) whereas 'wide' refers purely to spanning
columns. Generally all 'large' fields are implicitly 'wide', but not all 'wide' fields are 'large'. For example, you may want
a normal text field (not a text area) to span all columns.
|
OvalInspector inspects OVal annotations. It returns the following
attributes for the following business properties:
| Metawidget Attribute | OVal Annotation |
|---|---|
maximum-length |
@Length(max=...) or @MaxLength |
maximum-value |
@Max or @Range(max=...) |
minimum-length |
@Length(min=...) or @MinLength |
minimum-value |
@Min or @Range(min=...) |
required |
@NotNull or @NotEmpty or @NotBlank |
If you are using Sun's implementation of Java, Metawidget's annotation support requires Java 5.0u6 or later, which includes a fix for this bug (Bug Parade ID: 6322301).
Annotations are designed to 'silently fall away' in environments that do not
support them: they never throw ClassDefNotFoundError. For example,
if a JPA-annotated class is transferred to an application tier without ejb3-persistence.jar
(or equivalent) in its classpath, the JPA annotations will disappear.
If this is the cause, either add the appropriate JAR to the tier, or consider implementing a remote inspector (see Section 8.1, “Order Fields”).