# Definition of dynamic models using XML descriptors

Definition of dynamic models using XML descriptors

# Introduction

It is possible to define the underlying data model without having to write java code. To do this, you must use an XML descriptor which describes the DataNodes and their relationships. An skeleton XML descriptor has the following structure:

```XML
<?xml version="1.0" encoding="UTF-8"?>
<zkib-model>
    <datanode name="my-data">
        <finder name="title" type="title">
        </finder>
        <finder name="country" type="country">
            ...
        </finder>
    </datanode>
    <datanode name="title"/>
    <datanode name="country">
        <finder name="city" type="city">
            ...
        </finder>
    </datanode>
     
    <datanode name="city">
            ...
    </datanode>
</zkib-model>
```

<span class="notranslate">Within the XML tag whose root is always zk-ib, you can specify one or more DataNodes.</span> <span class="notranslate">Each DataNode has a unique name.</span> Within each<span class="notranslate"> DataNode, you can define multiple finders.</span> Each<span class="notranslate"> finder specifies a name and a type. The name will be used to build xpaths, whlie the type identifies the type of DataNode this xpaths refers to.</span>

<span class="notranslate">Within each finder you can define multiple search handlers.</span> They w<span class="notranslate">ill be responsible for retrieving data from persistent storage, just like the find method on the finder interface.</span> <span class="notranslate">Additionally, you can define one or new instance handlers.</span> <span class="notranslate">They will be responsible for creating new business objects on user request.</span>

<span class="notranslate">Finally, each DataNode can have many persistence handlers. They will act just lik the doInsert, doUpdate and doDelete methods on DataNode class. Each type of handler can</span><span class="notranslate"> be executed conditionally, depending on expressions to be evaluated at run time.</span> <span class="notranslate">These expressions can use the following predefined variables:</span>

<span class="notranslate">Additionally, EL expressions may refer to all variables defined within the DataSource. Those variables are accessed via JXPathContext.getVariables() method. </span>To use of this type of data models, simply create a datamodel component on the ZUL page and assign the src attribute the path to the XML descriptor. The path can be a web component or a class path resource.

<div id="bkmrk-variable-value-self-"><div><table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Variable: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" tabindex="0"><div>**Variable**</div></th><th aria-disabled="false" aria-label="Value: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" tabindex="0"><div>**Value**</div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd">self</td><td class="confluenceTd">Current DataNode</td></tr><tr role="row"><td class="confluenceTd">instance</td><td class="confluenceTd">Business object wrapped into current DataNode</td></tr><tr role="row"><td class="confluenceTd">parent</td><td class="confluenceTd">Parent DataNode</td></tr><tr role="row"><td class="confluenceTd">parent.instance</td><td class="confluenceTd">Business object wrapped into parent DataNode</td></tr><tr role="row"><td class="confluenceTd">datasource</td><td class="confluenceTd">DataSoruce the current DataNode belongs to</td></tr></tbody></table>

</div></div>

# Ejb-handler Handler

It is responsible for persisting the object via a stateless session bean. The following attributes are supported:

<table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" id="bkmrk-attribute-usage-jndi" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" tabindex="0"><div>**Attribute**</div></th><th aria-disabled="false" aria-label="Usage: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" tabindex="0"><div>**Usage**</div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd">jndi

</td><td class="confluenceTd">JNDI path to EJB Home interface

</td></tr><tr role="row"><td class="confluenceTd">if

</td><td class="confluenceTd">EL expression that must be evaluated to true prior to handler action

</td></tr><tr role="row"><td class="confluenceTd">unless

</td><td class="confluenceTd"> EL expression that must be evaluated to false prior to handler action</td></tr></tbody></table>

<span class="notranslate">Inside the handler, you should specify the suitable insert-method, delete-method and update-method tags.</span> There is a mandatory attribute named method. This attribute must contain the name of the method to invoke. Additionally, the parameters to use can be specified. <span class="notranslate">The following example shows an ejb-handler that uses an EJB whose only parameter is the data object:</span>

```western
<datanode name="network">
    <ejb-handler jndi="com.soffid.sample/NetworksBean">
        <insert-method method="insert"/>
        <delete-method method="delete"/>
        <update-method method="update"/>
    </ejb-handler>
        ...
</datanode>
```

This second example shows how to call a method with slightly complex parameters:

```XML
<datanode name="acl">
    <ejb-handler jndi="com.soffid.sample/NetworksBean" >
        <insert-method method="grant">
            <parameter value="${parent.instance}"/>
            <parameter value="${instance}"/>
        </insert-method>
        <delete-method methos="revoke"> 
            <parameter value="${instance}"/>
        </delete-method>
    </ejb-handler>
</datanode>
```

