Whilst we don't necessarily encourage the use of XML-based metadata, if you already have XML configuration files in your architecture Metawidget will take advantage of them. Equally, XML can be useful for declaring 'ad hoc' UI entities that do not map to any Java class, as well as for declaring UI-specific attributes for existing Java classes (i.e. if you prefer not to use annotations, or if you want to introduce additional 'virtual' properties).
Note when using XML-based metadata you should still try to avoid duplicating metadata that already exists in other parts of your application. For example, if you are also using PropertyTypeInspector in your CompositeInspector there is no need to duplicate the names and types of all properties.
Once nice feature of XML is that ordering of child elements (such as <property>) is explicit, so XML-based Inspectors make great 'first inspectors' for use within CompositeInspector (e.g. you don't need to also use @UiComesAfter).
BaseXmlInspector's config class, BaseXmlInspectorConfig, uses a setInputStream method to specify the location of the XML. This allows a variety of options for sourcing the XML. For example:
<xmlInspector xmlns="java:org.metawidget.inspector.xml" config="XmlInspectorConfig"> <inputStream> <resource>com/myapp/metawidget-metadata.xml</resource> </inputStream> </xmlInspector>
<xmlInspector xmlns="java:org.metawidget.inspector.xml" config="XmlInspectorConfig"> <inputStream> <url>http://myserver.com/my-xml.xml</url> </inputStream> </xmlInspector>
As well as specifying multiple files (which will all be merged and inspected as one):
<xmlInspector xmlns="java:org.metawidget.inspector.xml" config="XmlInspectorConfig"> <inputStreams> <array> <url>http://myserver.com/my-xml-1.xml</url> <url>http://myserver.com/my-xml-2.xml</url> </array> </inputStreams> </xmlInspector>
This functionality is extended to all XML-based Inspectors.
Several pieces of BaseXmlInspector functionality apply to mixing XML-based Inspectors (e.g. XmlInspector) and Object-based Inspectors (e.g. PropertyTypeInspector) in the same application (i.e. via CompositeInspector).
First, you may encounter a problem whereby the Object-based Inspectors will always stop at null or recursive references, whereas the XML Inspectors (which have no knowledge of Object values) will continue. This can lead to the WidgetBuilders constructing a UI for a null Object, which may upset some WidgetProcessors (e.g. BeansBindingProcessor). To resolve this, you can set BaseXmlInspectorConfig.setRestrictAgainstObject, whereby the XML-based Inspector will do a check for null or recursive references, and not return any XML. In addition, setting restrictAgainstObject allows the XML Inspector to traverse child relationships and infer their types using the Object. This saves having to explicitly specify those types and relationships in the XML.
Second, by default you need to explicitly specify any inheritance relationships between types in the XML, because the XML has no knowledge of your Java classes. This includes the names of any proxied classes. If this becomes laborious, you can set BaseXmlInspectorConfig.setInferInheritanceHierarchy to infer the relationships automatically from your Java classes. If you are using setRestrictAgainstObject, setInferInheritanceHierarchy is implied.
Third, it is important the properties defined by the XML and the ones defined by the Java classes stay in sync. To enforce this, you can set BaseXmlInspectorConfig.setValidateAgainstClasses.
CommonsValidatorInspector inspects Apache Commons Validator validation.xml files. It returns the following attributes for the following business properties:
|Metawidget Attribute||Validator XML|
|maximum-length||<field depends="maxlength" /><var><var-name>maxlength</var-name>...|
|maximum-value||<field depends="intRange" /><var><var-name>max</var-name>... (or floatRange or doubleRange)|
|minimum-length||<field depends="minlength" /><var><var-name>minlength</var-name>...|
|minimum-value||<field depends="intRange" /><var><var-name>min</var-name>... (or floatRange or doubleRange)|
|required||<field depends="required" />|
HibernateInspector inspects Hibernate hibernate.cfg.xml and mapping.hbm.xml files. For the former, it iterates over <session-factory>'s <mapping> elements and inspects all mapping files. It returns the following attributes for the following business properties:
|Metawidget Attribute||Hibernate XML|
|large||<property type="clob" />|
|maximum-length||<property length="..." />|
|parameterized-type||<bag type="..." /> or <list type="..." /> or <set type="..." />|
|required||<property not-null="true" />|
PageflowInspector inspects JBoss jBPM pageflow files looking for page nodes and their associated transitions to be used as actions. For example, this pageflow.jpdl.xml file...
<page name="confirm"> <transition name="purchase" to="complete" /> <transition name="cancel" to="cancel" /> </page>
...would return purchase and cancel as available actions for the confirm page. For an example of PageflowInspector in use, see Section 1.4.4, “jBPM Example”.
SeamInspector inspects Seam XML files for useful metadata. Specifically:
Delegates jbpm:pageflow-definitions elements from components.xml to PageflowInspector.
XmlInspector inspects files in inspection-result-1.0.xsd format. It can be used when no other Inspector is available for the given attribute.
Some attributes accept multiple values, such as lookup. These can be supplied as a comma-separated string. The values will be trimmed for whitespace. If the values themselves contain commas, they can be escaped with the \ character.
WsdlInspector inspects Web Services Description Language (WSDL) files. It extracts the XML Schema from the <schema> element of the WSDL and parses it for useful metadata.