# Script-handler Handler

It ca be used to persist the business objects using BSH scripts. Supports the following attributes:

<div id="bkmrk-attribute-usage-if-e"><table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" tabindex="0"><div>**Attribute**</div></th><th aria-disabled="false" aria-label="Usage: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" tabindex="0"><div>**Usage**</div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd">if

</td><td class="confluenceTd">EL expression that must be evaluated to true prior to handler action

</td></tr><tr role="row"><td class="confluenceTd">unless

</td><td class="confluenceTd"> EL expression that must be evaluated to false prior to handler action</td></tr></tbody></table>

</div><span class="notranslate">Inside the handler, you can use the insert-script, delete-script and update-script tags.</span> <span class="notranslate">Each contains the BSH script that the engine will execute to perform inserts, deletes or updates.</span> <span class="notranslate">Within the BSH script you can refer to the same EL expressions predefined variables:</span>

<div id="bkmrk-variable-value-self-"><table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Variable: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" tabindex="0"><div><div>**Variable**</div></div></th><th aria-disabled="false" aria-label="Value: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" tabindex="0"><div><div>**Value**</div></div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd">self</td><td class="confluenceTd">Current DataNode</td></tr><tr role="row"><td class="confluenceTd">instance</td><td class="confluenceTd">Business object wrapped into current DataNode</td></tr><tr role="row"><td class="confluenceTd">parent</td><td class="confluenceTd">Parent DataNode</td></tr><tr role="row"><td class="confluenceTd">parent.instance</td><td class="confluenceTd">Business object wrapped into parent DataNode</td></tr><tr role="row"><td class="confluenceTd">datasource</td><td class="confluenceTd">DataSoruce the current DataNode belongs to</td></tr></tbody></table>

</div><span class="notranslate">The following example shows how to save objects in file Country:</span>

```XML
<datanode name="country">
    <script-handler >
        <insert-script>
            import java.io.*;
            f = new FileOutputStream ("country."+instance.abbreviation);
            oos = new ObjectOutputStream (f);
            oos.writeObject (instance);
            oos.close ();
            f.close ();
        </insert-script>
        <update-script>
            import java.io.*;
            f = new FileOutputStream ("country."+instance.abbreviation);
            oos = new ObjectOutputStream (f);
            oos.writeObject (instance);
            oos.close ();
            f.close ();
        </update-script>
        <insert-script>
            import java.io.*;
            f = new File ("country."+instance.abbreviation);
            f.delete ();
        </insert-script>
    </script-handler>
        ...
</datanode>
```

# Collection-handler Handler

<span class="notranslate">This handler is applicable when the persistence of this object is managed by the parent dataNode. The allowed attributes are:</span>

<div id="bkmrk-attribute-usage-coll"><table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" tabindex="0"><div><div>**Attribute**</div></div></th><th aria-disabled="false" aria-label="Usage: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" tabindex="0"><div><div>**Usage**</div></div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd">collection

</td><td class="confluenceTd">EL expression that identifies the collection onto which the business object must be added or removed

</td></tr><tr role="row"><td class="confluenceTd">if

</td><td class="confluenceTd">EL expression that must be evaluated to true prior to handler action

</td></tr><tr role="row"><td class="confluenceTd">unless

</td><td class="confluenceTd">EL expression that must be evaluated to false prior to handler action</td></tr></tbody></table>

</div><span class="notranslate">The following example shows how you could manage objects City as a collection of objects within the object Country, which in turn is saved on a disk arhivo:</span>

```
<datanode name="city">
    <collection-handler collection="${parent.instance.cities}">
</datanode>
```

# Custom-handler Handler

<span class="notranslate">The custom-handler provides coverage for situations where you need a more sophisticated handler and it is not worth to use a bsh script., In this case the persistence must be done be a java class that implements the PersistenceHandler interface, and the custom-handler specifying the name of the class used. The attributes are:</span>

<div id="bkmrk-attribute-usage-clas"><table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" tabindex="0"><div><div>**Attribute**</div></div></th><th aria-disabled="false" aria-label="Usage: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" tabindex="0"><div><div>**Usage**</div></div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd">className

</td><td class="confluenceTd">Name of the java class to be used

</td></tr><tr role="row"><td class="confluenceTd">if

</td><td class="confluenceTd">EL expression that must be evaluated to true prior to handler action

</td></tr><tr role="row"><td class="confluenceTd">unless

</td><td class="confluenceTd"> EL expression that must be evaluated to false prior to handler action</td></tr></tbody></table>

</div>

# Data validation

<span class="notranslate">The validation tag is responsible for performing basic checks regarding mandatory attributes and valid attribute values before being submitted to the persistence handler.</span> <span class="notranslate">The validation tag may contain one or more attribute-validation and script-validation tags.</span> <span class="notranslate">The verification will be performed before running the insert or update handler.</span>

<span class="notranslate">attribute-validator contains the following attributes:</span>

<div id="bkmrk-attribute-usage-expr"><table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" style="width: 116px;" tabindex="0"><div><div>**Attribute**</div></div></th><th aria-disabled="false" aria-label="Usage: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" style="width: 693px;" tabindex="0"><div><div>**Usage**</div></div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd" style="width: 116px;">expr

</td><td class="confluenceTd" style="width: 693px;">EL expression pointing to the attribute to validate

</td></tr><tr role="row"><td class="confluenceTd" style="width: 116px;">friendlyName

</td><td class="confluenceTd" style="width: 693px;">Text to be presented to the user on validation failure. If there is a ZK label with this text, it will be localized based on current user language preference.

</td></tr><tr role="row"><td class="confluenceTd" style="width: 116px;">notNull

</td><td class="confluenceTd" style="width: 693px;">true is the attribute is mandatory</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 116px;">maxLength</td><td class="confluenceTd" colspan="1" style="width: 693px;">Maximum length of the attribute</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 116px;">minValue</td><td class="confluenceTd" colspan="1" style="width: 693px;">Minimum value in case of numeric attributes</td></tr><tr role="row"><td class="confluenceTd" colspan="1" style="width: 116px;">maxValue</td><td class="confluenceTd" colspan="1" style="width: 693px;">Maximum value in case of numeric attributes</td></tr></tbody></table>

</div><span class="notranslate">attribute-script contains a script that will be executed to validate the business object.</span>

<span class="notranslate">Example:</span>

```western
<datanode name="country">
    <validation>
        <attribute-validation expr=”${instance.abbrevisation}”
                notNull=”true” friendlyName=”Two letter abbrv.”>
        <script-validation>
            if (instance.abbreviaton.equals(“CT”))
            {
                throw new RuntimeException (“Catalonia is not a country yet”);
            }
        </script-validation>
    </validation>
        ...
</datanode>
```

# EJB find handler: ejb-finder

<span class="notranslate">Handles the method to retrieve business objects via a stateless session bean.</span> <span class="notranslate">Supports the following attributes:</span>

<div id="bkmrk-attribute-usage-jndi"><table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" tabindex="0"><div><div>**Attribute**</div></div></th><th aria-disabled="false" aria-label="Usage: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" tabindex="0"><div><div>**Usage**</div></div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd">jndi

</td><td class="confluenceTd">JNDI path to EJB Home interface

</td></tr><tr role="row"><td class="confluenceTd" colspan="1">method</td><td class="confluenceTd" colspan="1">EJB Bean method to get business objects</td></tr><tr role="row"><td class="confluenceTd">if

</td><td class="confluenceTd">EL expression that must be evaluated to true prior to handler action

</td></tr><tr role="row"><td class="confluenceTd">unless

</td><td class="confluenceTd"> EL expression that must be evaluated to false prior to handler action</td></tr></tbody></table>

</div><span class="notranslate">Additionally, it can specify one or more parameters in a way similar to the ejb-handler methods</span>

<span class="notranslate">ejb-finder example</span>

```western
<datanode name="country">
        ...
    <finder name="cities" type="city" >
        <ejb-finder jndi="com.soffid.sample/CitiesBean" method="findByCountry">
            <parameter value="${instance.abbreviation}"/>
        </ejb-finder>
    </finder>
        ...
</datanode>
```

# script-finder handler

<span class="notranslate">It is responsible for retrieve business objects from the persistence layer using BSH scripts. The following attributes are supported</span>

<div id="bkmrk-attribute-usage-if-e"><table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" role="grid" style="height: 98px; width: 689px;"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row" style="height: 28px;"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" style="height: 28px; width: 118px;" tabindex="0"><div><div>**Attribute**</div></div></th><th aria-disabled="false" aria-label="Usage: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" style="height: 28px; width: 571px;" tabindex="0"><div><div>**Usage**</div></div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row" style="height: 35px;"><td class="confluenceTd" style="height: 35px; width: 118px;">if

</td><td class="confluenceTd" style="height: 35px; width: 571px;">EL expression that must be evaluated to true prior to handler action

</td></tr><tr role="row" style="height: 35px;"><td class="confluenceTd" style="height: 35px; width: 118px;">unless

</td><td class="confluenceTd" style="height: 35px; width: 571px;"> EL expression that must be evaluated to false prior to handler action</td></tr></tbody></table>

</div><span class="notranslate">The contained bsh script must return a collection of business objects. If the returned object is not a collection object, the engine will treat the returned object as a singleton.</span>

<span class="notranslate">In the following example, the script finder retrives all countries saved to disk in the previous example:</span>

```western
<datanode name="root">
    ...
    <finder name="country" type="country" >
        <script-finder >
            import java.io.*;
            files[] = new File(".").listFiles ( new FilenameFilter () {
                public boolean accept (File dir, String name) {
                    return name.startsWith("coutnry.");
                }
            );
            v = new java.util.Vector();
            for (int i = 0; i < files.length; i++)
            {
                f = new FileInputStream (files[i]);
                ois = new ObjectInputStream (f);
                v.add (ois.readObject ();
                ois.close ();
                f.close();
            }
            return v;
        </script-finder>
    </finder>
    ...
</datanode>
```

# collection-finder handler

<span class="notranslate">Similar to collection-handler, this handler retrieves the list objects contained on a parent collection.</span>

<div id="bkmrk-attribute-usage-coll"><table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" tabindex="0"><div><div>**Attribute**</div></div></th><th aria-disabled="false" aria-label="Usage: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" tabindex="0"><div><div>**Usage**</div></div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd">collection

</td><td class="confluenceTd">EL expression that contains the objects collection

</td></tr><tr role="row"><td class="confluenceTd">if

</td><td class="confluenceTd">EL expression that must be evaluated to true prior to handler action

</td></tr><tr role="row"><td class="confluenceTd">unless

</td><td class="confluenceTd">EL expression that must be evaluated to false prior to handler action</td></tr></tbody></table>

</div><span class="notranslate">The following example shows how you could retrieve City objects as a collection of objects within the County object:</span>

```western
<datanode name="country">
        ...
    <finder name="cities" type="city" >
        <collection-finder collection="${instance.cities}">
    </finder>
        ...
</datanode>
```

# custom-finder handler

<span class="notranslate">The custom-finder provides coverage for situations where you need a more sophisticated handler and is not worth implement it using a script. In this case a class that implements the FinderHandler interface must be developed, and the custom-finder specifying the name of the class must be used</span>

<div id="bkmrk-attribute-usage-clas"><table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" tabindex="0"><div><div>**Attribute**</div></div></th><th aria-disabled="false" aria-label="Usage: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" tabindex="0"><div><div>**Usage**</div></div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd">className

</td><td class="confluenceTd">Name of the FinderHandler class

</td></tr><tr role="row"><td class="confluenceTd">if

</td><td class="confluenceTd">EL expression that must be evaluated to true prior to handler action

</td></tr><tr role="row"><td class="confluenceTd">unless

</td><td class="confluenceTd">EL expression that must be evaluated to false prior to handler action</td></tr></tbody></table>

</div>

# new-instance-script handler

<span class="notranslate">It is responsible for instantiating new objectswithin a finder on user request .</span>

<div id="bkmrk-attribute-usage-if-e"><table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" style="width: 81px;" tabindex="0"><div><div>**Attribute**</div></div></th><th aria-disabled="false" aria-label="Usage: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" style="width: 458px;" tabindex="0"><div><div>**Usage**</div></div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd" style="width: 81px;">if

</td><td class="confluenceTd" style="width: 458px;">EL expression that must be evaluated to true prior to handler action

</td></tr><tr role="row"><td class="confluenceTd" style="width: 81px;">unless

</td><td class="confluenceTd" style="width: 458px;">EL expression that must be evaluated to false prior to handler action</td></tr></tbody></table>

</div><span class="notranslate">With the following example the model will alow to create a new city within a country:</span>

```western
<datanode name="country">
    ...
    <finder name="cities" type="city" >
        <collection-finder collection="${instance.cities}">
        <new-instance-script>
            c = new City();
            c.countryAbbreviation = instance.abbreviation;
            return c;
        </new-instance-script>
    </finder>
    ...
</datanode>
```

# new-instance-bean handler

<span class="notranslate">This handler allows the craetion of a new business object and assign default attribute values.</span> <span class="notranslate">The value of the bean attributes is specified using multiple instances of the bean-attribute tag</span>

<div id="bkmrk-attribute-usage-clas"><table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" tabindex="0"><div><div>**Attribute**</div></div></th><th aria-disabled="false" aria-label="Usage: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" tabindex="0"><div><div>**Usage**</div></div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd">className

</td><td class="confluenceTd">Name of the business object class

</td></tr><tr role="row"><td class="confluenceTd">if

</td><td class="confluenceTd">EL expression that must be evaluated to true prior to handler action

</td></tr><tr role="row"><td class="confluenceTd">unless

</td><td class="confluenceTd">EL expression that must be evaluated to false prior to handler action</td></tr><tr role="row"><td class="confluenceTd" colspan="1">bean-attribute/name</td><td class="confluenceTd" colspan="1">Name of the attribute</td></tr><tr role="row"><td class="confluenceTd" colspan="1">bean-attribute/value</td><td class="confluenceTd" colspan="1">EL expression with the value to assign</td></tr></tbody></table>

</div><span class="notranslate">With the following example would create a new city within a country:</span>

```western
<datanode name="country">
    ...
    <finder name="cities" type="city" >
        <collection-finder collection="${instance.cities}">
        <new-instance-bean  className="City">
            <bean-attribute name="countryAbbreviation" value="${instance.abbreviation}"/>
        </new-instance-bean>
    </finder>
    ...
</datanode>
```

# custom-attribute handler

<span class="notranslate">Generates virtual attributes derived from other attributes or external elements of the application.</span> <span class="notranslate">It can be applied to any DataNode to add attributes that were not originally present at the underlying business object. Those attributes will be presented at the JXPath interface just as if they were business objects attributes</span>

<div id="bkmrk-attribute-usage-name"><table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" tabindex="0"><div><div>Attribute</div></div></th><th aria-disabled="false" aria-label="Usage: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" tabindex="0"><div><div>Usage</div></div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd">name

</td><td class="confluenceTd">Name of the virtual attribute

</td></tr><tr role="row"><td class="confluenceTd" colspan="1">expr</td><td class="confluenceTd" colspan="1">EL expression that evaluates de attribute value</td></tr><tr role="row"><td class="confluenceTd">if

</td><td class="confluenceTd">EL expression that must be evaluated to true prior to handler action

</td></tr><tr role="row"><td class="confluenceTd">unless

</td><td class="confluenceTd">EL expression that must be evaluated to false prior to handler action</td></tr><tr role="row"><td class="confluenceTd" colspan="1">depends</td><td class="confluenceTd" colspan="1">XPath to a attribute or business object the expression depends on</td></tr></tbody></table>

</div>It's important to properly set the depends attribute as long as the attribute will be reevaluated whenever a dependent attribute has been changed.

The custom attribute can have an empty EL expressions and use a BeanShell script instead. Here is an example of both aproaches:

```western
<datanode name="network">
    <custom-attribute name=”networkMask1” expr=”${instance.network}/${instance.mask}”>
    <custom-attribute name=”networkMask2”>
        <depends>@network</depends>
        <depends>@mask</depends>
        return instance.network + “/” + instance.mask;
    </custom-attribute>
    ...
</datanode>
```

# Using dynamic models

To use dynamic models XmlDataSource tag must be replaced by datamodel. The datamodel tag has the following attributes:

<div id="bkmrk-attribute-usage-id-z"><table class="confluenceTable tablesorter tablesorter-default stickyTableHeaders" role="grid"><thead class="tableFloatingHeaderOriginal"><tr class="tablesorter-headerRow" role="row"><th aria-disabled="false" aria-label="Attribute: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="0" role="columnheader" scope="col" tabindex="0"><div><div>**Attribute**</div></div></th><th aria-disabled="false" aria-label="Usage: No sort applied, activate to apply an ascending sort" aria-sort="none" class="confluenceTh tablesorter-header sortableHeader tablesorter-headerUnSorted" data-column="1" role="columnheader" scope="col" tabindex="0"><div><div>**Usage**</div></div></th></tr></thead><tbody aria-live="polite" aria-relevant="all"><tr role="row"><td class="confluenceTd">id

</td><td class="confluenceTd">ZK Identifier

</td></tr><tr role="row"><td class="confluenceTd">className

</td><td class="confluenceTd">root DataNode class name

</td></tr><tr role="row"><td class="confluenceTd">src

</td><td class="confluenceTd">XML resource name for XML dynamic data model</td></tr><tr role="row"><td class="confluenceTd" colspan="1">rootNode</td><td class="confluenceTd" colspan="1">Root node type for dynamic data model</td></tr></tbody></table>

</div>className usage is not compatible with src and rootNode attributes.

rootNode attribute is mandatory when using XML dynamic data models.