MetaWareJ®
User Guide

What is MetaWareJ
MetaWareJ is a framework and a tool for creating web-based business applications. “Business applications” means applications that deal with data input, validation and processing, based on a set of business requirements and rules. Examples of these are any type of inventory, invoicing, customer database, sales, application bridges, government work (customs, ports, civil registry, internal revenue), etc.
Applications built with MetaWareJ™ are Java web applications utilizing HTML/JavaScript. At the same time, they can be installed on an Android device and use the native user interface. They can also be deployed, without modifications, as web services. They can produce a variety of outputs such as charts, PDF reports, CSV exports etc. As an example of how dynamic MetaWareJ applications can be, you can run them using the Command line Interface. A traditional GUI front end (using Swing) is also available.
The basic design principle of MetaWareJ™ is that screens are simple and homogeneous, and that the programmer does not have to deal with them. Producing outputs of different formats does not require re-programming (or designing) the output. In this sense, MetaWareJ is best utilized in business applications where the efficiency of the user interface is one of the primary design goals.
As a developer, all you need to define is the retrieval and update of data, the validations and the screen content in a very simple MetaWareJ™ XML language. You are then free to program your business rules. Your application is ready and is running bug-free. See how easy it is by reading Your first MetaWareJ application: A tutorial.
MetaWareJ uses mainly direct JDBC access to a database. It is best suited for small to medium size installations.
MetaWareJ is an open source application, licensed under Apache License, Version 2.0.
For more information, please contact us first at metawarej@methodosit.com.cy or visit our web side www.methodosit.com.cy for details.
The basic building blocks are shown in the diagram. MetaWareJ consists of 4 main parts:
MetaWareJ
Processing
XML Screen
Definitions
Database
(or other
data store)
PDF/PDF Forms
Charts
Export XML/Text
Data Reader
Data Writer
Custom
Business
Rules
Web Client
Android Ô
Command Line
Web Services
An XML language which defines how to access the data, how to process them, how and where to display them.
The main processing logic which receives and processes the request from the user using the definitions in the XML files.
A database reader and a database writer to handle database transactions.
User interface generators which show the result to the user in the requested format.
MetaWareJ reads the XML definitions, accesses the data from the database and displays them to the user. An application developer needs to handle the parts shown in yellow in the diagram: The XML definitions and the custom business logic. The rest are handled by MetaWareJ.

Installation and building MetaWareJ Applications
Most common applications built with MetaWareJ are Java web applications using:
servlets
custom generators to create the user interface and other outputs.
JDBC to connect to the database.
XML definition files for screen layout and data processing.
MetaWareJ applications run on Tomcat or other servlet containers/application servers.
MetaWareJ applications are also Android applications and can run from command line interface etc, as we will see later.

3rd Party Tools and Applications
In order to develop and run MetaWareJ applications we need some 3rd party tools and applications installed.
Although MetaWareJ is open source, licensed under the Apache License, Version 2.0, please check the license terms of each 3rd party module to see how they apply to you.
For the runtime environment we need/support the following:
Java Environment	Java Platform Standard Edition (Java SE version 1.7 or later). We don't need the Enterprise Edition.
Application Server	We develop with Tomcat version 7 or later. Jboss version 5 and Weblogic 11g and 12 have been tested. Other application servers should work with little setup effort.
Database and related JDBC drivers	MySQL version 5 with innodb tables MariaDb version 10 Oracle Informix PostgreSQL
iText	Optional, for the creation of PDF reports and fill-in forms.
SVNKit	Version 1.8 or later. For access to subversion through MeatWareJ applications.
For the development environment:
Apache ant	Version 1.7 or later. If your using an IDE (Netbeans, Eclipse) it should be part of your development environment already.
Sybase PowerDesigner	Version 11. It can be integrated into the development process but it is not required.
PDF Form creator	If you want to use pre-printed (fill-in) PDF forms, you will need some tool to create them. Exporting OpenOffice and LibreOffice forms to PDF works for us.
Android SDK	If you plan to deploy on Android you will need to install the Android SDK
Additionally the following 3rd party libraries are delivered with MetaWareJ:
Apache log4j
JFreeChart	For the creation of charts
Mousetrap	JavaScript keyboard handling Copyright 2016 Craig Campbell, http:craig.is/killing/mice
Pikaday	Calendar support. We ship a modified version. Copyright © 2014 David Bushell
Font Awesome	by @davegandy - http://fontawesome.io
Apache PDFBox	https://pdfbox.apache.org/
JSON in Java [package org.json]	https://github.com/stleary/JSON-java
JavaMail	https://javaee.github.io/javamail/

How to install MetaWareJ
You can download a jar executable installer which will help you install MetaWareJ on either Windows or Linux. To install, download the MetaWareJ-installer.jar file in a temporary directory and run it. If your system does not know how to run jar archives you can start the installer by typing
java -jar MetaWareJ-installer.jar
at a command prompt/shell.
Screen 1: Installer Screen
The installation comes with reference documentation, including this manual. If you installed using the installer, look under you system's menu for links to the available documentation.
You can also download a gzipped tar or a zip archive and install it yourself. To install, uncompress it with your favorite utility in any directory on your PC. This will create a directory called MetaWareJ.
The directory holds:
database	initial database schema files
docs	MetaWareJ Javadoc, XML reference (Form.html) and this manual in PDF form
webapp, editor	Used by the application build script to deploy MetaWareJ base files.

Installing the Demo Application
You can download the MetaWareJ Demo application from our website. The Demo for Windows and Linux is delivered as a jar executable called demo-installer.jar. You can run the installer using:
java -jar demo-installer.jar
This will guide you through the installation process.
You can run the Demo under Apache Tomcat (or other servlet containers/application server) by installing under the Tomcat's webapps directory, or whichever location you application server installation expects to find its web applications.
For Android, you can download an Android package called demo-release.apk. You can login using any user name and password.
You can also download the source package of the Demo application. It is delivered as either zipped of gzipped tar archive. You can unzip the source in any directory and have access to all the XML and java files referenced in this document.
If you have MetaWareJ installed, you can unzip the Demo source in the directory where MetaWareJ is installed. You can then edit the build.xml delivered with the source and add the property:
<property name="deploy.dir" location="TOMCAT_WEBAPPS_DIR"/>
The TOMCAT_WEBAPPS_DIR is the directory where you want the compiled application installed, e. g. c:\tomcat\webapps\demo. After that you can compile and deploy any changes you want to make by running in the demo directory:

ant deploy
How to create a MetaWareJ Application
After installation you will need to create your application. During installation a “Create a MetaWareJ Application” shortcut was created. (If you chose to install by archive, this is the script createApp.sh/createApp.cmd in the MetaWareJ directory). When you run the shortcut you will see a screen that will help you create your application. Each field has a help instruction that explains how to use it.
Screen 2: Create Application Screen
All the application files will be located in a single application development directory. When you create an application using the method above, the application directory will be “Base Directory”/”Application Name”, e.g. if you enter C:\MyDevelopement as “Base Directory” and MyApplication as “Application Name” the application development directory will be C:\MyDevelopement\MyApplication.
Files from the application directory and the MetaWareJ directory are copied during deployment to create the web application directory from which the application runs. The web application directory is a standard web application structure.
The created application directory has the following:
webapp directory	You create your MetaWareJ XML definition files here, in webapp/WEB-INF/xml/<Application Name> to be precise. When deployed, files from webapp such as the WEB-INF directory structure (with classes, lib, XML etc) and the js directory are copied to the web application directory.
src directory	Contains your Java source files. Files from here are compiled into the web application directory.
conf	Tomcat context.xml based on the information you entered.

Creating Initial Database
You will need to create an initial database as well. For MySQL, the scripts mysql.sql and initial_data.sql (under MetaWareJ/database) will create and populate the initial database with some needed tables and data, mainly for the menu and users.
See Initial Database for schema details. You will find scripts for other databases (Oracle, PostgreSQL and Informix) under MetaWareJ/database as well.
The initial users will be:
admin with password admin and level administrator and
user with password user and level level4.
For MySQL, the sequence of commands is similar to:
cd database
mysql -uuser -p
and at the mysql prompt:
create database MyApplication;
use MyApplication;
source mysql.sql;
source initial_data.sql;
Note that the database name is the same as the application name, MyApplication in this example.
When you create an application, a Tomcat context.xml file is created under MyApplication/conf/tomcat/META-INF. The file contains a Resource entry for the connection pool that MetaWareJ needs. You can set any optional JDBC parameters there. You can also use a different database name and change URL in the context.xml, if you like.
If you work with something other than Tomcat you need to create the appropriate connection pool settings yourself. MetaWareJ finds the DataSource resource using JNDI under the name java:comp/env/jdbc/MetaWareJ.
Also note that the JDBC driver for MySQL (or any JDBC driver) is not delivered with MetaWareJ. You will need to setup your database connectivity yourself. For MySQL on Tomcat Version 6 or 7, this means downloading the MySQL Connector/J jar file and placing it under the lib directory of Tomcat. You will need a JDBC driver for Oracle, Informix or PostgreSQL, if you plan to use these.

Developing your Application
In MetaWareJ you will need to develop the following:
XML definition files under MyApplication/webapp/WEB-INF/xml/MyApplication.
Java source files under MyApplication/src.
(occasionally) JavaScript files under MyApplication/webapp/js.
You can create the XML definitions either by hand or you can use the MetaWareJ editor. If you want to learn more about writing your own XML files and how they work, go back and read Your first MetaWareJ application: A tutorial and create the examples XML yourself. If you prefer to use the MetaWareJ editor go to How to use the MetaWareJ XML Editor. In either case, take a look at Advanced to see what else MetaWareJ includes.
You can program using your favorite IDE/editor. Just save the code in MyApplication/src. You will not need to write any Java code right away. You will need it when you want to set the specific business rules of your domain. For this see Adding Business Logic and Programming with MetaWareJ.

Deploy and Run
An Ant build build.xml script is created in the application directory for compiling/deploying the application.
To create a web application, enter the development directory and type:
ant
The application is now deployed. Then go to your browser and point it to wherever Tomcat is found. Assuming your are running from the local machine use something like:
http://localhost:8080/MyApplication
You should see the login screen:
Screen 3: Login
The Ant script has the following main targets:
deploy	deploys all files to the webapp directory
build	compile source in the build directory
clean	delete deployment and build directories
javadoc	Javadoc

Build Android Applications
The same application you have created for web can be used unchanged as a native Android application, as shown in the Your first MetaWareJ application: A tutorial.
MetaWareJ Android apps are multi-tier application. They use JSON messaging to an installation of the same application on an application server. The communication from the Android app to the application server can be SSL (https) and can use a client certificate for authentication. The communication parameters must be entered in the global.parameters file of the application before building the Android app package. These parameters are:
JSON_URL	URL of the application, Either https or http can be used. Example: https://www.methodosit.com.cy/offers
SSLClientCertificate	If the protocol of the JSON_URL is https and the server needs a client certificate. This is the file name of the client certificate in PKCS12 format. The file should be placed under /WEB-INF/data/ directory. Only the name of the file should be entered here.
SSLClientCertificatePassword	Password for the client certificate above.
SSLRootCertificate	If the protocol of the JSON_URL is https and the server uses a self-signed certificate. This is the file name of the root CA certificate in PEM format. The file should be placed under /WEB-INF/data/ directory. Only the name of the file should be entered here.
JSON messaging is used by default as long as JSON_URL is provided. You can always use some other back end storage for Android apps but you have to provide your own ServerDataReaders and ServerDataWriters, see section Programming with MetaWareJ. The demo application for example, which you can download from our website, uses plain text files as back end even on Android. See also Error: Reference source not found.
MetaWareJ integrates with the Android SDK package so that you can develop your application without knowing the Android environment. You do need however to download, install and setup Android SDK and create at least one Android Virtual Device (ADV) for testing. The Android SDK installation is beyond the scope of this document. You can find clear instructions on the Android developer web side.
After you install both MetaWareJ and Android SDK, you need to set some Android properties. Edit the file MetaWareJ/android/local.properies located where you installed MetaWareJ.
Set the property sdk.dir to the directory where you installed Android SDK.
Set the property target to the Android API version you installed. Look at the Android SDK
Manager tool and Android documentation for more on this. Needs to be at least android-13.
If you have any additional jar files to be used with your Android application, put them in MetaWareJ/android/lib-extra.
Android uses signed packages for release level packages. We include ant targets for building release packages for your application directly from MetaWareJ. You will need however to setup a private key and key store as per Android instructions. You will also need to add the key store information in the MetaWareJ/android/ant.properties files.
There are four ant targets related to Android
build-android-debug	builds an Android application in debug mode. The android package will be in build-android/bin directory.
build-android-release	builds an Android application in release mode. The android package will be in build-android/bin directory.
deploy-android-debug	builds and installs an Android application in debug mode. It will try to install the package after build in the default android device. See the Android documentation on how to set this up.
deploy-android-release	builds and installs an Android application in release mode. It will try to install the package after build in the default android device. See the Android documentation on how to set this up.

Your first MetaWareJ application: A tutorial
We will explain how to build MetaWareJ applications using a series of examples. We have tried to make them as realistic as possible but simple enough to explain the concepts without too many details.
MetaWareJ applications consist of an XML file per screen in a language that we will explain in this tutorial. We will also explain how to insert your business logic and how to access the data in order to enforce your business rules.
This tutorial assumes that we are working with a direct JDBC connection to a supported database. The database schema is
Drawing 1: Demo Database Schema
You can find all example code in the demo application source delivered from our website. You will find the XML files used in this tutorial under the path WEB-INF/xml/demo/manual under the directory you choose to install the demo application or the demo source. You can also download and install the working demo application which runs stand-alone, as a Tomcat web application, and as an Android application. See Installing the Demo Application for installation instructions.
The examples assume that the MetaWareJ is already installed. If you want to develop the examples as you read this tutorial, download and install MetaWareJ as detailed in section How to install MetaWareJ .
The tutorial only covers the basic concepts of developing with MetaWareJ:
We keep referring to the “XML reference manual” which covers the full details of the MetaWareJ XML language, see XML definition language. If you have installed MetaWareJ, you will find a menu shortcut for the reference under “MetaWareJ XML Reference”. Also look under the MetaWareJ/docs directory for all available documentation.
You can edit the XML files by hand as shown in this tutorial. MetaWareJ, however, comes with a web application, the XML Editor, to help you write these files. See How to use the MetaWareJ XML Editor.

Display-only data
We will start by creating a read-only screen. We want to show the data of a simple table CUSTOMER which has three columns: ID int, USER_CODE varchar(10) and NAME varchar(50). See Screen 4: Display Only Table in Web Application and Screen 5: Android Display Only Screen.
The entire XML definition is as follows:
(see WEB-INF/xml/demo/manual/cust_readonly.xml in the Demo application directory)
<?xml version="1.0" encoding="UTF-8"?>
<form title="m_readonly" hasHeader="false"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.methodosit.com.cy/MetaWareJ
http://www.methodosit.com.cy/MetaWareJ.xsd"
xmlns='http://www.methodosit.com.cy/MetaWareJ'>
<table name="d" title="customer" function="READONLY" format="GRID">
<recordset >
<selectString orderBy="user_code">
select id,user_code,name from customer
</selectString>
</recordset>
<controls>
<input name="code" dbname="user_code" size="10" label="usercode"/>
<input name="name" label="custname" size="25" maxLength="50" />
</controls>
</table>
</form>
Let's see what it means.
The root element is a <form>. The schema information is requered by XML and helps validate the XML. It is just repeated in each XML file. This form consists of a single <table>. A <table> here means a set of data to be read, displayed and updated together.
The form title is “m_readonly” but it displays as “Readonly Table” because of the localization support of MetaWareJ. More on this in Localization. For now keep in mind that all labels, titles, etc. are kept in a global dictionary and the XML holds the keys to these labels.
The table reads the database table CUSTOMER using the SQL in the <recordset> element. No arguments are provided and the entire table will be read.
The table has two controls, the code and name which are listed under the <controls> element.
<controls>
<input name="code" .../>
<input name="name" ... />
</controls>
Defines the controls
<table name="d" title="customer" function="READONLY" format="GRID">
Defines a new table which will be shown as grid and sets the title
<form title="m_readonly">
Defines a form and sets the title
Screen 4: Display Only Table in Web Application
Each element has various attributes or chilrden elements that we will not cover in full detail here. The name attribute in <table> and each <input> control is important. It must be unique within each table of a <form>. It will allow us later to access the data. The dbname attribute of each <input> control links the control to the data retrieved by the select statement. So, dbname=”user_code” will read the column user_code.
Screen 5: Android Display Only Screen

Updating Data
The previous form can only display data. What needs to be done in order to be able to add, delete and update customers?
See Screen 6: Table with Update Capability, Screen 7: Android Table With Update Capability, and Screen 8: MetaWareJ Error Message.
The new XML is listed below. The bold sections are new.
(see WEB-INF/xml/demo/manual/cust_update.xml):
<form title="m_update_table" >
<table name="d" title="customer" function="DATA" format="GRID">
<recordset >
<selectString orderBy="user_code">
select id,user_code,name from customer
</selectString>
</recordset>
<update table="customer"/>
<controls>
<hidden name="id" type="INT" key="true" auto="true" protect="true"/>
<input name="code" dbname="user_code" size="10" label="usercode" />
<input name="name" label="custname" size="25" maxLength="50" />
<delete/>
</controls>
<buttons>
<button type="UPDATE"/>
<button type="ADD"/>
</buttons>
</table>
</form>
The <update> element defines the database table. The added <hidden> control defines the primary key (key=”true”) which in our case is auto-increament (auto=”true”) and cannot be changed by the user (protect=”true”) . MetaWareJ will decide automatically if a record needs updating and if it is to be updated, inserted or deleted and will create the SQL statements.
The <buttons> section adds the two buttons on the HTML form, as shown in Screen 6: Table with Update Capability. In Android clients, buttons are added to the action bar or the menu, see Screen 7: Android Table With Update Capability.
Screen 6: Table with Update Capability
Screen 7: Android Table With Update Capability
All input validations are also done automatically, including data type validations. Validations are done both on the client (in the browser using JavaScript), and on the server before updating. There are various types of validations and constrains that MetaWareJ will enforce. We will cover these later.
For now, let's look at the CUSTOMER.USER_CODE column. It was designed to be used as an alternative/user defined key. So it should be unique. We can have MetaWareJ enforce uniqueness by adding a unique=”contraintName” in the appropriate <input>
<input name="code" dbname="user_code" size="10" label="usercode" unique="userCode"/>
(see WEB-INF/xml/demo/manual/cust_update_unique.xml):
If a validation or other error occurs a message is displayed as shown in Screen 8: MetaWareJ Error Message. Messages are links. When the user clicks (or tabs in Android interface) on a message, the focus is set on the control that caused the error.
Screen 8: MetaWareJ Error Message

Searching
What happens if we have more than a few customers and displaying the entire table is not possible?
The new XML is listed below (see WEB-INF/xml/demo/manual/cust_search.xml) . The bold sections are new:
<form title="m_search_table" >
<table columns="2" name="s" format="FORM" function="SEARCH">
<controls>
<input name="code" size="10" label="usercode"/>
<input name="name" label="custname" size="25" maxLength="50" />
</controls>
<buttons>
<button type="FIND"/>
</buttons>
</table>
<table name="d" title="customer" function="DATA" format="GRID">
<recordset >
<selectString orderBy="user_code">
select id,user_code,name from customer
</selectString>
<argument parameter="name" where="name" />
<argument parameter="code" where="user_code"/>
</recordset>
....
Here we define a new table which has function=”SEARCH”. Only this table will be displayed the first time we call this form, as shown in Screen 9: Search Table,
The arguments are added to the <recordset> element. They will be used automatically (i.e. added as clauses to the SQL statement) if the user has entered some criteria.
After hitting the Search button, the data is displayed as before. The “Search Criteria” table will be folded on top of the “Customer” table, see Screen 10: Folded Search Criteria. The user can unfold it by clicking on the image.
Screen 9: Search Table
Screen 10: Folded Search Criteria

Paging
What will happen if the user does not enter any criteria but just hits Search? As we said above, arguments are only added if the user enters some criteria, so in this case the entire table will be again retrieved. We can make one or both arguments mandatory, but that is for later.
We can limit the number of rows to be displayed by adding rowsPerPage to the recordset element as show (see WEB-INF/xml/demo/manual/cust_paging.xml) :
<table name="d" title="customer" function="DATA" format="GRID">
<recordset rowsPerPage="2">
<selectString orderBy="user_code">
Screen 11: Table with Paging Controls
This simple addition will create the Previous, Page, and Next buttons. It will also add a limit clause to the select SQL statement and handle all the logic needed to do paging. The limit clause will be appropriate for the database we use, different for MySQL, Oracle, etc. Of course the rest of the functionality works as before.
As before, the new buttons are added to the action bar of Android, see Screen 12: Android Screen With Next Control . The “Page” control, where a user can enter and skip to a page number directly, is not added in the Android client. We are trying to keep the interface simple for the small screens.

Screen 12: Android Screen With Next Control
Master/Detail
Now, lets looks at the PROJECT table in which each customer has one or more projects. We would like to manage the customer projects in the same screen as customer in a master/detail configuration.
(see WEB-INF/xml/demo/manual/cust_master_detail.xml)
In order to do this, we add a second table in out XML definition, called “p” in the <table name=”p”> tag. The new section here is the <filter>. In it, we define that the new table will be a child of the “d” table (master=”d”) and the “id” control of the master table is linked to the “customerid” control of this table (<match master="id" detail="customerid"/>).
The child table does not have any arguments in the <recordset> . It will automatically retrieve only the projects belonging to the customers retrieved in the parent table.
<table name="p" title="projects" function="DATA" format="GRID" >
<filter master="d">
<match master="id" detail="customerid"/>
</filter>
<recordset orderBy="descr">
<selectString>
select id,user_code,customer_id, descr from project
</selectString>
</recordset>
<update table="project"/>
<controls>
<hidden name="id" type="INT" key="true" auto="true" protect="true"/>
<hidden name="customerid" dbname="customer_id" type="INT" protect="true"/>
<input name="code" dbname="user_code" size="10" label="usercode" />
<input name="descr" label="descr" size="25" maxLength="50" />
<delete/>
</controls>
<buttons>
<button type="ADD"/>
</buttons>
</table>
The result will be a second detail table for projects as show below:
Screen 13: Master - Detail Tables
First, note that in this example we have also changed rowsPerPage to 1 so that only a single customer is displayed. This is not necessary but it is more user friendly.
The projects displayed will be those belonging to the customer, as expected in a master/detail configuration. Any added projects will automatically belong to the shown customer as well. Next, Previous work as before. The screen updates two database tables in the same transaction.

Display Layout
Tables have two layouts, FORM and GRID, as we show in the following example (see WEB-INF/xml/demo/manual/cust_grid_form.xml)
<form title="m_grid_form" >
<table name="d" title="customer" function="DATA" format="GRID">
<recordset >
<selectString orderBy="user_code">
select id,user_code,name from customer
</selectString
</recordset>
<controls>
<input name="code" dbname="user_code" size="10" label="usercode"/>
<input name="name" label="custname" size="25" maxLength="50"/>
<delete/>
</controls>
</table>
<table name="e" columns="2" extends="d" format="FORM"/>
</form>
Screen 14: Layouts GRID and FORM
Here the table “d” has format=”GRID” while the table “e” has format=”FORM”. Additionally, the second table defines the number of columns to display ( columns="2" ) since each database record will occupy more than one row. See Screen 14: Layouts GRID and FORM . columns=”2” means one column for labels and one column for input fields, so don't forget the labels when defining the columns attribute.
The example code above introduces another concept. The table “e” has an attribute extends="d". This means that table “e” will inherit all attributes and sections from the table “d”. In fact the single line shown is the entire definition for table “e”. It only overrides the format and columns attribute of the base table “d”. More one this in Table Inheritance.
In a PDF report, the format is again used to layout the tables, as shown below for the same XML file.
Screen 15: PDF Report with GRID and FORM Tables

Tabs
When a web screen has multiple tables, they are shown one after the other. The tables can be folded so that they don't take up screen space, as we have seen.
<form title="m_master_detail_tabs" useTab="true" ...
...
<table name="p" tabName="k" title="projects" function="DATA" format="GRID"
...
Tables can also be displayed in a tab control as tab pages, by setting the <form useTab=”true” attribute in XML. See Screen 16: Tables Displayed in Tab.
(see WEB-INF/xml/demo/manual/cust_master_detail_tabs.xml)
Screen 16: Tables Displayed in Tab
Each table is placed on its own tab by default. We can put more than one table on the same tab page by explicitly naming our tab pages and using the same name for the tables we want to share a tab page. This is done by adding the tabName="k"attribute to the table definition. tabName attribute is not needed if the tables will be on separate tab pages. The special tab name “_top” will force a table to appear above the tab control.

Controls and Buttons
In all previous examples we have been using various controls such as <input> and <hidden> . MetaWareJ implements all the usual (and some not so usual) controls found in applications. As we have seen, controls are defined in the <controls> section of the XML definition for each <table>.
Each control has a set of attributes which define its appearance and behavior. Most common attributes are:
name	Should be unique within a table. Used to access the submitted data. [Caveat] A control's name must not contain the underscore character “_”.
dbname	Corresponding database column name (or alias or expression) from the SQL select statement.
label	Label holds a key to a dictionary from where the localized label is read.
type	Data type: STRING, INT, DATE etc.
maxLength, minValue, validationMask, minDigits,default, selectString, readonly, etc	Attributes that define the input domain and validations.
size, columnspan, style, labelStyle, displayMask	Attributes that define the visual appearance
events	JavaScript code to run when various events are triggered, e. g. onchange
Full reference of controls and their attributes can be found in the Form.html reference available through any MetaWareJ application under
http://<application URL>/Form.html

Controls
The available controls are listed below:
Control	XML element	Description
input	<input>	Basic input control. The type attribute can be set to DATE, DATETIME, INT, DECIMAL, STRING, NLSSTRING in order to define the data type. It can be read only.
hidden	<hidden>	Non visual control with value.
bufferOnly	<bufferOnly>	Non visual control, the value of which is not sent to the client. It can be used to access data to handle in the program.
password	<password>	Hides user input. Write-only control, i. e. it is never read from the database. <password> control always has MESSAGEDIGEST type.
text	<text>	Display-only control without a value, i.e it does not submit a value nor can it be used in JavaScript code. This is the difference between a read-only input control and a text control.
image	<image>	Displays an image.
File upload	<filelookup>	A file upload control. The file can be read using: InputStream inputStream= clientData.getUploadedFile(controlName);
checkbox	<checkbox>	Boolean control. The data type should always be BOOLEAN. MetaWareJ uses an integer database type as Boolean setting 1 for true and null for false. A developer should use type=BOOLEAN for all controls with boolean values and Convert.toBoolean() Convert.toString(boolean) to handle the data.
delete	<delete>	Marks a row to-be-deleted. The row will be deleted when the update button is pressed.
textarea	<textarea>	Multi-line edit control. It can be expanded and shrinked on focus, as shown in the example.
link	<link>
drop down lists	<select> <selectlist>	<select> is a drop down list that reads its data from a table. <selectlist> is a drop down list with fixed options in the XML definition.
radio	<radio>	Shows options in a radio button format.
Grabber	<grabber>	This control allows the user to open another pop-up form and search/select (or even add) a record from another table to his current working form. It can be used also to search-as-you-type or as a drop down list. A report can also be associate with the control so that the user can lookup information quickly.
line	<line>	non-data related control. Forces the controls that follow to be on the next line (in form format)
space	<space>	leaves an empty space on the form

Buttons
Buttons are predefined in MetaWareJ to perform specific actions. The type attribute defines the action to perform. So by adding <button type=”UPDATE”/> in the XML definition you get the update action. If you need a action that it is not predefined, you can add a custom action with some programming, see section FIXME.
Buttons may appear as icons in a toolbar or as traditional buttons, see Button Style.
Buttons can be used from the keyboeard using shortcuts. A button with attribute submitOnEnter=”true” will be the default and will be triggered with the Enter key. Commonly used buttons have shortcuts as listed below, for example Alt-u triggers Update. You can use the shortcut attribute to define shortcuts for other buttons.
The available buttons are listed here.
type=	Image	Shortcut	Description
FIND		Alt+s	Normal search.
UPDATE		Alt+u	Normal update
ADD		Alt+keypad-plus	Client side add. Uses JavaScript to add new row.
ADDSERVER		Alt+keypad-plus	Server side add.
ADDFRAME			Server side add on different frame
ADDROWS		Alt+keypad-plus	Adds rows to an existing screen table by asynchronously quering the server
REFRESH			Re-retrieves current page
REPORT			FIND but the tables become REPORT tables
RESET			RESETs form to original values
IMPORT			Imports a '|' (pipe) separated text file.
EXPORT			Exports data to a '|' (pipe) separated text file.
POPADD			Add multiple rows based on selection from search window. See description above.
SELECT			On search window: select and close window
SELECTMULTI			On search window: selects and adds multiple rows.
SELECTCLOSE			on search window: close without selection
<button type="OTHER" name="PRINT" label="PRINT">			Print button. Needs JavaScript in the event onclick.
COPY			Copies the displayed records. Records are first copied in memory, foreign keys are completed, unique keys are given default unique values, the records are updated in the database and then displayed.
COPYREFRESH			Copy Refresh, copies the displayed data as in “copy” but re-retrieves the data from database so that all display rules are re-applied.
NEXT, PREV, GOTO		Alt-n (Next) Alt-p (Previous)	Added automatically when paging is enabled.
PDF, CSV, XML, PRINT			Buttons added automatically. Export data in various formats
OTHER	programmer defined		Creates a new action. Needs JavaScript in the event onclick

Data Validations and Constrains
We have seen how we can use the attribute unique=”contraintName” on a control to enforce a uniqueness constraint. MetaWareJ automates many common validations and constraints. We will introduce them by moving to a new example. Here we have a screen to edit an “invoice”. It has a header record with some invoice general information and a set of detail records with the invoice particulars.
Screen 17: An "invoice" editing screen
The first table definition is listed below
(see WEB-INF/xml/demo/manual/inv_validations.xml)
<table name="d" title="invoice" function="DATA" format="GRID">
<recordset rowsPerPage="1">
<selectString>
select id, customer_id, invoice_number,
date_issued, paid, approved, date_approved
from invoice
</selectString>
<argument ... />
</recordset>
<update table="invoice"/>
<controls>
<hidden name="id" type="INT" key="true" auto="true" protect="true"/>
<grabber name="customerid" dbname="customer_id" label="customer"
size="35" type="INT"
showList="ONCHANGE" hasPopup="true"
URL="demo/manual/cust_search_grabber.xml">
<dataTransfer codeSource="id" labelSource="name"/>
<search idArgument="id" searchArgument="name"/>
</grabber>
<input name="invoicenumber" dbname="invoice_number" label="invoice_number"
mandatory="true" validationMask="^A(\\d{5})$" unique="invoicenumber"/>
<input name="dateissued" dbname="date_issued" label="date_issued"
readonly="true" type="DATE" minValue="2000-01-01" default="_TODAY"/>
<checkbox name="paid" label="paid" type="BOOLEAN"/>
<delete/>
</controls>
<buttons>
<button type="UPDATE"/>
</buttons>
</table>

Data Types
Lets start with data types. The attribute type=”” declares the data type of the data. MetaWareJ checks that all inputs correspond to the declared data type. This is especially important for the web client which (1) cannot be trusted to return the right data (2) all data are returned as strings. The data types can be one of STRING, DATE, DATETIME, INT, DECIMAL, BOOLEAN. For completeness, type can also be CODEINT, MESSAGEDIGEST, TRISTATE, EMAIL, and NLSSTRING.
The default data type is STRING. NLSSTRING is a string type that it is translated through the dictionary.
DATE is a real date (without time). The input control for DATE accepts a single digit to mean a day of this month (e. g. entering 13 means 13/4/2012 assuming we are in April of 2012), 3-4 digits to mean a day of month in the current year. In any case, the “/” separator is not needed. If you work with US locale, a single digit still means the day, but the formatted date will be mm/dd/yyyy. To enter month and day however, enter the month first.
DATETIME works more or less like DATE, except that it includes the hour as well in hh:mm format.
BOOLEAN is used mainly with check boxes and it needs an integer type in the database.
INT is a 32 bit integer number. CODEINT is a 32 bit integer number that it is not formatted.
DECIMAL defaults to a 2 decimal point double number.
MESSAGEDIGEST is a string that is converted to message digest using the algorithm in MessageDigestAlgorithm global parameter.
EMAIL is a string that it is validated to be an e-mail address.
TRISTATE is used with arguments, see section.

Mandatory
The mandatory="true" will ensure that the field will not be empty. MetaWareJ normally sends a null value to the database when the input is empty (empty string or null).

Readonly and Protect
The readonly="true" will make the field read only, which means that the user cannot change it throught the normal user interface. The field value can still be changed using JavaScript for example.
If you want to guarranty that the field value will not change, then set protect=”true”. MetaWareJ uses message authentication code (HMAC) to verfiy the data integrity and will not accept protected data that has changed. In the example above, we set the primary key “id” control as protect=”true”.

Minimum and maximum values
The attributes minValue and maxValue can be used to define the limits for types INT, DECIMAL, and DATE. The values used must be the same type as the data type of the control, of course. For example, see minValue="2000-01-01” in the example above.

Length and size
maxLength defines the maximum string length to be accepted. STRING type does not have a default maximum so setting the maximum always is recommended. size is the displyed size of the control.

Validation and Display masks
Two attributes can be used to define masks for the inputs, the validationMask and the displayMask. They work together to validate and then format the data. They are used on the server for validation before update as well as on the clients (using JavaScript in the browser )
The validationMask should contain one or more regular expressions separated by | (pipe character). (see java.util.regex.Pattern and JavaScript RegExp for regular expression syntax.) Each pattern is applied to the value until one matches. If a displayMask exists it should contain an equal number of formatting patterns. The corresponding formatting pattern will be applied to format the value, e. g. if the third validation pattern matched then the third display pattern will be applied.
In the example above, validationMask="^A\\d{5}$" ensures that only inputs formatted as ANNNNN will be accepted.

Primary, Alternate Keys and Uniqueness
The key is defined with the key attribute. MetaWareJ will never update (i.e. change) the primary key of a table. A <table> can have mulitple contols with key attribute.
If the key is a sequence number, the auto="true" attribute should be used. MetaWareJ has two ways of handling such columns. If the global property (see global.properties) UseAutoIncreament is true, we assume that the column is auto-increment and the database will assign values to the column. If it is false, MetaWareJ will use its own method to assign sequential values to column. In both cases, the value is immediately available, so any detail tables will have their foreign key correctly updated.
The key is also marked a protect=”true” to guarranty data integrity.
We have already seen how by using unique="constraint" ensures that the value will be unique. This is used in the above example to ensure that the invoice number value is unique. <unique> attribute should be used on the primary key and any alternate key columns. MetaWareJ will not do this automatically.
<unique> enforces globally, i. e. database table wide, uniqueness. Both the displayed data and the data in the database are validated. The attribute <uniqueInSet> checks that a value is unique only within the set of records displayed. For example, a user can belong to the group “admin” only once (but an belong to more than one group) or conversely a user can have the “admin” attribute only once.

Check Constrains
The update section includes a check section for each update column that defines a foreign key pointing to the table being updated. For example, (see WEB-INF/xml/demo/manual/cust_update_check.xml)
<update table="customer">
<column parameter="id" name="id">
<check refTable="project" refColumn="customer_id" deleteConstraint="RESTRICT"/>
<check refTable="invoice" refColumn="customer_id" deleteConstraint="RESTRICT"/>
</column>
</update>
In the example, the table INVOICE is pointing to the table CUSTOMER using column CUSTOMER_ID. Since an SQL update will never update the key, we need not worry about the constraint failing on update. We need to deal only with deleting the parent table record. The attribute deleteConstraint="RESTRICT" ensures that MetaWareJ will validate that the constraint will not fail. If we had deleteConstraint="CASCATE", MetaWareJ will do nothing. It will assume that the database will cascade delete the child records.
In a well designed database, the validations above will of course be enforced by database constraints. We feel that it is better to validate them in the code, so that we can at least give the user better error messages than let the database transaction fail. Of course the database constraint should be in place in any case. If you feel that the performance penalty is too much for your application, do not use these validations.
Screen 18: Error messages when trying to delete a column with check

Template Controls
Let's take a look at the second table of the invoice example above, see Screen 17: An "invoice" editing screen (WEB-INF/xml/demo/manual/inv_validations.xml)
The two “amount” fields are defined in XML as:
<input name="amount" size="10" type="DECIMAL" minValue="0" maxValue="999999999"
label="amount" />
<input name="amounttax" size="10" type="DECIMAL" minValue="0" maxValue="999999999"
label="amount_tax" dbname="amount_tax" />
The two definitions have many attributes in common that we will have to repeat every time we need to use an amount. MetaWareJ offers an alternative to this.
We can define our common controls in a file called controls.xml and place that in the directory of the applications XML definitions, see Application Structure for details on the application directory structure.
The controls.xml file will be
<controls>
<input name="amount" label="amount" size="10" type="DECIMAL" minValue="0"
maxValue="999999999"/>
</controls>
The controls.xml file does not have a <form> or any <table> sections. It has a single <controls> section where we enter the usual control information.
The invoice editing screen's XML definition now becomes
(WEB-INF/xml/demo/manual/inv_templates.xml)
<template tname="amount"/>
<template tname="amount" name="amounttax" dbname="amount_tax" label="amount_tax"/>
Instead of <input> we now have a <template>. The first “amount” field has no additional attributes, so it will use the template from the controls.xml file as is. The second adds attributes for name, dbname and label. These will overwrite the attributes of the template control.
Template controls are very important in the development work-flow of MetaWareJ applications. Normally, in XML files you should have very few, if any, normal controls. Almost all your controls should be <template controls.
During the design of the application and the database schema, you should end up with a set of data domains. These will translate to control templates in MetaWareJ. For example you can have database domains for customer name, address, sex, date of birth, amount, percentage etc. Each of these will become a template in MetaWareJ. Then you will reuse these in each screen as needed.
MetaWareJ comes with an already defined global controls.xml file which you will find in the WEB-INF/xml file of every application. Some of the common domains are already created, such as sex, year, month, age, etc.
Applications can use multiple template control files, the global control file being one of them. As a matter of fact you can extend the template controls of the global file in your application specific control files.
Here is an example of XML hierarchy:
WEB-INF/xml/controls.xml
WEB-INF/xml/myApplication/controls.xml
WEB-INF/xml/myApplication/module1/controls.xml
WEB-INF/xml/myApplication/pdf/controls.xml
WEB-INF/xml/myApplication/customerDetails.xml
WEB-INF/xml/myApplication/module1/customerDetails.xml
A <template control in file myApplication/customerDetails.xml will use the definitions in the controls.xml starting from the directory it lives until the global controls.xml, in this example the files myApplication/controls.xml and the global controls.xml. The same file under module1 directory will use the definitions from three controls.xml files.
Each controls.xml file overwrites and extends the definition of the lower level, so module1/controls.xml overwrites and extends any controls with the same name= in the myApplication/controls.xml and the global controls.xml.
For additional flexibility, there also exists a per output controls.xml file. In the example above, the file pdf/controls.xml will be used only when we are creating a PDF output for file myApplication/customerDetails.xml.

Table Inheritance
In the previous section we saw how to reuse controls. MetaWareJ allows us to reuse table definitions as well.
See the following example (from WEB-INF/xml/demo/manual/inv_inherited.xml)
<table extends="s" extendsFile="demo/manual/inv_templates.xml"/>
<table extends="d" extendsFile="demo/manual/inv_templates.xml" >
<recordset rowsPerPage="5">
<argument parameter="_[0]" where="approved"/> <!-- new argument -->
</recordset>
<controls>
<input name="dateapproved" dbname="date_approved" label="date_approved"
mandatory="true" type="DATE" minValue="2000-01-01"/>
<checkbox name="approved" label="approved" type="BOOLEAN"/>
</controls>
</table>
Here we have two tables. The first table is defined by a single line which points to file demo/manual/inv_templates.xml and to the table “s” (extends="s") within that file. This means that this table will inherit all attributes and sections from the table “s” of that XML file.
The second table also inherits from the same file, the table “d” this time. This table overwrites the <recordset> of the base table. We can see that we wanted to add an additional argument.
Controls are added to the existing controls of the base table. If the base table already has a control with the same name, the control is extended in the same way that we extend template controls.
Take a look at the reference manual for a full description on how each section is handled.

Form Inheritance
In addition to <table inheritance, you can also use <form inheritance. <form inheritance allows us to overwrite attributes of the base <form but it is also a shortcut for inheriting all the tables from one form to other.
For example, the form below will have all the tables of the myApplication/baseForm.xml but it will use tabs and the search table will be outside the tabs. <table name="s" extends="s" means that we are extending the table from the base form.

<form extendsFile="myApplication/baseForm.xml" title="formWithoutHeader" useTab="true">
<table name="s" extends="s" tabName="_top"/>
</form>
Output specific XML files
Sometime it is useful to have a somewhat modified screen for some output. For example, we might want to make some field smaller for PDF output. MetaWareJ opens an output specific XML file if it exists. So when asked to open file myApp/myFile.xml for PDF output, it will first look for myApp/pdf/myFile.xml and if this does not exist it will open myApp/myFile.xml.
Since most of the time the output specific and the base forms are almost the same, form inheritance is very useful in this case. For example, here is how you would change the size of a single control for PDF out from the baseForm.xml, the file saved under myApplication/pdf/baseForm.xml
<form extendsFile="myApplication/baseForm.xml" ...>
<table name="d" extends="d" >
<controls>
<input name=”someControl” size=”10”/>
</controls>
</form>
A better way to do these type of change would be use controls.xml specific output files with <template controls in the base form, as shown in Template Controls. For the same example the base form myApplication/baseForm.xml will be:
<form ... >
<table name="d" ... >
<controls>
<template tname=”someControl”/>
</controls>
</form>
The file myApplication/controls.xml will contain the base definition of the control and the file myApplication/pdf/controls.xml will contain the changed size control as in:
<controls>
<input name=”someControl” size=”10”/>
</controls>
When form form myApplication/baseForm.xml is opened for pdf output, it will use the controls.xml definition in myApplication/pdf/controls.xml.
Using the controls.xml is better because the changes will affect all the XML forms that use the template control, when they are used for PDF output.

Abstract tables
Inheritance is related to the concept of ABSTRACT tables. A <table> is abstract when it has function="ABSTRACT". Abstract tables parallel abstract classes in Java, that is, it it an incomplete definition of a <table> and it exists only to be extended. It follows that abstract tables do not appear in any form, nor are used directly to retrieve data. As a matter of fact, at runtime, after they are used as the base for the tables that extent them, abstract tables are removed from the form definitions.

Calculated Fields
In the invoice example Screen 17: An "invoice" editing screen, we have a column “amount” for which we should provide a total. The total must be calculated when the user changes any amount field. The total can be added by adding a trailer="SUM" attribute to any numeric control as you can see the listing of the XML below.
(WEB-INF/xml/demo/manual/inv_calc_fields.xml)
<table name="i" title="invoicedetails" function="DATA" format="GRID">
<expression>
<exp control="amounttax"
script="fn_num( n( Dgi.gv('amount',idx) ) * 0.15 )"/>
</expression>
<filter master="d"><match master="id" detail="invid" /></filter>
<recordset> ... </recordset>
<update table="invoice_detail"/>
<controls>
<input name="amount" label="amount" size="10" type="DECIMAL"
minValue="0" maxValue="999999999" trailer="SUM"/>
<input name="amounttax" dbname=" " label="amount_tax" size="10" type="DECIMAL"
readonly="true" minValue="0" maxValue="999999999" trailer="SUM"/>
<delete/>
</controls>
<buttons> ... </buttons>
</table>
We also want the tax to be calculated automatically given a fixed 15% rate. This is more complicated. First we change the “amounttax” control to be readonly. We also set the dbname attribute to space, which means we will not read it from the database. Note that setting the dbname as empty string will not work, because the default for dbname is the control name.
Then we need to add an expression as shown above. Expressions are pieces of JavaScript code that are executed whenever the user modifies any value on the form. A table can have multiple expressions. The expression attribute control identifies the control to be modified. The script is a JavaScript expression that will provide the new value.
In the above example we have control=”amounttax”. This means that the expression will modify the value of “amounttax” control on each row of the table.
The expression itself is more complicated. You can find all the details of using JavaScript with MetaWareJ in JavaScript Support. For now we will explain that: the outer most call is to a function fn_num() which formats a number. The rest is a multiplication between the number “0.15” and the value of the “amount” control. The function n() converts a string to a number. The DGi object accesses the “i” table. The gv(name,idx) method gives us the value of the control at row number idx. idx refers to the row number and it is provided by MetaWareJ to be used in our scripts. The result is a Tax column as shown in Screen 19: Calculated fields.
Screen 19: Calculated fields
Calculated fields can work with PDF output depending on the expression used. The above example produces the output: FIXME
Screen 20: Calculated fields in PDF

Arguments
We have been using arguments all through this tutorial. Arguments add where clauses to the select statement when the value specified by the argument exists.
Let's look at the arguments of the previous example (inv_validations.xml) in more detail:
<argument parameter="finvdate" where="date_issued" comparator="&gt;" type="DATE"/>
<argument parameter="tinvdate" where="date_issued" comparator="&lt;" type="DATE"/>
<argument parameter="invnumber" where="invoice_number"/>
<argument parameter="_[0]" where="approved"/>
An argument has at least a parameter which defines where to get the argument's value, and a where which defines how to use the value. A third attribute, table, defines the table of the parameter attribute. It defaults to “s” which is what we call our search table.
So in the example above, the first argument's value will come from table “s”, control “finvdate” and row=0. If the value exists, i. e. the user enters a value, the where part will be added to the select statement. The clause produced is “date_issued = ?”.
The <argument> has a comparator attribute that can be used instead of equality. So the clause in the example will actually be “date_issued > ?”. The default comparator for string arguments is a “starts-with”, so the third argument in the example will create a clause “invoice_number like ?” and the value will be “VALUE%”
Arguments can have fixed or default values. Fixed arguments are always added in the select statment and are defined in the parameter attribute.
In the example we also have this argument:
<argument parameter="_[0]" where="approved"/>
Here the parameter name is given as “_[0]”. This means that the argument value will be the fixed value “0”. You can use whatever value from the list of default values, for example parameter=”_TODAY” will retrieve record related to today's date and parameter=”_USERID” will retrieve related to the login user.
Default argument value is entered in the attribute default, as in the example:
<argument parameter="inputDateControl" where="some_date" default=”_TODAY”/>
The deference between fixed arguments and default arguments is that the default argument value will be used only if the user does not provide a value, in the example if the inputDateControl is empty, while in the fixed argument the value will always be used.
Arguments can also be mantadory, by setting required=”true”. In this case table will not be retrieved, if the argument value is not provided.
Clauses added from multiple arguements are added using “and”. If you want to add clauses using “or” you can include them in an <or> element as in:
<argument parameter="param1" where="some_column" comparator=”e=”/>
<or>
<argument parameter="search1" where="user_code" comparator="any"/>
<argument parameter="search2" where="descr" comparator="any"/>
</or>
<or>
...
Assuming all values are provided, the clause will be “param1=? and (search1 like ? or search2 like ?)”.
Note that multiple <or> elements can be used.
The parameter attribute need not be unique. This can be usefull if we want to search in various database column for a user input. For example we can use
<or>
<argument parameter="search" where="user_code" comparator="any"/>
<argument parameter="search" where="descr" comparator="any"/>
</or>
to search the imput “search” in two database columns. This is actually vary common in <grabber> URL forms, see <grabber>.

Drop down, popup lists and interactive search
As we have seen above, MetaWareJ has various controls for drop-down lists and searching. We will take a closer look here.

<selectlist>
The simplest list control is a <selectlist>. It produces a standard drop-down list. The items listed are included directly in the XML definition of the screen, as shown here:
<selectlist name="sex" dbname="sex" label="sex" size="8" type="INT">
<option code="1" label="sexm"/>
<option code="2" label="sexf"/>
</selectlist>
Note that the option labels are looked-up in the dictionary and labels appear in the user's selected language, as seen in Screen 21: <selectlist>.
Screen 21: <selectlist>

<select>
Another control that produces a standard drop-down list is the <select>. Below is a select that displays a list of users:
<select name="user" dbname="ref_user_id" type="INT" label="user" size="30"
codeColumn="id" labelColumn="name_e">
<selectString>
select id, name_e from ref_user order by name_e
</selectString>
</select>
For <select> the listed options are read directly from the database. We need to provide an SQL select statement (selectString) and define the code (codeColumn) and label (labelColumn) columns. The labels are read form the database and shown as-is, i. e. no look-up is performed in the dictionary by default. See section Language on how to change the default behaviour.

Filtered <select> controls
A <select> control can be filtered by another control, by adding the master=”” attribute. In the example below, we add a drop-down which lists, the departments. We want to show only the users of the selected department. So we add master=”department” and a where-clause to the select statement.
<select name="department" type="INT" label="name" size="30"
codeColumn="id" labelColumn="name">
<selectString>
select id, name from department order by name
</selectString>
</select>
<select name="user" type="INT" label="user" size="30" master=”department”
codeColumn="id" labelColumn="name_e">
<selectString>
select id, name_e from ref_user
where department_id=?
</selectString>
</select>
A few things to keep in mind.
This works only for controls on the same table and row.
The master control does not need to be a <select>, it can be any control including <hidden>. This can be used, for example, you to make a control show different lists on each row of a table.
A master control can filter multiple children, e. g. the “department” control can filter a “users” controls and a “projects” control.
You can create a chain (actually a tree) of select controls each filtering its children.
Only one bind value is allowed in the select statement of the child.
Children lists are loaded asynchronously on the change event of the master.

<grabber>
Database tables connect to other tables using foreight keys, for example out INVOICE table has a foreigh key to the CUSTOMER table. There is always a need to provide the user with a simple interface to connect a child table record being edited with a parent record.
This control allows the user to open another pop-up form or an interactive list and connect a record from another table to the current working form. A <grabber> can populate multiple controls on its row and use multiple controls to search the connected table as well as do interactive search.
The full control is shown in Screen 22: Grabber Control. When the user types in the input box, grabber does on interactive search and shows a list of options Screen 23: Grabber with list open, whne the user clicks on the “open Popup” button the full form appears where the user can search,select , or even add a parent record Screen 24: Grabber with open popup form. Finally, grabber provides an additional button where we can show a report related to the select record, for example show the balance of customer to decide if we will give a discount.
Screen 22: Grabber Control
Screen 23: Grabber with list open
Screen 24: Grabber with open popup form
Screen 25: Grabber with history/report showing
Lets lookup at a grabber using an example based on the invoice form we have been using (see inv_grabber.xml.) We are editing an invoice and we want to select the customer/debtor of the invoice.
There are several parameters that we need to setup in XML to make a <grabber> work. First keep in mind that we are working with two XML files, the base screen which has the <grabber> control and the popup screen which allows the user to select.
The <grabber> control itself is listed below.
<grabber name="customerid" dbname="customer_id" label="customer" size="35" type="INT"
showList="ONCHANGE" hasPopup="true"
URL="demo/manual/cust_search_grabber.xml"
historyURL="demo/manual/cust_grabber_history.xml">
<dataTransfer codeSource="id" labelSource="name"/>
<search idArgument="id" searchArgument="name"/>
</grabber>
The grabber control, as the other lists, have two values, a code that it is what exist in the database and a label which is what the user sees.
The URL points to the XML file which is used by the <grabber> . The file is used to open the popup screen when the search icon is clicked and to show the list (interactive search) when the value of the <grabber> changes. It is also used to populate the grabber description when its form is first loaded.
Since the URL pop-up form is another screen, it can have update capabilities which means that it can be used to add the customer, if the customer entry is not already there.
The <dataTransfer> element describes how the connect the controls of the two forms. The codeSource attribute referes to a control of URL form from where the grabber will get its value. The labelSource attribute referes to a control of URL form from where the grabber will get its display label. The <dataTransfer> always refers to the controls of the first DATA table of the URL form. So if we look at cust_search_grabber.xml we will find the controls in table “d”
<hidden name="id" type="INT" key="true" auto="true" protect="true"/>
<input name="name" label="custname" size="25" maxLength="50" />
The <search> element is used to provide the URL form with argument values.
The idArgument attribute refers to the argument of the first DATA table fo the URL form which can be used to uniquely identify the selected record. So, if we have customer_id=5 in the database in our INVOICE table, it refers to CUSTOMER record with id=5. In this case the URL form ( cust_search_grabber.xml) needs to have an argument that will return the record with id=5. In the actual file:
<argument parameter="id" where="id" type="INT"/>
The idArgument attribute is only used when the grabber is first initialized in order to display the already selected value.
The searchArgument attribute refers to the argument that will be used to do interactive search. When the user types something the typed value is sent as searchArgument to server URL form and any records found are used to create the list. In our case, “name” should be an argument in the cust_search_grabber.xml form:
<argument parameter="name" where="name" />
It is common to want to search in mupliple fields in interactive search. For example, we might want the user to search with customer phone number, or email, etc. Inthis case we can use the <or> element of the arguments, as in
<or>
<argument parameter="search" where="phome_mobile" comparator="any"/>
<argument parameter="search" where="phome_home" comparator="any"/>
<argument parameter="search" where="email" comparator="any"/>
...
</or>
These are the minimum entries we need to make a grabber work.
The grabber can also return/fill-in additional controls in the base form. For example, we also want to have the customer's address on our screen after we selected the customer with the grabber control. We can add the following to the <dataTransfer> element:
<dataTransfer codeSource="id" labelSource="name">
<copy to="address" from=”address”/>
</dataTransfer>
The to is a control in the same <table> and row as the grabber. The from is a control on the URL form. When to and from are the same you can write only the to part. Multiple <copy> elements can be added.
The grabber can also use other controls to pass multiple search argument to the uRL form. Assume we have multiple departments in our orginization and, when issueing an invoice, we want to list only customers related to out department, We could add in <search> element:
<search idArgument="id" searchArgument="name">
<argument source="department" argument="department"/>
</search
The source is a control on the same <table> and row as the grabber. The argument is the argument of the URL table. Multiple <argument> can be added.
The historyURL points to another XML form which can show some more details related to the selected value, or even a full report etc. The value of the grabber is passed as single argumnet which is always called id, so the XML should have and id argument. In the example, the cust_grabber_history.xml file has:
<argument parameter="id" where="id" type="INT"/>
A few more details.
You can disable the popup button by setting hasPopup to false.
The interactive list is controls from attribute showList and can work either when the user types something (ONCHANGE), when the control gets focus even if empty (ALWAYS) or never (NO)
The history button is not displayed if you don't provide a historyURL.
The attribute historyTarget lets you open the report in frame, as in the example, or a separate window.
arguments in the URL form do need to appear in the forms search table. The form might not have a search form at all. Only the arguments in the first data table are needed.
The URL form is configured by MetaWareJ with selection check box and extra buttons.

suspended
In the life of the system, we usually find records that are no longer valid or should not be used any more for whatever reason. These records cannot be deleted since we have already used them, but we want to control the future use. We call these suspended records.
<grabber> and <select> controls handle suspended records, if the retrieve records have a field called suspended. In case of grabber, the suspended field has to be a control in the URL form. In case of select, it has to be a column if the selectString SQL.
When a field exists the attributes suspendedShow and suspendedCheck (ALLOW, WARN, ERROR) control the behaviour.
suspendedShow can be YES which means show as normal entries, NO don't show suspended entries, or GREY show the suspended entries a disabled:
Screen 26: GREY suspended entries
suspendedCheck controls if the value will be accepted for modified records and takes the values ALLOW, WARN, or ERROR.

isDefault record and initial value
When adding a new record, <grabber> and <select> controls choose the default record using the isDefault field. In case of grabber, the isDefault field has to be a control in the URL form. In case of select, it has to be a column if the selectString SQL. In case of <select> the field can be called is_default as well. If this fields is true (meaning integer equal to 1 ) then that value will be used. Additionaly <grabber> will use that record to initialize and other controls using the <copy> elements.
isDefault should also be used as an argument in the graber URL form, as shown below, so that we can find the default faster. However, this is not needed and as long as the isDefault control exists, MetaWareJ will fin dthe default record.
<argument parameter="isDefault" where="default_culumn" type="TRISTATE"/>
The isDefault initialization works in parallel with the normal default attribute. It has the advantage that it can be defined dynamically while the default attribute is fixed.
Both controls will also initialize if their list contains only one item.

<button type="POPADD">
The button type POPADD allows us to add multiple rows in a table from a popup screen. It works very much like the grabber described above, so we will not go into details here.
POPADD button is simplier than <grabber> because it does not have values or interactive search list. So the attributes codeSource and labelSource don't exist and atleast one <copy> is needed. You should actually use enough <copy> elements as to initialize the new rows correctly.
<search> element is also not needed. It can be used, if you want to pass arguments to the URL form. In the POPADD case arguments are read from its form's SEARCH table, while grabber arguments are read from the same table and row as the garbber. This is actually obvious, if we remember that the button does not have a row and its table might be empty.
The URL form of the POPADD button is configured to allow selection of multiple rows, as shown in Screen 27: POPADD Button with the popup window
<button type="POPADD" URL="demo/manual/cust_search_grabber.xml">
<dataTransfer>
<copy to="level" from="uLevel"/>
<copy to="descr"/>
</dataTransfer>
</button>
Screen 27: POPADD Button with the popup window

Adding Rows and default values
There are four buttons that add rows. Rows are always added on the client screen and an additonal update is needed to insert them in the database. The POPADD button above is one of the four, the other three are described here.
If you need to programmably add new rows, see section Adding rows.

default values
When a row in added the controls are initialized using the default attribute, if it set, otherwise remain empty. The default attribute must hold a value the matches the data type of the controls, such as “true” for BOOLEAN or -1 for INT. DATE and DATETIME defaults must be in format YYYY-MM-DD and HH:MM. DECIMAL must have a period separator (not comma).
MetaWareJ offers a set of keywords that can be as default values. Everything that starts with '_' (underscore) is considered special. You can find the keywords in the reference, for example _USERID, is the id of the logged-in user, _TODAY is today's date, etc. Additionally, _(table,control,row) can be used to initilaize from another control, _{keyword} from a global property. _[list,of,items] will set the contolr on the first row to “list”, on the second row to “of”, etc.
As we have seen in section <grabber> , the grabber control can initialize onther controls on the same row. This is also done when adding new rows, if the controls have not been initialized yet.

ADD button
The first, <button type=”ADD”, as we have already seen, adds a row iin the client, using JavaScript, and marks the row as NEW. Multiple rows can be added this way, before the form is submitted. If the use modifies the row, the status becomes NEWMODIFIED and, when the form is submitted, the row is inserted in the database. Rows having status NEW are not inserted. You can change the initial status of new rows by setting the newRecordStatus attribute of the <table> to “NEWMODIFIED” or even “MODIFIED” and “NOTMODIFIED”.

ADDSERVER button
The second button has type=”ADDSERVER”, and adds rows by submitting the form to the server with action ADD. The server rebuilds the form, adding one or more rows in one or more tables. The number of rows added (default 1) is controled by the <table> attribute defaultRecords. The default attribute of each control is also used to initialize the control as above.
The ADDSERVER button can also use a select SQL to add rows. If the <table> has a <recordSetNew> element then it will be used to retrieve data and add one row for each record retrieved. IN this case the table's defaultRecords attribute is not used.
A <recordSetNew> element looks and behaves like the <recordSet> element that we have already seen, with the exeption that it is used only to add rows.
After adding a row, if a control is still empty but has a default attribute value, then it will be used to initialize it.

ADDROWS button
The button with type=”ADDROWS” submits an ADDROWS action to the server but does so asynchronously. It creates new rows as in the ADDSERVER but only for the table of the button or the table given in the buttons targetTable attribute. so
<button type="ADDROWS" targetTable="d2"/>
will add rows in table “d2”.
ADDSERVER creates JSON output that it is used to add the rows directly in the existng client screen, in addition to any existing rows.

Frames
A <table function="FRAME"> creates a separate screen within the screen of the <form>. In HTML, this is done using an iframe tag. A frame can be used as the target of a link in the parent screen. This is done using a <link> control with a target= attribute to the frame. An example:
<table name=”a” function=”DATA” ...
<controls>
...
<link name=”link1” target=”d” baseURL="?f=other_form.xml&...” />
</controls>
</table>
<table name=”d” function=”FRAME”/>
When link1 is clicked it will load other_form.xml into the frame named “d”. Moreover, when the screen is loaded, it will include JavaScript code to load the frame from the baseURL of the first link1 on the page. In other words, if table “a” has data when it is loaded, the frame “d” will load the first link1 automatically.
If a frame is not linked to a link control, then its attribute sourceURL= will be used to load it. sourceURL= should not be used on a <table function="FRAME"> that it is linked to a link control, because it will cause it to be loaded twice.

Header files
If you want to add some header information to your application you can create a header XML file and add the name in global.properties under the HeaderFile key. (Or you can just call it header.xml and place it in the same directory as your XML files.) This will be added on top of every XML file processed.
A header file can have some general information regarding the application, logged in user, version etc. MetaWareJ curries some of this information in session parameters which can be added as default values. See the example below which creates the header in Screen 28: Header table added to a screen.
<table name="header" title="" function="HEADER" format="FORM"
columnHeaders="false" style="hd" expandable="false"
columns="6" defaultRecords="1"
serverReaderClass="cy.com.methodosit.common.Meta.DefaultDataReader"
buffered="false">
<controls>
<image name="l1" default="images/logo_small.png" rowSpan="2"/>
<text name="cid" dbname=" " default="_APPLICATION" style="large"
columnSpan="2" type="NLSSTRING"/>
<space/>
<text name="uid" dbname=" " default="_USERNAME" style="headername"/>
<template tname="copyright" name="c" default="_COPYRIGHT"
size="25" style="copyright"/>
</controls>
</table>
Screen 28: Header table added to a screen

Localization

Language
All labels, titles, menu items, messages, etc. are keys which are looked-up in the dictionary and shown in the user's language. The default language is defined in the global.properties file parameter Lang. It should be set to an ISO language code, e. g. en for English and el for Greek. The language can be changed for each user (for any request actually) using the “lang” parameter which can be added to the initial URL (or any URL). The language is saved in the user session after that.
The dictionary consists of a hierarchy of three property files:
A <form> level property file which can be defined using the dictionaryFile attribute.
An application property file defined in global.properties under key Dictionary.
The MetaWareJ property file called dictionary.properties.
The key is looked-up in this order and if not found in any of them, the key itself is displayed.
MetaWareJ does not handle translated data. For example, if you need your customers' names in more than one language you should handle it yourself as part of your overall design.
MetaWareJ does provide ways to store localized keys in the database.
If you define, in XML, a control with data type NLSSTRING, instead of STRING, MetaWareJ will look-up the returned value in the dictionary. You could store the key in the database and enter the displayed values in one of the dictionary property files.
<text dbname="company_name" type="NLSSTRING" />
For drop down lists, the control <selectlist> looks-up the labels in the dictionary as we have seen.
The control <select> does not look-up labels in the dictionary by default. If you want the labels to be localized, you can change the selectModel used by a <select> control. The selectModel defines the class that fetches the data. The default is ReferenceTable. If you set
selectModelClass=”cy.com.methodosit.common.jdbc.DictionaryReferenceTable”
in the XML definition of the select control, then the labels will be looked-up in dictionary as well.

Localized data
Dates and numbers are presented to the user using the European conversions by default, that is day/month/year for dates and comma (,) for decimal separator.
As with the language above, the locale is defined globally in global.properties parameter Locale. It can be changed by the user by appending a locale= parameter to any URL.
If the locale is defined as en_US, the US conversions are used instead, month/day/year for dates and period (.) for decimal separator.

Importing and Exporting Data
The button of type EXPORT can be added to any <table> to export the data in a '|' (pipe) separated text file. When exporting, the data is retrieved using the entered searched criteria. If multiple <table> exist in the form, all will be exported with detail records following each parent record, along with column names.
The buttons of type IMPORT can be added to any <table> to import data from a '|' (pipe) separated text file. Only one <table> is imported.
The file must have the name of the controls to be imported in the first line, separated with '|' (pipe) as well. This means that we can import from a file that contains only some of the controls. All validations, default values, business logic for the imported <form> and <table> will be applied.
For example, to import into the table “customer” of the following form
<table name="customer" title="customer" function="DATA" format="GRID" >
<update table=”customer”/>
<controls>
<hidden name="id" type="INT" auto=”true” key=”true”/>
<input name="code" dbname="user_code" ... />
<input name="name" ... />
<input name="address" ... />
<delete/>
</controls>
<buttons>
<button type="UPDATE"/>
<button type="IMPORT"/>
We can use the following file
code|name|address
CUST1|Customer 1|Some address without new lines
CUST2||
Note that the second customer, CUST2, has empty name and address.

Programming with MetaWareJ

Adding Business Logic
In a previous example, we have two controls:
<input name="dateapproved" dbname="date_approved" label="date_approved" mandatory="true"
type="DATE" minValue="2000-01-01"/>
<checkbox name="approved" label="approved" type="BOOLEAN"/>
The first control has the attribute mandatory set to true. This means that we will not accept an empty “dateapproved” value. Assume that we want to check that the value exists only if the “approved” checkbox is checked. In order to enforce rules like this we need to add code to the application.
You should notice that, so far, we have created a screen that handles searching, displaying, and updating multiple database tables, does all the needed validations, does paging, and handles master/detail without adding a single line of code.
When we need additional business logic, which should be almost always, we need to write our own code and link it to the screens we have created. We will continue with the example above:
public class InvoiceDataWriter extends ServerDataWriter{
@Override
public void beforeUpdate() throws BackEndException{
Message messages=context.getMessages();
DataReader dataReader=new ClientDataReader(context, “d”);
while(dataReader.next()){
if(dataReader.getBoolean("approved")){
if(dataReader.isEmpty("dateapproved")){
messages.addMessage(
"MISSING",
"d",
"dateapproved",
dataReader.getRow(),
Message.Level.ERROR);
}
}
}
This is a listing of a new class we need to create. There are a lot of new concepts we need to explain here:
The class extends a ServerDataWriter MetaWareJ class which is the class that validates and saves the data.
It overrides the beforeUpdate() method, which is the method we need to write in order to do our own validations.
It uses a MetaWareJContext class, the context variable, which gives us access to the various objects used by our application such as the buffer where the data is stored.
It uses the MForm and MTable classes which give us access to the XML definition.
It uses a Message object which is how we communicate with the user.
It uses a ClientDataReader utility class to assess the data.
Before we see the example in more detail, let's connect the above code to screen.
<form title="m_server_writer"
serverWriterClass="cy.com.methodosit.demo.InvoiceDataWriter">
At the top level of the XML definition, in the <form tag, we add the full name of the new class. This means that there can be only one such class per XML file, which also means that all the data is saved in a single transaction.
Since we will handle the mandatory rule ourselves, we should also remove the mandatory=”true” from the control definition.
What will happen is as follows. MetaWareJ will instantiate our class when it needs to save the data, i.e. when the user hits the “Update” button. It will do all the default validations already defined in XML. If no problems are found, it will call our beforeUpdate() method. If still no problems are found, it will get a database connection and start a new transaction.
In the beforeUpdate() method, we access the object that represents out table, MTable, and we create a ClientDataReader to loop through the data of the ClientData buffer, which does not appear in our code directly. DataReader allows us to get the data in the type we need, using the names of the controls as defined in the XML file. So dataReader.getBoolean(“approved”) will return true if the checkbox was checked.
If the validation fails, we add a message to the Message object. When the beforeUpdate() returns, MetaWareJ checks the Message object. If we have messages of level ERROR, the processing stops and the messages are shown to the user. If not, the update continues normally. Note that we can add multiple messages, so we don't have to stop the validation on the first error. The messages will be links as we have seen above, since we added information about the control in the addMessage() method.
The method throws BackEndException which should be used only to re-throw database (or other) exceptions. You should add normal messages for other validation errors as shown in the example.
ServerDataWriter has three more methods that can be overridden to add custom code.
The startTransaction() method executes right after the beforeUpdate() method but executes after the database transaction has begun. You should use this method to do validations, updates, or lock resources that need to be done as part of the transaction. This method has access to the JDBC connection to the database in a member protected Connection con. The connection is already established when startTransaction() is called. Do NOT open, close, commit or rollback. As with beforeUpdate(), if you add a message of level ERROR to the Message object, the transaction will stop and be rolled back. If you return without errors, MetaWareJ will proceed to update the database as defined in the update sections of the XML definitions as we have already seen.
The second method is the endTransaction(). Here we are still in the transaction and we still have access to the same Connection object con. You can override this method to do any updates that need to be done after the screen data have been saved.
The final method called is the afterUpdate(). This is called after the transaction has committed, and only if the transaction committed successfully. The data still maintains its status, so we can check if a record is new for example. (See Data Organization for more on statuses.) The method does not have access to the Connection object. If we need to touch the database we must call ConnectionPool.get() and ConnectionPool.put(con) to get and return a connection, as well as commit/rollback to end the transaction.
Let's repeat that you don't need to update the data displayed on the screen. MetaWareJ handles that automatically.

MetaWareJContext and fundamental classes
MetaWareJContext class provides access to the core objects used by the application.
MetaWareJ at its most basic level does the following (context refers to MetaWareJContext):
Step	Related Classes	How to access them
establishes a user session	SessionData	context.getClientData().getSessionData()
accesses an XML form description.	Meta package. MForm, MTable, etc	Override from XML. context.getMForm() form.getTableByName()
reads data from the database	ServerDataReader	Override from XML. (rarely context.initServerDataReader())
translates labels and data to the appropriate language.	Dictionary	context.getDictionary()
formats data for the appropriate locale.	Convert	context.getConverter()
displays the data in the requested format (HTML, PDF, etc)	Generator	output= in the request parameters
reads requests from the user interface, buffers user data.	ClientData	context.getClientData()
validates user data	ClientData	clientData.validateTable()
converts user data to the appropriate database type	Convert	context.getConverter()
saves the data	ServerDataWriter	Override from XML. (rarely context.initServerDataWriter())
displays the results including any messages to the user.	Message	context.getMessages()
We will take a closer look at these classes starting with data organization.

Data Organization
Data is organized in tables and addressed by (tableName, controlName, row) where tableName and controlName are the XML name= attribute of the table and control. row is a sequence number for each row starting from zero.
A ClientData interface is used to access buffered data. Within a ServerDataWriter you can call context.getClientData() to get access to the ClientData object.
Lets look at a sample code; assume we are in ServerDataWriter.beforeUpdate() method:
ClientData clientData=context.getClientData();
int rows=clientData.getRowCount(“d”);
for(int rowNum=0; rowNum<rows; rowNum++){
if(clientData.isRowDeleted(“d”,rowNum){
continue;
}
if(clientData.getBoolean(“d”,”boolean_control”,rowNum)){
clientData.setNull(“d”,”some_control”,rowNum);
}else{
double doSomeMath= clientData.getDecimal(“d”,”decimal_control”,rowNum,0);
clientData.setParameter(“d”,”some_other_control”,rowNum, doSomeMath);
}
}
First, we loop throw all the rows of a table named “d”. The method getRowCount() returns the number of rows. Then we check that the row is not marked for deletion with isRowDeleted(). (More on row statuses below.)
We use the getBoolean() method to check the value of the control “boolean_control” which is probably defined as checkbox in the XML definition. We also use the getDecimal() method to get a double value. The call to getDecimal() has four arguments. The last one is the default value to be returned if the value does not exist (or cannot be converted to a double). There is also a three argument getDecimal() which throws a ParseException instead of returning a default value.
There exist methods to get all the supported types such as getDate(), getInt(), etc. All work as the getDecimal() method in the example.
To change the data we use setParameter(). There is one such method for each supported type as well. We use setNull() to set the value explicitly to null.
MetaWareJ maintains a status for each row which tells us if the row is modified, new, or deleted. Use the ClientData methods isRowNew(), isRowModified(), isRowDeleted() and setRow...() to access or modify the status. The status of row dictates the SQL statement (insert, delete or update) to be submitted.

newClientData.setParameter("balance", "someInfo", 0, 20);
newClientData.setRowModified("balance", 0,true);
Searching for data: find()
The ClientData interface offers methods to search for buffered data. The most general is
int find(String tableName, List<String> columnNames, List<String> values,int startRow);
It finds the next matching row given the List on column names and a list of values.

DataReader interface
MetaWareJ buffers data sent by the user. This data is available using the ClientData interface as we have seen. MetaWareJ does not always buffer data read from the database. Sometimes data is read from a JDBC database using a ServerDataReader and sent to the user directly, for performance reasons.
Internally, MetaWareJ uses a DataReader interface as the primary source of data. Implementations of this interface, such as ServerDataReader and ClientDataReader, hide the details of where the data originated (the database or the user). Of course other implementations exist such as DefaultDataReader for getting default values from XML definitions, TextDataReader for reading text files, etc.
You can use the DataReader interface yourself if you are writing code that might work with other sources than buffered data or if you find it more convenient than using the ClientData interface directly.
The DataReader interface provides methods accessing data organized in a table and accessed by named fields, as show in the following code fragment:
while(reader.next()){
if(reader.getBoolean(“wantsIcecream”)){
doSomethingWithRow(reader.getRow());
}
}
This is resembles the way JDBC ResultSet works.
We will see how to get a DataReader a little later. For now, we call next() to get the next row and one of the methods getBoolean(), getString(), getDate(), getDateTime(), getDecimal(), etc. to access the data. The isEmpty() method returns true if the field is null or empty string. You should check for empty before calling the get...() methods because they throw ParseException if the data is missing.
To loop through the rows of a table in a ClientData, a DataReader class can be used, as in the following code
DataReader reader=new ClientDataReader(context, “tableName”);
while(reader.next()){
}
DataReader class also has methods to check the status of the current row isRowNew(), isRowModified(), isRowDeleted().

More on Data Types
Here is a list of data types that can be defined in XML and their mapping to database and Java types.
XML type	Java Type	DB Types
STRING	String	varchar, char, etc	The default data type is STRING.
NLSSTRING	String	varchar, char, etc	If you define in XML a control with data type NLSSTRING, instead of STRING, MetaWareJ will look-up the returned value in the dictionary. You could store the key in the database and enter the displayed values in one of the dictionary property files.
DATE	java.sql.Date java.util.Date	date	DATE is a real date (without time). The input control for DATE accepts a single digit to mean a day of this month (e.g. entering 13 means 13/4/2012 assuming we are in April of 2012), 3-4 digits to mean a day of month in the current year. In any case, the “/” separator is not needed. If you work with US locale, a single digit still means the day, but the formatted date will be mm/dd/yyyy. To enter month and day however, enter the month first.
DATETIME	Timestamp	MySQL: datetime or timestamp Oracle: date Informix:datetime	DATETIME works more or less like DATE, except that it includes the time as well in hh:mm format.
BOOLEAN	boolean	int	BOOLEAN is used mainly with checkboxes and it needs an integer type in the database.
INT	int	int, integer	A 32 bit integer number
DECIMAL	double	decimal	DECIMAL defaults to a 2 decimal point double number. For US locale the period (.) is used as a decimal separator, for the rest the comma (,).
MESSAGEDIGEST	String	varchar, char	MESSAGEDIGEST data type is used to store passwords. Any field of this type will be converted by default to SHA-256 hash value before saved. The algorithm can be defined in global.properties MessageDigestAlgorithm parameter.

User Messages
The Message class is provided to communicate with the user. A message consist at least of a key and a type.
The key is looked-up in the dictionary to retrieve the message based on the user's language.
The type is a value from the enum Message.level which is one of EXCEPTION, ERROR,WARNING, OK. Messages of type EXCEPTION, ERROR are fatal, i. e. the transaction will be rolled back if they exist.
Messages can be simple text or links. When one of the addMessage() methods is used and a tableName, controlName and rowNum is passed, the message appears as a link that takes the focus to that particular control.
Messages allow simple parameter substitutions. If a message contains the '#' character it will substituted by the next available argument of addMessage().

Changing the retrieve process, ServerDataReader
MetaWareJ allows you to replace/extend the default ServerDataReader which is the class responsible for reading the data for one <table> from the database. The default ServerDataReader uses a direct JDBC connection, executes the SQL select statement in the <recordSet> and buffers the data.

canRetrieve()
The first reason to change the ServerDataReader is to allow us to read or not read the data based on some business rule. For this we code the canRetrieve() method.
import cy.com.methodosit.common.jdbc.ServerDataReader;
public class MyServerDataReader extends ServerDataReader{
@Override
public boolean canRetrieve() throws BackEndException {
ClientData clientData=context.getClientData();
if(clientData==null){
return super.canRetrieve();
}
return isManager(clientData.getSessionData().getUserLevel());
}
}
We also need to plug-in our class to the XML of the <table>
<form...
<table ...
serverReaderClass=”my.company.myApp.MyServerDataReader”>
If the method returns true MetaWareJ will continue retrieving otherwise it will stop processing this <table>. A <table> has a visible attribute which is not affected by canRetrieve(). This means we can retrieve invisible tables or stop retrieving visible table.

afterRetrieve()
There are cases when we need to modify the data after it is retrieved and before they are shown. We may, for example have some complicated rule for default values that cannot be expressed directly using the default attribute of the control in XML.
In these case, we can program the afterRetrieve() method of our the ServerDataReader. It is called after all records have been buffered for a <table>.

Non-JDBC sources
There are cases when our data do not come from a database SQL. This is another reason to change the default ServerDataReader. As an example, assume we have a report on which we need to apply a complex set of calculations which are either easier or faster to do in Java rather than in the database. Assuming we will show the results of the calculations in its own <table> then we will have a ServerDataReader that does not talk to the database.
Here is sample code:
public class MyTotals extends AbstractServerDataReader{
@Override
public String getConvertedValue(MControl control) throws BackEndException{
ClientData clientData=context.getClientData();
double result=clientData.getDecimal("someTable", “someControl”, 0, 0) -
clientData.getDecimal("someOtherTable", “someControl”, 0, 0));
return context.getConverter().toString(result);
}
private int row=-1;
@Override
public boolean next() throws BackEndException{
return ++row<1;
}
We extend AbstractServerDatarReader in this case since we don't need a JDBC connection.
getConvertedValue() is what MetaWareJ uses to access the data from the ServerDataReader. We can do whatever calculations we need and return the appropriate value. Note that the method must return a properly formatted String which is done with context.getConverter().toString().
When extending the AbstractServerDatarReader we must implement all the remaining abstract methods. The method next() returns true if a next row is available. so we can use it to return/create as many rows as required. In the above example, we wanted to create a single row, which is done by return ++row<1;

Changing the update process, ServerDataWriter
The ServerDataWriter class is responsible for saving the data. We have already seen an example of extending/changing in the section Adding Business Logic .
ServerDataWriter class executes one transaction updating all the data for a single <form>. The update transaction consists of these steps, as sequence if methods calls :
beforeUpdate(). Runs before transacton begins. Default does nothing. to be overriden.
connect to database
lock(). Uses <lockStatment> for concurrency, see Concurrency and <lockStatement>.
various checks.
startTransaction() Runs within transaction. Default does nothing. to be overriden.
doTransaction(). MetaWareJ updates the data, Do not override.
endTransaction() Runs within transaction. Default does nothing. to be overriden.
commit() (or rollback() if we don't get this far)
afterUpdate() Runs if transacton ends sucessfully. Default does nothing. to be overriden.

More on Update Statements: Inserts and Deletes
We have seen how MetaWareJ automates the update of records based on status of each row, in section Updating Data. There are more XML elements you can use to control the update process, the <insertStatement>, <deleteStatement>, and <updateOnlyStement>.
For example, in order to keep the consistency of your data you need to ignore other users' changes and just save what you have in the screen in front of you. To do so you need to issue <deleteStatement> in the parent table and the <insertStatement> in the child table .
Assume you are updating a table called PARENT_TABLE and you want to delete all rows from its child table called CHILD_TABLE. (You will need to issue an <insertStatement> in the child table to save back all its rows after the deletion).
In this case, the update section of the PARENT_TABLE <table> will look like:
<table name=”master” ...
<deleteStatement table="CHILD_TABLE">
<key name="fk_to_master_id" parameter=”id” type="INT"/>
</deleteStatement>
<update table="PARENT_TABLE">
<column name="id" auto="true" type="INT"/>
<key name="id" type="INT"/>
</update>
....
</table>
<table name=”child” ...
<insertStatement table="CHILD_TABLE">
<column name="id" auto="true" type="INT"/>
<key name="id" type="INT"/>
</insertStatement>
Here we ask MetaWareJ to delete all rows from table CHILD_TABLE using the fk_to_master_id column and passing the control value id as argument.
The <deleteStatement> and <insertStatement> statements, by default, ignore the status of a row. So the <insertStatement> in the child table will issue an insert statement for each row (that is not deleted). The child table does not have an <update>.
You can use the attribute useRowStatus to force the two elements to use the row status. For example, we have two table FIRST_TABLE and SECORD_TABLE. We need to delete the records of the SECOND_TABLE for each deleted row of the first. This is something that a database can do with a cascade delete foreign key. If we add to our FIRST_TABLE a <deletedStatement table=”SECOND_TABLE” userRowStatus=”true” it will do what we want.
To summarize, the <deleteStatement> will, by default, issue a delete statement for each row of the <table> if it is not a new row. If useRowStatus is set to true, it will issue a delete statement for each deleted row, instead.
Similarly the <insertStatement> will issue, by default, an insert statement for each row of the <table> if it is not deleted. If useRowStatus= is set to true, it will issue an insert statement for each new row, instead.
The <updateOnlyStatement> wokrs in a similar way and only updates records.
Remember that a plain <update> statement will issue:
a delete statement for each delete row that it is not new,
an update statement for each modified row that it is not deleted.
and an insert statement for each new and modified row that it i snot deleted.
The order the statements are executed is:
First we delete records starting for the last <table> on the <form>.
Then we update records starting from the first <table> of the <form>
and finally we issue insert statements starting from the first <table> of the <form> .

Concurrency and <lockStatement>
MetaWareJ does not handle concurrency. It is up to you as a programmer to decide for each transaction, table, etc. the type of concurrency needed and how to enforce it.
MetaWareJ provides a <lockStatement> element that you can use to lock some records based on your policy. The <lockStatement> will issue a “select ... for update” SQL statement. All <lockStatement> for all <table>s of a <form> are executed first, followed by the other statements.
Example: we are issueing invoices as in the previous example and we want to varify that no two users issue an invoice for the same customer and service at the same time. So as a policy, we decide to lock the cutsomer record before we proceed to make whatever checks need to be made. We add this to a relevant <table>
<lockStatement table="customer">
<key parameter=”customerId” name="id" type="INT"/>
</lockStatement>
MetaWareJ will lock the customer record using the value of the customerId control, before any other statement executes. You can then use the startTransacrtion() method to do any additional validations. You should of course make sure that any additional data retreived from the database use the same connection object, ie are part of the same transaction. See the following section Accessing, modifying and protecting data. on how to read additional data.
MetaWareJ does not maintain any locks between the time the data is retrieved (using a ServerDataReader) and the data are written (using a ServerDataWriter). In a web environment this would be impossible. Any locks taken during retrieve, because of the isolation level of your database, are released after the data of each <recordSet is retrieved. This means that retrieve is not done in a single transaction.
Writing the data is done in a single transaction, but again it is up to you to enforce your concurrency constraints.

Accessing, modifying and protecting data.
We often need to retrieve and/or modify data in order to apply the application rules, in addition to the data shown and submitted by the user. It is common, for example, in applications to have to update various tables with calculated data, data structures internal to the application, sensitive/secure data, data that need to be retrieved to verify consistency, etc. These can be part of a single or multiple transactions.
You can choose whichever method to access these additional data from within your extended ServerDataWriter. You can, for example, use the provided Connection object and write your own JDBC based code. You can, however use MetaWareJ code to buffer, examine, modify and save data.

MANUAL tables and bufferOnly controls
When you need to access additional data, you can define within your <form> one or more <table>s of function=MANUAL. MetaWareJ will not autotically buffer these tables and will not display them to the user, even if they have data. You can use the bufferTable() methods to retrieve these tables as you need.
If you modify the row status in a MAMUAL table during an update action, MetaWareJ will update them along with the rest of the data. So, you can use a MANUAL table to insert data in a database table that the user does not access, for example.
Since MANUAL tables are not shown to the user, you can use the control bufferOnly to give MetaWarej the minimum information required to buffer the data. bufferOnly however can be used in a DATA table, if you want to retrieve a column for use in your ServerDataReader code, but don't want to column displayed.

Protected and Original Values
Web clients are stateless, so there is no way of knowing if data were changed when a user submits a form. Even hidden fields can be changed, if the user knows how. We have seen a primary key control as:
<hidden name="id" type="INT" key="true" auto="true" protect="true"/>
This means that the “id” control value will not change.
MetaWareJ uses message authentication code (MAC) to verify integrity. Note that new rows are not part of the integrity check. If the integrety check fails, MetaWareJ displays a fatal error and the user session ends. There is no way to recover form it and it might be a securtiy risk.
If we want to allow the user modify a value but we still want to know the previous value we can use the keepOriginal attribute in a control. Then we can use methods getOriginalParameter(), getOriginalDate(), getOriginalDecimal(), isOriginalEmpty(), etc. to get the original value. The original value is always protected so that we can be sure that the user did not change it.

Buffering a single table (ClientData.bufferTable())
ClientData.bufferTable() is the most direct method to read a <table>. Assuming you have a <table> named “d” in your form that you want to retrieve, you call ClientData.bufferTable(“d”). This will retrieve the table in the same way it would when the user hit the FIND button, in other words, it will use the arguments defined in the <table> as usual. This method will not reset data already buffered, you can call resetTable() if you need to remove existing data.
You can use the two argument ClientData.bufferTable(tableName,newTableName) to buffer the data using the same <table> definition but under a different name. In fact, this method will temporarily add the new table to the form. The data will also be saved as part of the transaction, if you modify the statuses accordingly. It is “temporarily” because the actual form definition will not change. After the transaction is finished the new table no longer exists. The new table will be shown to the user, however, if you make it visible using MTable.setVisible(true). It is added as invisible by default.
The most general form of bufferTable is
bufferTable(Object connection,String tableName, String newTableName,String...args)
You will need to use this form if you want to retrieve data within the same transaction. For example, in a ServerDataWriter, after MetaWareJ has locked some records you might want to do some consistancy checks. Data retrieved in this case must be in the same transaction , os you need to pass the connection object of the ServerDataWriter to the bufferTable().
This bufferTable also accepts its own retrieval arguments, which will use instead of any existing.

Buffer a table from a different form
An example: you are issuing an invoice and want to verify that the customer does not have more than defined amount outstanding credit.
We first create a new XML file “myApp/customerBalance.xml” which returns the amount in the table “balance” control “credit”,given the customer id in control “id” of the search table. Note that we don't actually have to create the search table “s” in our new file if it is never going to be used for the user interface.
<table name="balance" function="DATA">
<recordset>
<selectString>
select sum(some_amount) credit from customer
</selectString>
<argument parameter="id" where="id" type="INT"/>
</recordset>
<controls>
<hidden name="credit" type="DECIMAL"/>
</controls>
As usual we extend ServerDataWriter to add our rules, as in the following code sample.
In the appropriate method of ServerDataWriter, we create a new context object based on the XML form using context.newContext(form,forUpdate). The second argument tells MetaWareJ if this new context will be updated as part of the current transaction.
By creating a new context we get a new ClientData buffer separate from the ClientData of the current context. This makes data manipulation easier since there can be conflicts between table names from one form to the next (especially if you name all your data tables “d” like we do.)
Next we pass the customer id argument. Note that we have to get the new ClientData from the new context. Last, we buffer the table “balance” which will retrieve the data in the new ClientData buffer.
import cy.com.methodosit.common.jdbc.ServerDataWriter;
public class MyDataWriter extends ServerDataWriter{
@Override
public void endTransaction() throws BackEndException{
ClientData clientData=context.getClientData();
int id=clientData.getIt(“d”,”id”,0,-1);
MetaWareJContext newContext=context.newContext(
“myApp/customerBalance.xml”,
false /*forUpdate*/);
ClientData newClientData=newContext.getClientData();
newClientData.setParameter("s", "id", 0, id);
newClientData.bufferTable("balances");
if(newClientData.getDecimal(“balances”,”credit”,0)>LIMIT_AMOUNT){
context.getMessages().error(“No more credit”);
}
If we wanted also to update the balance or some other information, we would create a normal <update> element in the “balance” <table>, pass true in the second argument of newContext() and modify the data. MetaWareJ would do the rest. Remember to change the row status when modifying data; MetaWareJ will not do that automatically.

Retrieving multiple tables at once (Processor.retrieve()).
Above we retrieved the data for a single <table>. We can do the same for all the tables in a form using Processor.retrieve() as in the example below
MetaWareJContext newContext=Processor.retrieve(
currentCcontext.getClientData().getSessionData(),
"someFile.xml",
“param1”,”value”,...);
or
MetaWareJContext newContext=Processor.retrieve(
"someFile.xml",
“param1”,”value”,...
);
These methods can be used, for example, when we want to combine data from various sources. The “someFile.xml” can define a ServerDataReader that reads a web service. We can access the database that the application is using normally through the current XML screen and access the web service data using retrieve().
We can also use these methods to use MetaWareJ as a library, i.e. use it from a different application to access data.

Adding rows
When you use the ClinetData setParameter() methods, MetaWareJ adds new rows as needed. If the row did not exist, the rest of teh controls remain empty as is the row status. So you should always call setRowNew() setRowModified() to set the status. Setting the row status before setting any control will also add a new row in the ClinetData.
To initialize a new row using the control definitions in XML use the bufferFromDefaults() method. The method will add defaultRecord rows and initialize the controls using their default attributes. Row will have status as in the <table> attribute newRowStatus which defaults to NEW.

Manually updating a transaction
We saw above how to retrieve additional data and save it as part of the current transaction. We can however update the data in a separate transaction or manually if required.
UpdateTransaction trans=new UpdateTransaction();
trans.update(newContext, true /*commit*/);
if(!messages.hasErrors()){
First we create a newContext as shown in the previous section. Then we run the simple code fragment above. The second argument of the update() method tells MetaWareJ if it will call commit or not. If we pass true, the transaction is committed or rolled back when we return. If not, we have to commit it ourselves perhaps as part of a bigger multi-context transaction.

Custom Actions
Buttons in MetaWareJ are connected to an action such as Find, Update, Next, Add, etc. If you need to perform some action other than the default then you have two options. The first, as we have seen, is to extend the ServerDataWriter and perform your action with the Update action. For example , if you want to sent an email after the data is saved, you can put the logic in the ServerDataWriter.afterUpdate().
The second option is to write your own action. An action is any class the extends AbstractAction and implements doAction() method. Your action has access to the context using the context variable of AbstractAction.
You can trigger you action by connection it to a button, as in this example used to reset the cache of MetaWareJ:
<button type="CUSTOM" help="clear_cache"
actionClass="cy.com.methodosit.common.baseApp.ClearCacheAction"/>
The action class is:
public class ClearCacheAction extends Display{
@Override
protected void doAction() throws BackEndException {
SelectModelFactory.clearCache();
}
}

Changing the user interface, MForm, MTable
Generally MetaWareJ does not allow modifications of the user interface through programming. The basic design principle of MetaWareJ is that screens should be simple, consistent and that the programmer should not have to deal with them.

Changing the XML definition dynamically
There are cases where a more dynamic layout is needed. For that reason, MetaWareJ allows you to substitute the base classes that hold the XML information with your own and change pretty much anything you want. There are two classes of interest, both under cy.com.methodosit.Meta, the MForm and MTable. The first represents the <form> while the second represents a single <table>.
To change the default classes, first create your class by extending the MetaWareJ class. Then, plug-it-in to the XML file using the implementingClass attribute of the <form> or <table> elements.
This method can be used to make a table or a control invisible, change the form title, etc. See the javadoc for full description of the default classes.
For example, assume we want to make a control invisible if the user is not a manager.
First we create our MTable class:
package my.company.myApp;
public class MyMTable extends MTable{
@Override
public boolean isControlVisible(MControl control){
ClientData clientData=getClientData();
if(clientData==null){
return super.isControlVisible(control);
}
if(“privateInformation”.equals(control.getName()){
if(isManager(clientData.getSessionData().getUserLevel())){
return false;
}
}
return super.isControlVisible(control);
}
The check for null ClientData is always needed because this method can be called before the data is initialized.
Then we plug-it-in the XML file:
<form...
<table ...
implementingClass=”my.company.myApp.MTable”>
<controls>
<input name=“privateInformation” ... />

Style Sheets
For HTML clients, MetaWareJ uses cascade style sheets (CSS) to define the display attributes. The main CSS file is called bb.css and you should not change it. Additional style sheets can be defined by adding a <CSSFile filename="file.css"/> section in your XML definition and use your styles using the controls' style, labelstyle, and boxStyle attributes.
MetaWareJ also provites a print.css style sheet, which is designed for printable HTML output. You can add it to your form using <CSSFile filename="print.css"/>.

Button Style
MetaWareJ uses image buttons as you can see in all examples of this document. If you prefer to use more traditional style buttons, you can set the global property ButtonsAppearance=TEXT in the global.properties file. This will show buttons as shown in Screen 29: Toolbar Buttons and Traditional Buttons
Screen 29: Toolbar Buttons and Traditional Buttons

Dynamic Lists
We have seen in Drop down, popup lists and interactive search the various controls MetaWareJ provides for allowing the user to find and choose from existing data. If you need to build more dynamic lists then you need to do some programming.
Let's show an example. Assume that you have a drop-down list in the form of a <select> control which show the available benefits in some insurance plan.
<select name="benefit" dbname="benefit_id" type=”INT”
label="benefit" codeColumn="id" labelColumn="befenit_descr" >
<selectString>
select id, befenit_descr from available_benefits
</selectString>
</select>
Assume further that a user can only access certain benefits based on his level. In order to filter the list, we extend the ReferenceTable class of MetaWareJ as:
import cy.com.methodosit.common.jdbc.ReferenceTable;
public class BenefitReferenceTable extends ReferenceTable{
@Override
public String getSelectString(){
return "select id, befenit_descr from available_benefits "+
“ where user_level =”+clientData.getSessionData().getUserLevel();
}
}
We extend ReferenceTable which is the default class used to fill the list of a <select> control. The getSelectString() method returns the SQL statement to run, and we add the extra condition to it. Note that since the user level in clientData.getSessionData().getUserLevel() is controlled by MetaWareJ there is no security problem in adding it directly to the statement.
We also need to let MetaWareJ know which class to use when filling the select list by plugging our class to the control. We modify the above example with:
<select name="benefit" dbname="benefit_id" type=”INT”
selectModelClass="my.company.insuranceModule.BenifitReferenceTable"
You can use the above technique to build lists of any kind. All the lists and search controls support the selectModelClass attribute. The class you provide must implement the select.SelectModel interface, but as we show above it is easier to extend one of the available classes and override what you need. The default class used by each control is listed in the XML reference manual.
Lists are cached for performance in MetaWareJ. The key used for caching is taken from the method SelectModel.cacheKey(). In the case of a ReferenceTable, cacheKey() returns the SQL select string used to produce the list. If you are building a list that is not based on constant or seldom changing data then caching should be disabled. To do this you override the cacheKey() method and return null.
In the example above, a new list will be cashed for each user level since we are adding the user level to the select string. Assuming that we have a system with hundreds of user levels, it will make caching inefficient. So we should turn caching off by adding the following code
@Override
public String cacheKey(){
return null;
}

Connecting to non-JDBC sources
This manual assumes that we are working with a direct JDBC connection to a relational database. This is not the only way to store your data however. If you want to use a different back-end, you can implement the cy.com.methodosit.common.ServerDataWriter interface directly or extend the cy.com.methodosit.common.AbstractServerDataWriter class and the cy.com.methodosit.common.ServerDataReader interface.
We have seen an example in Non-JDBC sources.
MetaWareJ already uses various implementations of ServerDataWriter, for example to save the XML files when using the editor.

Interface with Apache™ Subversion®
Apache Subversion is an open source version control system. MetaWareJ can use Subversion to store and retrieve documents. The interface is based on SVNKit libraries.
To use the interface, first, you need to setup two global parameters SVN_BASE_URL and SVN_BASE_DIRECTORY, for example with SVN_BASE_URL= file:///somePath and SVN_BASE_DIRECTORY=someDirectory the subversion client will check-out and use the URL file:///somePath/someDirectory.
MetaWareJ has two ready to use XML files, attachment.xml will download a file from subversion and svnhistory.xml will show log and history information for a file. Both files expect a single parameter “filename”.
So the URL ?f=attachment.xml&filename=myProject/analysis.pdf will download the file myProject/analysis.pdf.
To use the interface from your application you need to use the cy.com.methodosit.common.subversion.SVNClient. You will find information in the javadoc. See an example in the <channel>: non-database output creation.

Emailing
MetaWareJ provides a simple wrapper around the JavaMail library that can be used to send email. The class OutgoingMail has methods that can be used for the most common mail tasks as in the code that follows. The mail will be sent to the server and port in the global parameters mail.smtp.host and mail.smtp.port.

OutgoingMail outgoingMail=new OutgoingMail();
outgoingMail.setFrom(...);
outgoingMail.addRecipientTo(...);
outgoingMail.addRecipientCC(...);
outgoingMail.addRecipientBCC(...);
outgoingMail.setSubject(...);
outgoingMail.setText(...);
outgoingMail.attach(file);
outgoingMail.send();
SMS
A simple SMS interface for CYTA exists in CytaSMS class. It has a single call:
sendSMS(String msg,List<String> phones).
The global parameters SMS.CYTA_URL, SMS.CYTA_KEY, and SMS.CYTA_USER must be defined.

<channel>: non-database output creation
The basic flow of MetaWareJ is designed for generating one output based on the output= parameter. The various generators produce output based on the data in the ClientData buffer, mostly written to a stream.
A channel can be inserted in the MetaWareJ process flow instead of the output generation. The channel is expected to create the output itself.
We can insert a <channel> in our screen definition, for example:
<form ... >
<channel channelClass="cy.com.methodosit.SomeChannel"/>
<table name=”d” ...
</form>
The channel class must extend the cy.com.methodosit.common.AbstractInputChannel class. A channel is a simple interface and can be used to create any type of output.
The following code example uses the subversion interface to send a file to client. In the init() method the SVNClient is initialized and the File containing the checked-out file is obtained. In the write() methods the file is copied to the OutputStream.
@Override
public void init() throws BackEndException{
ClientData clientData=context.getClientData();
SessionData sessionData=context.getClientData().getSessionData();
svnClient= new SVNClient( sessionData.getUserLogin(),"");
inputFile=svnClient.getFileForReading(clientData.getParameter("filename"),
context.getMessages());
}
@Override
public void write(OutputStream stream) throws BackEndException{
try{
// copy to outputChannel
InputStream input=new FileInputStream(inputFile);
Util.copyStream(input, stream);
input.close();
}catch (...) {
}
}
@Override
public String getFilename(){
return inputFile.getName();
}

Upload file
The control <filelookup> can be used to upload a file. It is up to you to save the uploaded file.
For example, we have a control in a table:
<form ... serverWriterClass="cy.com.methodosit.example.SaveFileWriter"
<table name="a"
<controls>
<filelookup name="newfile" label="upload"/>
Then in the SaveFileWriter we use the following code to save the file:
if(clientData.isUploadFileCapable()){
for(int i=0;clientData.existsRow("a", i);i++){
String filename=clientData.getUploadedFileName("a”,”newfile",i);
if(filename!=null && !"".equals(filename)){
clientData.SaveUploadedFile("a", "newfile", i, new File(...));
}
}
}
Error checking is omitted as usual. We will need to specify the actual location of the file, of course.
The clientData.isUploadFileCapable() is always needed because the other two methods will throw an exception if no file has been uploaded. The rest is simple, getUploadedFileName() returns the name of the original file. This is only the file name, not the path. SaveUploadedFile() saves the uploaded file to the location specified.

Batch jobs
If you need to execute a job at regular intervals you can use the BatchJob class. First, extend the BatchJob class and code the execute() method. BatchJob is a servlet so you can add your new class in the web applications web.xml file, with a <load-on-startup>1</load-on-startup> so that Tomcat will start the servlet. Then add the parameter loopSeconds in the global.properties file. The execute() method will then be called every loopSeconds seconds in its own thread.
loopSeconds possible values are -1- which disables the batch job, 0 executes only once, and n means every n seconds.

Classes and Interfaces that can be overridden or re-implemented FIXME
(all class names are under cy.com.methodosit.common)
Interface/ Abstract Class	Implementing classes/interfaces in MetaWareJ	How to change Examples of implementing classes/interfaces in other applications (under cy.com.methodosit)
ServerDataReader	jdbc.ServerDataReader	Defined in XML attribute <table serverReaderClass=””>
ServerDataWriter	jdbc.ServerDataWriter jdbc.Password – re-authenticates user	Defined in XML attribute <form serverWriterClass=””>
MForm	Meta.MForm	<form implementingClass=””
Message	Message	<form messagesClass=””
MTable	Meta.MTable	<table implementingClass=””
MenuData	MenuData	From global.properties file Parameter MenuDataClass
StaticData	DefaultStaticData	From global.properties file Parameter InitSessionDataClass
BatchJob (abstract)		In case of a web application it is started from a custom web.xml <load-on-startup> in the <servlet> section of web.xml
select.SelectModel	select.FixedList select.NullModel jdbc.ReferenceTable jdbc.LookupTable	Defined in XML attribute <controls> <select selectModelClass=””> <lookup selectModelClass=””> etc
action.abstractAction	action.Next, action.Upadte	Defined in XML attribute <button actionClass=/>

Reports, Chart and PDF
MetaWareJ can produce reports and chart either as HTML or PDF output.
For PDF output we can use the iText library version 5 from http://itextpdf.com/, if it is available. Because of license restrictions, however, it is not delivered with MetaWareJ. If you can use iText then add the jar file under the WEB-INF/lib directory of your project and enable PDF output setting the ShowExportPDF=true in the global.properties file.

Reports
A <table> with function=REPORT represents the basic report. All active elements are removed, that is all controls are readonly, buttons other than search buttons (FIND, PDF, CSV, etc.) are removed, the delete control is removed, etc.
There is also a REPORT button. A REPORT button submits a REPORT action which is similar to a normal search except that:
all data tables are changed to be REPORT tables.
tab/tabpages are removed from the output
paging (Next/Previous) is done automatically. All records are retrieved/displayed.
Let's look at an example, continuing the example of section 3.5Master/Detail.
<form title="customer" >
<table columns="2" name="s" format="FORM" function="SEARCH">
<controls> .... </controls>
<buttons>
<button type="REPORT"/>
</buttons>
</table>
<table name="d" title="customer" function="REPORT" format="GRID" >
<recordset orderBy="customer.name">
<selectString>
select customer.name,
project.id,project.date_opened,
project.customer_id
from customer, project
where customer.id=project.custoner_id
</selectString>
<argument parameter="name" where="name" alias="customer.name"/>
...
</recordset>
<controls>
<text name="name" group="true"/>
<text name="dateOpen" dbname="date_open" type="DATE"/>
</controls>
<controls> .... </controls>
</table>
Here we retrieve both customers and projects in a single <table> and we use the group=”true” attribute to show some controls only once, on the group header. The group header consists of a single row of controls, see Screen 32: Group Report Layout.
The button for the search table is now a REPORT button. For this report to have meaning, the order of the data must be set in the <recordset> using an orderBy.
Let's look at the same example in a different way.
<form title="customer" >
<table columns="2" name="s" format="FORM" function="SEARCH">
<controls> .... </controls>
<buttons>
<button type="REPORT"/>
</buttons>
</table>
<table name="d" title="customer" function="REPORT" format="GRID" >
<recordset rowsPerPage="1" > .... </recordset>
<controls> .... </controls>
</table>
<table name="p" title="projects" function="REPORT" format="GRID" >
<filter master="d">
<match master="id" detail="customerid" />
</filter>
<recordset orderBy="descr"> ... </recordset>
<controls> ... </controls>
</table>
Here we have three tables ,'s' a SEARCH table, 'd' a master table and 'p' a child REPORT table. The button for the search table is a REPORT button.
When clicked, the 'd' table will be retrieved and for each record fetched (rowsPerPage=”1”) the child 'p' table will be retrieved based on its <filter>. Records of the 'd' table will be fetched one at a time until all records are shown, simulating the Next button being pressed.
Note that since the button is REPORT (instead of FIND) the 'd' and 'p' tables' function will automatically be set to REPORT, even if it was DATA, and the rowsPerPage of table 'p' will be set to 1 even if it were not.
Since we simulate a Next action, a select will be issued for the mater table multiple times (once for each row) and the child table will be retrieved once for each row of the master table. This might be inefficient and slow depending on the situation. It does allow us, however, to turn any XML screen to a REPORT, or at least produce a printable output from any XML screen either as HTML, as the example above. or as PDF as we see below.
Reports that contain master/detail relations might be more efficient if done using nested tables. See below.
One final note, if you want to produce HTML output for printing then you use the print.css style sheet which comes with MetaWareJ. It is designed for printable HTML output. You can add it to your form using <CSSFile filename="print.css"/>. See Style Sheets for more on style sheets.

<nested> tables
A <table> can have a number of tables nested within the <table> definition, example:
<table name="d" title="offer" function="DATA" format="FORM">
<recordset > .... </recordset>
<controls> .... </controls>
<nested>
<table name="n1" ...> ... </table>
<table name="n2" ...> ... </table>
</nested>
</table>
A nested table might be a child table of the outer table by using a <filter> element but it does not have to. A nested table will be displayed after each row of the outer table.
If the nested table is additionally a child table and has its own <recordset>, it will be retrieved for each row of the outer table. This scenario is very similar to the master/detail REPORT we describe above. The main differences are:
The master table is retrieved only once. In the normal master/detail case the master table is retrieved once for each row.
The XML with nested tables can only be used for reports, you build interactive forms using normal tables.
Nested tables can have nested tables themselves, in other words we can have multiple levels of nested tables.

<nested dataFrom=“” > tables
You might have noticed that above we said “ ... and has its own <recordset>”. This is because nested tables[1] can share the data with another table and so avoid being retrieved multiple times.
[1] Actually any table can use dataFrom, not only nested tables, but it is most useful for nested tables.
Only an example will save us here. Assume we have customers and projects for each customer, as in the examples used in the Your first MetaWareJ application: A tutorial.
We want to show a report that shows the customer details followed by a list of projects for each customer.
<form title="customer" >
<table columns="2" name="s" format="FORM" function="SEARCH">
<controls>
...
<input name="name" label="custname" size="25" maxLength="50" />
</controls>
<buttons>
<button type="REPORT"/>
</buttons>
</table>
...... Continues ......
<table name="invCustomers" visible=”false” buffered="true">
<recordset >
<selectString>
select project.id,project.date_opened, project.customer_id
from customer, project
where customer.id=project.custoner_id
</selectString>
<argument parameter="name" where="name" alias="customer.name"/>
...
</recordset>
<controls>
<hidden name="id" type=”INT”/>
<hidden name="customerId" dbname="customer_id" type="INT"/>
<hidden name="dateOpen" dbname="date_open" type="DATE"/>
</controls>
</table>
<table name="d" title="customer" function="REPORT" format="GRID" >
<recordset >
<selectString orderBy="user_code">
select id,user_code,name from customer
</selectString>
<argument parameter="name" where="name" />
...
</recordset>
<controls>
<hidden name=”id” type=”INT”/>
...
</controls>
<nested>
<table name="p" dataFrom="invCustomer" title="projects"
function="REPORT" ...>
<filter master="d">
<match master="id" detail="customerid" />
</filter>
<controls>
<text name=”dateOpen” type=”DATE”/>
...
</controls>
</table>
</nested>
</table>
Some things should be familiar and some not. We have a normal SEARCH table. We have a normal REPORT table which shows the customer details (table “d”).
We also have a second first level table called “invCustomers” which serves as a buffer for the projects. This table:
it is invisible, nothing will appear on screen for this table. (visible=“false”)
buffers its data (buffered=“true”)
it is NOT a child of the customers table but it retrieves its data based on the arguments entered in the search table. This means that the customers and projects are retrieved independently and each is retrieved only once.
Although “invCustomers” is invisible, it still needs a <control> section because controls are used to buffer the data. All controls can be <hidden>, however, since we don't care about appearance (unless they are used in the nested table as well, see further down).
The other table of interest is the nested “p” table. This table does NOT have a <recordset> but has a dataFrom attribute in the element <table>. It is a child table of the customer table “d” because of the <filter> element. If it had had a <recordset>, the <filter> would have been used to modify the select statement as normal. Since we don't have a <recordset>, the <filter> will be used to filter the buffer of data created by the dataFrom table.
Note that the controls of the <nested dataFrom=> table must have the same names of the dataFrom buffer.
We can easily add more nested tables to our customers using the same technique. We could for example create and “invAddress” table and a nested “address” table to show the a list of address after each customer.
If the nested table will show the exact same controls as the invisible table then we can avoid duplicating the controls of the invisible table in the nested table. The nested table without <controls> becomes simply:

<nested>
<table name="p" dataFrom="invCustomer" title="projects"
function="REPORT" ...>
<filter master="d">
<match master="id" detail="customerid" />
</filter>
</table>
</nested>
Buffered and unbuffered <nested dataFrom=“” >
In the example above, the invisible table had the buffered=“true” attribute which means that it data will be buffered and that the nested tables that used its data will filter the buffer.
If the report is big[2] it might not be feasible to buffer all the data from the start. In this case we can leave buffered=“false”. The result will be the same but the data will fetched one record at a time[3] and filtered as it is read.
[2] How big is “big” depends on your environment. Running out of memory,is a good indication.
[3] ... or as many records your JDBC driver actually fetches when you do a ResultSet.next().
In nested reports with buffered=false, since the data are not buffered we must make sure that the sort order of the master table matches the sort order of the invisible table.
Buffered invisible table has the additional benefit that can share its buffer with more that one nested tables. Unbuffered table can also be shared with multiple nested tables but, since the data is not buffered, they will be retrieved once for each nested tables.

Summary of master/details reports options
So we have a CUSTOMER table and a PROJECT table and we want to show them in a report. Here are the options we have (as explained above):
1	Create a single <table> combining the two and have the controls that show customer details have a group=”” attribute.	Simple and fast, but it only shows the grouped controls in a single row.
2	Create normal master/details tables with rowsPerRecord (next, previous) and a REPORT button.	Internally it is the same as option 3.
3	Create master/details tables where the detail is nested.	The master table is retrieved only once. Slower than option 4 because the detail is retrieved multiple times but simpler XML which means simpler maintenance.
4	Create master/details tables where the detail is nested and shares buffer with an invisible table. The invisible table might be buffered or un-buffered.	Faster than option 3. More complicated to produce and maintain.

Charts
When the <table> function attribute is set to CHART (or to REPORT_CHART), the table will be shown as a chart, as in Screen 30: Sample Chart.
MetaWareJ supports two styles of charts: Bar (single or series) and Pie (single pie chart or multiple). The style of chart is defined by the chartFormat attribute of the table. Only the first three visible controls of a table are used in charts.
In Bar style, if the table has only two visible controls the first control is used as the category (x-axis). The second must be numeric and it is used as value. If the table has three controls, the first is used as the series, the second as the category and the numeric third as the value.
In Pie style, if the table has only two controls the first column is used as the category. The second must be numeric and it is used as the value. If the table has three controls, the first is used to create a series of pie charts.
Example:
The XML fragment below creates the chart shown in Screen 30: Sample Chart. The three controls are used as in turns as Series, Category and Value. Note that in this example all the data is included directly in the XML in the default attribute of the controls.
<table name="d" title="Report and Chart from defaults" function="CHART"
format="GRID BAR" defaultRecords="3">
<controls>
<text name="series" label="Series" group="true" default="Series 1"/>
<text name="categories" label="Categories" default="_[first,second,third]"/>
<text name="values" label="Values" type="INT" trailer="SUM" default="_[1,2,3]"/>
</controls>
</table>
Screen 30: Sample Chart

Reports and Charts using optional controls
MetaWareJ can create user-defined reports and charts. There are several concepts involved.

<form template=”true”
The first is the template attribute of the form element which allows the user to save the report parameters in the database. When is set to true, MetaWareJ creates three new tables (as show in Screen 31:Report Management Tables) which manage saved reports.
The first table shows already saved reports as links. When the user clicks on the link, the report runs.
The second table allows the user to save or delete the report.
The third sets some report parameters. These are:
“Show As” has options “Report”, “Chart” and “Report and Chart”
“Report Format” has options “Form” and “Grid”
“Chart Format” has options “Bar Chart” and “Pie Chart”
Orientation has options Landscape and Portrait.
“Number of columns” is used with reports of “Form” format to define the number of columns per line.
“Cutoff Percent” Used in charts. Categories with value less than this percentage will be shown in charts grouped under the “Other” category.
Screen 31:Report Management Tables

optional and column
The other two related elements are the optional attribute of the controls and the <column> element of the <recordset> element.
If a table has one or more optional controls then a new table will be added as shown in Screen 33: Optional column selection table, with which the user will be able to:
include/exclude the optional control in the report or chart.
set the order of the column within the report columns, i. e. define which column will appear first, second, etc. Using numbers 10,20,30,... will make the management easier.
set the sort order of the rows.
create groups. Groups appear as paragraphs in the report with the group columns in the header of the paragraph. See Screen 32: Group Report Layout . Note that rows must be sorted by the group columns. This is not done automatically. So if Customer is to be a group column, you enter 10 in the “Group” selection and 10 in the “Sort” selection.
Screen 32: Group Report Layout
Screen 33: Optional column selection table
Optional controls read their data (as do all controls) using the dbname attribute from the records retrieved using the table's recordset element. If we have many optional controls or controls associated with sub-queries, we want to avoid reading the data when the control is not selected (since it will not be shown).
For example, assuming we have a recordset with an SQL select as: (where-clauses not shown for brevity)
<recordset>
<selectString>
select c.customer_id, (select sum(d.amount) from details as d where ...) as amount where ...
</selectString>
</recordset>
with the “amount” column is used by an optional control:
<text name=”amount” optional=”true” />
the select sub-query will run even if the “amount” control is not included in the report.
To avoid the above problem we can use the column element of the recordset, as:
<recordset>
<selectString>
select c.customer_id as amount where ...
</selectString>
<column name=”amount” include=”(select sum(d.amount) from details as d where ...)”/>
</recordset>
This will include the sub-query in the SQL select only if the control is included in the report. [Caveat] A control (which is optional) and a recordset column must have the same name.

TemplateReportMForm and TemplateReportMTable
The report <form> should use the TemplateReportMForm and <table> should use the TemplateReportMTable class, as in:
<form
implementingClass="cy.com.methodosit.common.TemplateReportMForm"
<table name="d" ...
implementingClass="cy.com.methodosit.common.TemplateReportMTable"
This sets correctly the title, orientation, etc. of the report.

Running Template Reports
In the web application, when the form constructed as described above is loaded we find the list of saved reports as links. When you click on the link a URL of the form FormServlet?f=myApp/myReport.xml&do=LOADTEMPLATE&loadtid=24 is submitted. This loads the previously saved options and runs the report. You can then use the PDF button, for example, to produce the report is PDF format.
To run a template report directly to PDF, you can submit a URL as:
PDFiServlet?f=myApp/myReport.xml&do=RUNTEMPLATE&loadtid=24
Note that we use PDFiServlet and RUNTEMPLATE action.

PDF

Screen Output
MetaWareJ can produce PDF output from all screens. The PDF is produced on the server by re-submitting the request. It uses the same XML definitions.
Screen 34: Show-as-PDF link
The <table> attribute print defines which tables are included in the PDF output. By default virtual tables are not printed/included and DATA, REPORT, and CHART tables are. Additionally, each control has a print attribute as well, which you can use to exclude the control from the PDF.
Since PDF is static, the interactive elements of the form, such as buttons and delete controls, are not displayed.
Master/detail relation is preserved in the PDF; each record from the master table is printed followed by the records of the detail table. When creating a PDF output, paging is ignored (rowsPerPage) and all matching records are retrieved. This can be dangerous if a large number of records are retrieved.
Charts can also be included in the PDF. Since charts can be a detail table, multiple charts can be produced in the same PDF document, see Screen 35: Chart as a Detail Table.
The default page is A4 portrait. You can change it for the whole document at the <form> level using the attributes printPageSize and printPageOrientation.
You can start a new page at each <table> by setting attribute printOnNewPage to true. If you do that, you can also change the page size for the new page(s) (again attribute printPageSize) and orientation (printPageOrientation).
Screen 35: Chart as a Detail Table

PDF Forms
MetaWareJ can also fill PDF forms. PDF forms are PDF files which contain fields to be filled by the user. We use them when custom designed output is required e.g. quotations, proposals, financial reports, etc. You could create an invoice printout in PDF using normal XML screens, including company logo etc, but if a custom design is required then PDF forms provide more flexibility.
In MetaWareJ, PDF forms are filled by a specific servlet called PDFFormServlet and are associated with XML screens as usual. A call to the PDFFormServlet will look like:
PDFFormServlet?f=APP/form_filler.xml&do=REPORT&s_id_0=value
f=APP/form_filler.xml specifies the XML file to use.
do=REPORT is an action that signifies a non-interactive output.
s_id_0=value is an example of a parameter that needs to match the <argument> in the XML.
A PDF form must first be created using an external tool. It can be created using tools from Adobe or OpenOffice or LibreOffice. In LibreOffice, just create a document with form controls and then export it as PDF.
The form must have fields with names that match the control names of MetaWareJ. A control named “customer” of table “d” will fill a field called d_customer_0. Note that since the form is already formatted, we don't need any formatting information in the XML which servers only to create the buffer for the data.
The XML screen can be used to fill a single PDF Form. It can also reopen and fill a new form each time a table starts or reopen the form for each row of a table. This is defined by the startNewForm attribute of the <table>. All the filled forms will be concatenated in one PDF document.
The form file name itself is read from the database under the predefined column pdfform. The files are located under WEB-INF/docs directory of the application. Only the path after WEB-INF/docs must be included.
Lets clarify all these with an example:
<table name="d" function="DATA" startNewForm="EACHROW" buffer="true">
<recordset rowsPerPage="1">
<selectString >
select o.date_in, o.offer_no, ....
ifNULL(p.pdfform,'offers/offer.pdf') as pdfform
from project as p, offer o
where o.project_id=p.id
</selectString>
</recordset>
<controls>
<text name=”datein” dbname=”date_in” type=”DATE”/>
<text name=”offerno” dbname=”offer_no”/>
<hidden name="pdfform"/>
</controls>
</table>
This example assume two tables “offer” and “project”. It will print an offer document. One form will be created/filled for each row of table “d” as defined in startNewForm="EACHROW". All the forms will be concatenated in one PDF document. Since the filename is read from the SQL, a different PDF form can be used for each row.
When filling PDF forms, the buffer="true" attribute is necessary because the generator needs the value of the pdfform field before the rest of the data are used. The pdfform name should exist as a control, usually hidden.
The file is defined in the ifNULL(p.pdfform,'offers/offer.pdf') as pdfform which means a project has a field with the specific PDF form to use. The form defaults to offers/offer.pdf. The file will be opened from WEB-INF/docs/offers/offer.pdf.
The form itself must have fields to be filled. To fill a value for “Offer Number”, the form must have a field called d_offerno_0.

Advanced

How everything works
When a MetaWareJ application runs in a servlet container, it can accept HTTP requests either in “application/x-www-form-urlencoded” (or “multipart/form-data”) content type or in “application/json” content type. Two servlets are used one for each input:
FormServlet is the default and is reached under /FormServlet URL. It handles the “normal” web application requests.
JSONServlet is reached under /json URL and handles JSON formatted input.
The default configuration requires authentication before accessing either servlet. Form based authentication is configured in the default web.xml.
HTML
PDF
JSON
XML
CSV
MetaWareJ
Processing
FormServlet
action [ do= ]
FIND, NEXT
PREVIOUS, UPDATE
ADDSERVER, REPORT
etc.
JSON Input
HTTP Request
f= XML definition file
JSONServlet
Data Store
output=
Drawing 2: MetaWareJ Input, Processing, and Output
The basic URL format for a MetaWareJ application is:
http :// host : port / application / Servlet ? f=XMLfile & parameters
The first 4 terms are standard URL terms which depends on the local deployment environment.
Servlet is one of the defined MetaWareJ servlets, as described above.
f=XMLfile defines the XML definition file to use. The XML file 's path is relative to the WEB-INF/xml directory of the web application. So f=offers/customers.xml will open the file WEBAPP_APPLICATION_ROOT/WEB-INF/xml/offers/customers.xml where WEBAPP_APPLICATION_ROOT is the root path of the web application.
If an XML file is not given, the default XML file is read from the global.parameters file under key DefaultXMLFile or using the DefaultXMLFileProvider class.
The other important parameters are:
Parameter	Description
do	This is the action to perform. MetaWareJ uses predefined actions. The values are (values are case sensitive, “logout” is the only lower case action): <no action defined> - Performs a search if it can. We do a search if the main table does not have arguments or if all arguments are provided. If not, only the search table is shown. This is the action submitted from the menu links, usually. FIND – starts a search, tables are retrieved if the mandatory arguments are provided. REFRESH – does a search with current parameters and current page. FIND starts at page 1 while REFRESH remains on already displayed page. BACK – restores the context saved form the last form with saveContext=”true” and does a search with the restore search parameters NEXT – moves to the next page of records, as defined by the rowPerPage RecordSet attribute. PREVIOUS - moves to the previous page. GOTO – moves to the numbered page. ADDSERVER – Adds a new record using the RecordSetNew section of the table. UPDATE – updates the records in the database. COPY – Copies the displayed records. Records are first copied in memory, foreign keys are completed, unique keys are given default unique values, the records are updated in the database and then displayed. COPYREFRESH – Copies the displayed data as in COPY but re-retrieves the data from database so that all display rules are re-applied. IMPORT – Imports the uploaded file. Needs Servlet 3.0 implementation. REPORT – starts a non-interactive search. This means that paging (NEXT/PREVIOUS) is not done and all report data is displayed at once. This is used to create PDF reports for example. logout – logs out the user Example: http://localhost/?f=customer.xml&do=FIND
output	Defines the oupput to be produced. One of: NHTML – default HTML style HTML – an older HTML style PHTML – printable HTML format PDF – PDF report PDFFORM- for filling PDF Forms XML – XML formatted output CSV – tab, comma, or '|' separated text output CHARTPIE – Chart in Pie format CHARTBAR – Chart in Bar format CHARTMULTIPIE – Chart in multiple Pie format JSONLIST - Dynamic drop down controls for JSON clients JSON – JSON formatted data
s_s_0	Status of the search row. Needed if you want to simulate a FIND using a link. Usually setting to 0 [literal zero character] is enough. Example: http://localhost/?f=customer.xml&do=FIND&s_s_0=0&s_customer_0=5 This will submit a FIND action with a parameter customer=5. The s_s_0=0 is needed because it is used internally by MetaWareJ
The “MetaWareJ Processing” flow in box in the previous diagram is shown in the diagram below.
Read
Update
ServerDataReader
ServerDataWriter
Buffer
Database
Database
Datastore
Generator
Channel
has
channel
?
e.g. Subversion
respository
Modifies ClientData buffer
Read request
in ClientData buffer
Update request
in ClientData buffer
Processor
Creates Context
(MetaWareJContext)
action
?
Output
Stream
Drawing 3: MetaWareJ Processing

User Authentication
MetaWareJ applications are Java application generally running in a container. Java containers handle user authentication in various ways. The default MetaWareJ configuration uses FORM based authentication and provides a login.jsp to be used by the container to login.
When running on Tomcat MetaWareJ applications use by default JDBC Realm authentication. The user is authenticated using the REF_USER table defined in the default database, see Initial Database for diagrams and database description. The base application also comes with a screen to manage users. Point your application at URL “?f=users.xml” to get the screen.
Android applications authenticate the user by calling the server application
Swing and CLI also use by default the same authentication tables.

User Authorization
Each main menu, sub-menu and menu item can be associated with one or more user levels. A menu entry is shown only if the user has access, which means that different user levels can see different menus.
Screen 36: Menu and XML File Authorizations
A user has access to a menu item if his level is listed for that menu item. If that menu item has no authorizations entries at all then the parent menu entries are read (or sub-menu) up to the last parent level.
If no authorizations are defined in the menu hierarchy then access is allowed to all.
The administrator level has access to all menu entries. Otherwise, user levels do not inherit access from lower levels, i. e. level1 does not have access on entries of level2; it must be explicitly defined.
Examples:
If menu item “Customer” has a level2 authorization and the user is level1, the user does not have access.
Menu item “Customer” has no authorizations. If its parent menu “Entries” has a level2 authorization and the user is level1, he does not have access.
Menu authorizations go beyond showing/hiding the menu items. The menu authorizations are validated whenever an XML file is accessed based on the menu URL entry. As a result:
The user will be denied access even if he types the URL by hand.
[Caveat] All XML files need to have a menu entry even if they are not a menu item. For such files, we do not define a parent menu.

Custom Authorization
MetaWareJ allows you to define your own authorization scheme. The global.properties (see global.properties) entry AuthClass defines a custom authentication class to be used. The class must implement cy.com.methodosit.common.auth.Auth.
A class cy.com.methodosit.common.toys.NullAuth is provided if you need to have no authorization at all. So setting:
AuthClass=cy.com.methodosit.common.toys.NullAuth
in global.properties allows all logged in users to access all XML files.

Menu
Screen 37: Menu
A MetaWareJ application has a traditional menu. The menu configuration is saved in the database. This allows easier customization of the menu. It also allows the administrator to configure access to menu items. The menu has a maximum of two level sub-menus.
Menu items are in reality HTML links the URL of which point to XML file definitions. See Error: Reference source not found for more details. Most of the time an entry ?f=file pointing to the XML file is all that is needed.
The initial application (see How to create a MetaWareJ Application) comes with a predefined simple menu, together with the form to modify the menu and the menu authorizations.
Screen 38: Menu Editing Form
Each menu entry has a Type which can be:
Main Menu: Appears on the top level menu bar, e. g. The “File” main menu in the Screen 37: Menu above.
Submenu: Defines a one level sub-menu.
Menu Item: It is the actual menu item.
The other columns are:
Menu Name: This is a name that links main menus and sub-menus to menu items. It is also used as a command in the Command Line Interface, see Command Line Interface.Menu items need names only if you plan to use them in the Command Line Interface.
Label: Localized label to display, this is a key to a dictionary property file.
URL: See Error: Reference source not found for more details.
Parent Menu Item: Menu name of the parent of this menu item or sub-menu. Main menus do not have parents, of course.
Order: the display order within the menu or menu bar.
If a form must not show a menu then set hasMenu attribute of the <form> to false.

Multiple Application menus
MetaWareJ allows multiple applications to share the same database. The global parameter (see global.properties) ApplicationCode defines the currently connected application. This is used to retrieve the menu based on the REF_MENU.MODULE column. When you use the menu screen to add new menu entries, the REF_MENU.MODULE column is updated as well to the currently connected application.
As a special case, the value REF_MENU.MODULE 'ALL' means that a menu item will appear in all modules sharing the same database.

Auditing
MetaWareJ comes with application level auditing. “Application level” means that auditing is done as part of the application logic.
Modified data are written in the table ref_log, see Initial Database. This includes inserts, deletes or updates of records. When a record is updated only the actual data modified will be recorded.
An audit report rep_audit_report.xml is also included in the default application and it is available for the admin user.
There are five audit related attributes connected to the <update> element of the <table>. To enable auditing of a database table set the audit to true as shown in the code sample:
<table title=”project” ...
<update table="project" audit="true">
<column name="amount" parameter=”amount” />
<column name="user_code" parameter=”userCode” audit=”ALWAYS” />
<column name="very_long_descr" parameter=”notes” audit=”NEVER” />
...
<key name=”id” type="INT"/>
</update>
<controls>
<input name=”userCode” label=”userCodeLabel”...
...
This will insert one record in the ref_log table for each column updated/deleted/inserted. The table title and related control label will be recorded as well as the old and new values. In the sample code above and for the column user_code, audit will record table=“project”, column=“userCodeLabel” along with the before and after data.
If you need to record some other value instead of the table title and control label, the attribute auditLabel can be used at both the <update> and <column> elements to override the defaults.
By default, MetaWareJ saves key columns and modified columns in the audit records. If you want some column to be recorded always, because for example it will be easier to find what was changed, then you can add audit=”ALWAYS” to the <column>. You can also use audit=”NEVER” to prevent a column from being recorded. You can do this for very large or unimportant columns. The audit attribute takes three values ALWAYS, NEVER, and ONCHANGE. The default is ONCHANGE.

Logging
MetaWareJ uses the Log4j library. The initialization is done through a log4j.properties file, see log4j.properties.
The log level of some classes changes other aspects such as caching and appearance. See the Caching section for information on caching.
When the class cy.com.methodosit.common.html.Generator is set to DEBUG, the names of the XML <table> appears on the screen to help the developer. Also an Edit link is added so that you can enter the editor directly.
If you set the Logger named ApplicationMessages to DEBUG, normal application messages will be recorded in the log as well. These are messages created from data validations or any business logic that you add.
The Logger SaveDebugXML controls the creation of a debug XML file. If set to DEBUG, a fully expanded XML file will be saved for each form under the WEB-INF/xml directory with the ending _debug. This is very usefull when developing the application. The XML file you create can contain expanded table, templates, default headers, etc. The debug XML file is saved after everything has been expanded so it show exactly what MetaWareJ is running.

log4j.properties
It controls log4j logging. The file is located in WEB-INF/classes of the web application. Notable entries are:
# classes that affect performance because of caching etc.
log4j.logger.cy.com.methodosit.common.select.SelectModelFactory=DEBUG
log4j.logger.cy.com.methodosit.common.Meta.XML.DocumentPool=DEBUG
log4j.logger.cy.com.methodosit.common.html.Menu=DEBUG
# affect appearance of screens (titles)
log4j.logger.cy.com.methodosit.common.html.GeneratorNHTML=DEBUG
There is also a RollingFileAppender configured that it is needed by the default log viewer screen, see Logging.

Logging Management and Viewing
The default application comes with a screen that allows us to change the logging level of a class without restarting the application. Look under “Log Level management” menu. You should only change these if you know what your doing. Generally, loggers are based on the class hierarchy. MetaWareJ uses levels DEBUG, INFO, WARN, ERROR and more rarely EXCEPTION. You can change the “root” logger to DEBUG to get full log.
Screen 39: Log Level Management
There is also a screen to see the log entries under the “Log Viewer” menu. This allows you to search the log for specific lines or view the log after a specific line.
The “update” button forces the log to “roll”, i.e. the current log file is backed-up and a new log file is created. When viewing the log, the current log is first copied to a temporary file before searching. This can be slow, if the log is very big. For this we suggest you use the “Update” button first to clear the current log.
Screen 40: Log Viewer

Caching
MetaWareJ caches frequently used data and objects in memory to gain performance. Caching is turned off when the debug level of log4j for the class involved is enabled. This is done so that changes done during development are immediately visible.
What is cached	Where (under cy.com.methodosit.common)
Each XML file has a corresponding MForm object. MForm objects are cached once per thread because the parser is not thread safe.	DOM.DocumentPool
The menu is generated (in HTML form) once at the user login and is cached in user's session (SessionData). Normally the user will have to log-out and re-login in order to see any changes to the menu.	html.Menu
Any class that implements SelectModel interface can be cached in the SelectModelFactory. If the class stores the reference data ( e. g. jdbc.ReferenceTable) then the data are also cached. The objects are cached by the cacheKey() returned by the SelectModel. See also Dynamic Lists. The cache is cleared when a table with <update reference=”true” is saved.	select.SelectModelFactory

Command Line Interface
MetaWareJ applications can be run using a command line interface, under Unix and Windows, either on the command prompt/shell or in a scripting environment. This option can be used, for example, to automate report creation. All of the application options are available, however, and you could use the CLI to update your data if you wished.
To run a command go to the directory where the application is installed and run the metawarej.sh or metawarej.cmd. Note the lower case, if this is important to your environment.
You must always login in order to use it, even to see the command line options. You do this by entering:
metawarej.sh -u user -p password -help
The results will be:
-user (-u): user login
-password(-p): user password
-lang(-l): language
-url(-r): run from given URL
-menu(-m): main menu option
-menuItem(-i): menu item option
-action(-a): action to perform, one of REPORT, RUNTEMPLATE, FIND, UPDATE, etc.
Default REPORT.
-data(-d): sets data parameter input.
Value should be in form of table:control=value or parameter=value
Multiple arguments are allowed, as in -d s:name=k -d s:lastName=p
-output(-o): format to produce. one of PDF, HTML, XML, CSV, JSON. Default PDF.
-file (-f): name of file to save the output.
-f - (dash) means output to System.out.
Default is 'output' in current directory.
-help menu: show menu
Both the long and short form of the arguments are supported.
Lets give an example:
./metawarej.sh -u me -p myPassword \
-url f=myApp/someReport.xml \
-f report.pdf
This will run the report someReport.xml and produce a PDF file in report.pdf.
Alternatively, we can use the menu to run an XML file.
metawarej.sh -u me -p myPassword \
-menu reports -menuItem monthly \
-o monthly_report.pdf
This will run the menu item 'monthly' under the menu 'reports' and produce a PDF report in file monthly_report.pdf. This is equivalent to clinking the PDF button in the web application for the same menu item and saving the report in that file.
In order to find the available menu items, you can run:
metawarej.sh -u me -p myPassword -help menu
This will show an interactive menu, like this:
--------- MENU --------
1 : File [main1]
2 : Reports [rep]
0 : exit
The keywords in brackets are the menu commands that you should use for the -menu argument. You select a menu by entering its number in order to see the available items:
--------- SUBMENU --------
Analytical Report [report]
0 : exit
<enter> : back
Here the keywords in brackets are the commands that you should use for -menuItem argument.
Not all menu items are available for command line processing, only those that were given a “Menu Name”, see Menu. Since menu items normally don't need names, you should enable the options you want explicitly.
The -data/-d arguments allows us to enter data. Assuming the we have a screen with a search table with a control named customerId. If we want to produce the report only for customer with id 5, we can add -d s:customerId=5 to the command line.

Command Line Interface Setup
Command line interface needs these parameters in global.properties to connect to a database
JDBCUser=
JDBCUPassword=
JDBCdriver=
JDBCConnectString=
Additioanally, a file META-INF/login.conf with the default JAAS configuration must exist.

JavaScript Support
You can use JavaScript in your XML files either in the expression section of a table (see Calculated Fields) or as events of controls and the main form. In either case you can use the objects and functions defined in the MetaWareJ libraries. Take a look at the XML reference on how to create expressions and events.
MetaWareJ represents each table ( <table> listed in the XML definition) as a JavaScript object called dg. The dg object is defined in the loaded JavaScript file dg.js. A global associative array dgs holds a reference to each dg object which can be accessed by name. For example the search table 's' can be referred to as dgs['s']. As a shortcut (and to avoid multiple escapes in XML code) global variables of the form DGtablename also hold references to each table's dg object, for example the search table's variable is called DGs.
The dg object has members and methods to access and manipulate the data of the table. We will take a look at the useful methods below.
MetaWareJ also includes a set of utility functions to validate inputs and make useful common calculations. Some functions are defined using the user locale i.e. the server sends only the file containing the definitions appropriate for the user locale.
Additional JavaScript files can be loaded using the javaScriptFile element of the form element.

dg object methods
Methods of the dg object allow access and modification of the table data. Methods are called either using the dgs global array or the table alias. For example to call the method needsSave() for table 'd' we can call dgs['d'].needsSave() or DGd.needsSave().
Table data are organized in rows; the first row is number zero. Each row has the same controls (in a virtual column) which are referenced by name. The control name is the name defined in the XML definition of the screen. For example, dgs['d'].gv('id',1) will return the value of the control (or column) named 'id' on row 1 (the second row) of table 'd'.
dg objects keep track of the status of each row, i. e. if the row is modified or not, new, or marked for deletion.
dg objects keep track of the current row (called selected row). Several methods work on the selected row by default.
The dg object holds one col object for each defined control/column
getControl(controlName)	Returns the col object associated with the control named controlName.
getLast(controlName)	Returns a reference to the JavaScript object (as returned by document.getElementById()) for the control named controlName on the last row of this table.
getSameRowControl(obj,field)	Returns the a reference to the JavaScript object having id=field on the same table and row as obj control.
getRowCount()	Returns the number of the last row
getRef(controlName,idx)	Returns a reference to the JavaScript object (as returned by document.getElementById()) for the control named controlName on the row idx of this table.
gsr()	Returns the selected row number.
init(controlName,value)	If the control named controlName on the currently selected row is empty, it will be initialized to value.
srv(controlName,value)	Sets the value of the control named controlName on the currently selected row to value.
gv(controlName,idx)	Returns the value of the control controlName on row idx. return true/false for check boxes.
sv(controlName,idx,value)	Sets the value of the control named controlName on row idx to value.
gsv(controlName)	Returns the value of the control named controlName on the currently selected row.
ssr(newRow)	Sets and highlights the selected row to newRow. Row numbers start st zero.
checkOnlyOne(controlName,rowNum)	Un-checks all control name controlName on all rows except rowNum.
checkAll(controlName)	checks or un-checks the control named controlName on all rows.
nr()	Creates a new row. The new row will be the new selected row. Controls on the new row are initialized based on the XML definition of the table, either from a recordsetNew or the default attributes in the control elements.
sum(controlName)	Adds the values of the column name controlName on all visible and non-deleted rows of the table.
filter(parent,localColumns,parentColumns)	Handles master/detail tables in JavaScript. localColumns and parentColumns are arrays of control names on this and the parent table. Rows of this table will be visible only if all localColumns control values are equal to the corresponding parentColumns control values of the table name parent.
validate()	Validates all controls on all rows of this table. Checks data types, formats, masks, as well as mandatory values. Controls that have errors are highlighted but the validation continues for all controls. Returns false if any error are found.
needsSave()	Returns true if any controls is modified or any row marked as deleted.
getURL()	Creates a stings that includes all controls name and value pairs.
isDeleted(idx)	Returns true if row idx is marked for deletion.
isModified(idx)	Returns true if row idx is modified.
isNew(idx)	Returns true if row idx is new.
isRowVisible(idx)	Returns true if row idx is visible.
sort(field,hObj)	Sorts the rows of the table

Validation and Formatting
Global MetaWareJ functions that are used for formatting and validations. These are loaded from lib.js file and are not part of a dg object.
fd(dateV)	Formats and returns a date value. The argument must be a Date object.
fdt(dateV)	Formats and returns a datetime value. The argument must be a Date object.
fi(value)	Formats and returns an integer value. Formating is done based on the user locale.
fn_num(value) fn(value)	Format and return an decimal value. Formating is done based on the user locale. fn_num() accepts a numeric argument while fn() accepts a string.
mask(obj,valMask,dispMask) tmask(obj,valMask,dispMask)	Validates and formats the object. obj is a reference to an object as returned by document.getElementById(). valMask should contain one or more regular expressions separated by |. (see JavaScript RegExp for regular expression syntax.) Each pattern is applied to the value until one matches. If a dispMask is not “”, it should contain equal number of formating patterns. The corresponding formating pattern will be applied to format the value, i. e. if the third validation pattern matched then the third display pattern will be applied. mask() returns false if none of the valMask patterns matches. tmask() always return true. Example: The first pattern matches nnnn-nnnnnn with the -nnnnnnn optional. The second matches nnnn from one to 4 digits. Both patterns save the matching parts to be used in the display (as $1 $2) valMask="^(\d{4})-?(\d{0,7})$|^(\d{1,4})$" dispMask="$1-$2|$1"
m(obj){	Checks mandatory value. obj is a reference to an object as returned by document.getElementById().
vd(obj) tvd(obj)	Validates and formats the object value as a date. obj is a reference to an object as returned by document.getElementById(). Valid dates are (d is any digit): One or two digits are converted to date in current month (dd -> dd/CurrentMonth/CurrentYear) Day and month are converted to date in current year (dd/mm -> dd/mm/CurrentYear) Two digit year is converted to year after 1950, e. g. 60 converts to 1960 while 40 converts to 2040 (dd/mm/yy -> dd/mm/ year in [1950 -2050]) Full date (dd/mm/yyyy) vd() returns false if the object value is not a valid date. tvd() always return true.
vi(obj) tvi(obj)	Validates and formats the object value as an integer. Formating is done based on the user locale. obj is a reference to an object as returned by document.getElementById(). vi() returns false if the object value is not a valid integer. tvi() always return true.
vn(obj) tvn(obj)	Validates and formats the object value as a decimal value. Formating is done based on the user locale. Tow decimal places are left after formating. obj is a reference to an object as returned by document.getElementById(). vn() returns false if the object value is not a valid decimal. tvn() always return true.
compDate(a,b)	Compares the strings a and b as dates. returns -1 if a is before or equal to b.
compNumber(a,b)	Compares the strings a and b as numbers. Returns -1 if a is less or equal to b.
n(value){	Converts and returns the string argument to a decimal number. Conversion is done based on the user locale.
toDate(string)	returns a Date object from String based on the user locale
toDateTime(string)	returns a Date object from String based on the user locale. String is datetime formatted value.

Utility function
calcAge(tableName,idx,date1,date2) calcAgeToday(tableName,idx,date1)	Calculate the age. Age is the number of whole years passed at the last birthday. calcAge() calculates between any two dates while calcAgeToday() until the current date. Both methods read values from controls (named date1 and date2) on table name tableName at row idx.
checkOnlyOne(obj, bObj)
c(obj)	Marks object obj as modified and recalculates all expressions.
getDisplayedValue(obj)	For select controls it returns the displayed label of the selected option. For check boxes it returns “Checked” or “Not Checked”, etc.
getSameRowControl(obj,field)	Returns a reference to a control named field on the same table and row as obj
getValue(obj){	Returns the value of obj (even for controls that don't have a defined obj.value attribute in JavaScript)
gv(tableName,columnName,idx)	Returns the value of control columnName on table tableName on row idx.
clickLink(tableName,linkName,row)	Clicks the link at (tableName,linkName,row)
rc(){	Recalculates all expressions.
sameRowSetValueIfMT(obj,field,value)	Sets the value of controls name field on the same table and row as obj, but only if it is empty.
sameRowSetValue(obj,field,value)	Sets the value of controls name field on the same table and row as obj
setValue(obj,value)	Sets the control value (even for controls that don't have a defined obj.value attribute in JavaScript)
showtab(tab)	Raises the tab page called tab
ssr(obj)	Finds, selects and highlights the row of the table where obj belongs.

How to use the MetaWareJ XML Editor
MetaWareJ includes a tool to help you create the XML form files.
This can be accessed through a URL as:
http://localhost:8080/APPLICATION/?f=editor/editor.xml
If you created the application using the initial database script, then the default menu has the option to enter the “XML Screen Editor”, if you logged in as admin.
Screen 41: Initial Application Menu
Before using the editor you should create a new property file devel.properties under the webapp/WEB-INF/classes directory of your application source directory, or under the local directory. This can have two entries:
The DevelopmentDir key defines the root path of your project. If you set this property, the XML files created by the editor will be saved under webapp/WEB-INF/xml directory of your project as well as the deployed application. If DevelopmentDir is not defined, files will be saved where the web application is deployed and you will have to copy them to the project yourself.
The PDMFile points to a PowerDesigner file of you db (if you use this tool). This will assist the editor assign domains to controls, etc. PDMFile must be the full path of the file.

The Fast and Easy Way
To create real life complex business applications you will need to read at least chapter Your first MetaWareJ application: A tutorial and understand what are the MetaWareJ XML files and how MetaWareJ works. But in order to create a form, even a complex one, you can do the following:
Design and create your database
Create a MetaWareJ application from the base application.
Enter the editor as explained above.
Using the editor form in Screen 42: Initial editor screen enter the Filename (example demo/myInvoice.xml), then click on the “Add Multiple” button of the Database Tables and select the database tables you want the new form to manage, see Screen 43: Editor database table selection .
Then click the “Create From” button on the top toolbar. The editor will then analyze the database tables and create a form to manage them. The editor will create master/detail relationships, filters, key checks, add buttons as needed, etc. This might take a few seconds. After it is done you will be left in the editor screen on the Form tab, where you can click the provided link to see the created form in action.
Screen 42: Initial editor screen
Screen 43: Editor database table selection
MetaWareJ comes with a PowerDesigner base physical model which has the minimum tables needed, see Initial Database. It also has named domains for various data types and use cases. The domains found in this model correspond to control templates already created in the control.xml file. The editor will use the information in the PowerDesigner file to assign the appropriate control template. It will also use the design to fill-in some additional information such as referential integrity checks.
The mapping from physical model domains to MetaWareJ templates should be used as part of the design methodology. We suggest the following:
Create your own physical model implementing the provided base.pdm and try to use its provided domains as much as possible.
Create your own domains when the existing are not sufficient. For each new domain, create the appropriate control in the application level control.xml.
Use the editor to create the forms and associate the forms with the physical model.

Creating a new XML form
To create a new form, go to the URL above. The editor Search screen appears. Enter a new “Filename” and click “Add New”. The file name should be entered as APPLICATION/newfile.xml where APPLICATION is the name of the application.
The editor works on one <table> at a time. It has one tab page for the <form> attributes, a second one to set the <table> attributes, and one tab to handle each main element of the <table>.
To select a table of an existing form use the search button. A list of existing tables allow you to select the table to edit, see Screen 44: Selection of existing tables.
Screen 44: Selection of existing tables

The form
Screen 45: Form attributes in the editor
The form properties are shown above. The description of each can be found in the XML reference.
The form can be run/tested by using the “Test” link provided.
The “Title” property is a key to the dictionary property file (or files) as are all labels, titles and help information, see Localization. At the form level a new dictionary could be created (one per form or one for the application). The file name can be entered in the “Additional Dictionary File”. The property files must be created under the WEB-INF/classes of the application.

Table Properties
Screen 46: Table Attributes
The table attributes are shown above. Again look at the XML reference for full description.
Table “Order” defines the relative order of a table in the form. Usually this is the physical order of the tables, e. g. Search tables first, followed by master data tables, and detail tables last.

Retrieval Information
Screen 47: <resordset> Attributes
The “Retrieval Information” tab holds information that corresponds to the <recordset> element.
The first part Screen 47: <resordset> Attributes holds the “Rows per page” attribute which limits the number of records displayed and adds Next, Previous and Goto page buttons.
The second part holds the select statement. More than one row can be added here, in which case, each “select” will be added to a Union statement.
Screen 48: Select Statement
The next part can be used to add the arguments which corresponds to the <argument> element of the <recordset> ,see Screen 49: Arguments. The columns correspond to the attributes of an <argument> element, see reference.
Screen 49: Arguments
The “Add Multiple” button allows us to create arguments from controls on other tables.
The workflow sequence should be:
Create the “Search Table” with the appropriate controls
Create the data table.
Add the arguments of the data table by clicking “Add Multiple” and selecting the controls of the Search table as shown in Screen 50: Selecting Arguments from Other Controls of a Search Table.
Screen 50: Selecting Arguments from Other Controls of a Search Table
The last part creates the <column> elements which are used to create user defined reports. See Reports and Charts using optional controls.
Screen 51: <column> elements
The “Add Multiple” button can be very useful because it will list all the optional controls of this table from which to create the columns. If you read Reports and Charts using optional controls then you will know that we need one <column> element for each optional controls.

Controls
Screen 52: Selecting Controls
At the Controls tab hit “Add Multiple”. A selection window will be open listing all the database columns produced by the select statement. Assuming we are using a PowerDesigner physical model, the “Template Name” column will filled as well.
Screen 53: Controls and Templates of the Form
Once the controls are created, any control property can be changed. Template controls can override limited properties of the base control. See the reference.
Controls can also be added directly by using the “Add” button

Update
After the controls, we are ready to add update information. The “Add Multiple” button will allow us to select which controls to update.
Screen 54: Selecting Controls to Update
New columns can also be added manually, if needed.
All the integrity constraints found in the PowerDesigner file will be automatically copied to the editor's Checks window when we update:
Screen 55: Foreign Key Checks

Buttons
Screen 56: Button Attributes
The final piece we need are buttons. We can add them in the Buttons tab. Usually all it is needed is the Button type.

Master / Detail – The Filter
Screen 57: Adding a Filter
A master/detail relation between two tables can be created in the Table tab.
Open the detail table in the editor.
On the Table tab find the “Filter” property and select the master table.
Save the form
Go back to the Table tab and add one or more Filter rows selecting the join between the master and detail tables.

Reference Information

global.properties
Global properties define application parameters that generally should not be changed by a user or an administrator of the application. These properties are defined in the global.properties file that lives under WEB-INF/classes. Properties can also be defines using the -D java argument in the usual way, e.g. -DAuthClass=someClass. They can also be defined in the ref_parameter database table, if such a table exists. The order is system property (-D), ref_parameter table, and last global.properties file. Global properties are read only once per application. You need to restart/reload your application for any changes.
The class GlobalProperties should be used to access this file, should you need to, which should be never.
(all class names are under cy.com.methodosit.common.)
Parameter	Default	Remarks
Application	none	Name of the application to display on the application window. It is looked up in the dictionary.
ApplicationCode	none	Application code. Used to define the application module the user connects. Used in the default menu retrieval.
AuthClass	jdbc.Auth	Class that authorizes access to the logged in user to each XML file. It must implement auth.Auth. The default uses the REF_MENU_LEVEL table in the database. See Creating Initial Database.
ButtonsAppearance	ICON	Show buttons as images (ICON) or traditional (TEXT).
CSRF_ProtectionLevel	error	Handles Cross Side Request Forgery attempts as well as resubmission of old forms through the browser's history. If error, such a request will be handled as error. If warn, a warning will be shown to the user and he will be allowed to resubmit. If none, the protection will be disabled. This can be used in secured environments if there is a benefit in allowing the users to use the back button.
DefaultServerType	JDBC	The default database or other backend type, Default is JDBC. Can also be: JSON – use JSON to comunicate with MetaWareJ application on a server, need to set JSON_URL as well. AndroidSQLite – use custom SQLIte database on Android
DefaultOutputType	Depends on entry point. NHTML for web applications.	The output to show by default. HTML, BHTML, NHTML, PDF etc.
DefaultXMLFile	none	Default XML file to use
DefaultXMLFileProvider	none	Class implementing the Meta.DefaultXMLFileProvider interface and which provides the default XML file to open. Either this or the DefaultXMLFile should be included in the global.properties. This class can be used, for example, when the default XML file depends on the logged in user.
Dictionary	none	Application level dictionary to use.
HeaderFile	file called header.xml in the same directory as the processed XML file	Holds the table to be added as header in all XML form files. All tables from this file will be added on top of the current tables.
InitSessionDataClass	DefaultStaticData	This class is used to initialize user related static information such as user name, company, etc. It must implement StaticData. If set to “none” then it will not be initialized.
InitSessionXMLFile	userData.xml	XML file to be used by DefaultStaticData to initialize the user session.
JDBCConnectionName	jdbc/MetaWareJ	The JNDI name to look up to retrieve a DataSource object. The name is a JNDI name relative to the java:comp/env context. In Tomcat, this the resource name of the DataSource in context.xml and also the resource-ref name in the web.xml for the same resource.
JDBCConnectionPoolDisabled JDBCUser JDBCUPassword JDBCdriver JDBCConnectString	false	Alternative connection parameters. Used for non-web clients (Swing, Android) and for testing. When JDBCConnectionPoolDisabled is set to true the ConnectionPool class connects/disconnects from the database using the rest of the provided properties instead of using the connection pool.
JDBCDisabled	false	When true, the default database connection will not be attempted. Alternative implementations for MenuData, DefaultStaticData and Auth must be provided in this case.
JSON_URL		URL of the application, Either https or http can be used. The final /json is added automatically. Example: https://www.methodosit.com.cy/offers
Lang	el	Default application language. Changes the labels, titles, etc.
loginHasRegister	false	show “create account” link on login screen
loginHasForgotPass	false	show “Forgot Password”
Locale	el	Default application locale. Changes date and number format.
LoginClass	DirectLogin or JSONLogin	Login class to use for stand alone clients, e.g. android. When running in a container, the container handles authentication so this is not used. Use only when a stand-alone client has special login requirements.
LoginDatabaseURL	none	Database connection URL for alternative login. For application that login with specific user.
LoginModuleConfigurationName	jdbcLoginModule	JAAS LoginModule configuration name. This name should exist in the login.conf file under META-INF directory.
loopSeconds	0	Used by Batch/BatchJob. It is the number of seconds the BatchJob.execute() methods will be executed. -1 means never 0 means execute only once n means every n seconds
mail.smtp.host		Host name of the outgoing mail server.
mail.smtp.port		Port to use for the server above.
mail.smtp.user		User to use to send email.
mail.smtp.password		Password for user above.
mail.smtp.auth.ntlm.domain		When connecting to an Exchange server with NTLM authendication, the domain name to use.
MenuDataClass	MenuData	The name of a class that extends AbstractMenuData and provides menu data. The default is MenuData which reads the menu data from the database using the menuDataAdmin.xml and menuData.xml. See Creating Initial Database. none means no menuDataClass but, depending on the user interface, a menu might still be created. Use <form hasMenu=”false” to remove the menu.
MenuAdminXMLFile	menuDataAdmin.xml	XML file to be used by MenuData to get the menu structure for the administrator user.
MenuXMLFile	menuData.xml	XML file to be used by MenuData to get the menu structure for normal users.
MessageDigestAlgorithm	SHA-256	Algorithm to use for hashing passwords. 'plainText' disables encryption
NeedsAutoCommit	false	ConnectionPool will call setAutoCommit() if this is true.
OutputLimitMB.HTML		Limit in MB of the HTML output to be generated. When set, if the output exceeds the limit, the output stops and any error message is sent to the user.
ShowExportCSV	false	Show “Export in CSV” button.
ShowExportXML	false	Show “Export in XML” button.
ShowExportPrint	false	Show “Printable format” button
ShowExportPDF	true	Show “Export in PDF” button.
ShowTotalPages	false	Show total number pages when showing Netx/Previous buttons
ShowFullExceptions	false	Show full stack dump to the user when an unexpected exception occurs
SMS.CYTA_URL		The full URL for CYTA web SMS service, see https://www.cyta.com.cy/mobile/misms/docs/WebSmsApiGuide_en.pdf for details
SMS.CYTA_KEY		Key for CYTA web SMS service
SMS.CYTA_USER		User login for CYTA account. Note that this is different from the “Sms Sender”
SSLClientCertificate		Used in JSON clients. If the protocol of the JSON_URL is https and the server needs a client certificate. This is the file name of the client certificate in PKCS12 format. The file should be placed under /WEB-INF/data/ directory. Only the name of the file should be entered here.
SSLClientCertificatePassword		Password for the client certificate above.
SSLRootCertificate		Used in JSON clients. If the protocol of the JSON_URL is https and the server uses a self-signed certificate. This is the file name of the root CA certificate in PEM format. The file should be placed under /WEB-INF/data/ directory. Only the name of the file should be entered here.
SVN_BASE_URL		Subversion URL to access the document repository. In the subversion format, e.g. file:///somePath or svn://hostName
SVN_BASE_DIRECTORY		The root directory under the version control that MetaWareJ will access. This allows using the same repository both for MetaWareJ application and other uses. For SVN_BASE_URL= file:///somePath and SVN_BASE_DIRECTORY=someDirectory the subversion client will check-out and use the URL file:///somePath/someDirectory.
UseAutoIncreament	false	When false, update columns with auto=”true” attribute will get their values from ref_counter table, using Counter.manual() method. If true, they will get their values from the database after insert. The database column should be auto-increment and the JDBC driver should support the Statement.getGeneratedKeys() in this case. In case of Oracle, MetaWareJ will user a sequence to create the key. The sequence's name must be 'TABLENAME_seq'.
UseRefParam		Use ref_parameter table when initializaing global parameters

XML definition language
We have seen examples of how the XML definition creates both the user interface and the database interaction. Here, we will describe the main elements of the XML definition language.
The XML language is defined in an XML Schema file called Form.xsd which is delivered in the root of the web application directory. A full reference can be seen from any MetaWareJ application by pointing a browser to :
http://host/APPLICATION/Form.html
The root element of the XML is <form> which describes one screen. Each form has one or more tables in <table> elements. All data in a form are retrieved and, more importantly, updated together in a single transaction.
Tables define a set of data, the method to retrieve and update that data and controls to display them.
A table has a function which defines the table's purpose. Function can be SEARCH, DATA, REPORT, CHART, REPORT_CHART. A SEARCH table is used by the user to enter search criteria. It has no update or retrieve capabilities. A DATA table handles the processing of data, that is retrieval and update. The rest are for display only .
The <table> has five main elements:
the <filter> defines the relation of the table to a parent table on the same form,
the <recordset> which defines how data are read,
<update> which defines how data are updated,
<controls> which has a set of controls, and
<buttons>

Initial Database
The initial database has tables for users and roles (groups, levels or whatever you want to call them), the menu, the audit table, parameters and some internally used tables for saving reports.
In brief:
Table	Description
ref_user	One row per user.
ref_level	User levels. Role with code 00 is the administrator.
ref_menu	Menu data. See Menu below on how to manage it.
ref_menu_level	Menu access and XML authorizations, see User Authorization.
ref_counter	Used for automatic creation of sequence numbers (primary keys etc).
sys_singleton	System and installation description. Its data appear on every screen header.
templates templates_param templates_colsel	Saved reports. See Reports and Charts using optional controls.
ref_log	Audit log table
ref_parameter	Global application parameters that can be changed by the administrator. Parameters with id <1000 are reserved and do not appear in the provided screen.

Application Structure
MetaWareJ application structure is that of a Java web application with some additional structure. The structure of the web application is listed below. The column “Implemented by developer” identifies the items that are created/implemented by the developer.
PATH	Description	Implemented by developer
/	Form.xsd and base.css
/js	MetaWareJ javascript files
/js/APPNAME/	application specific JavaScript files	yes
html	static html
images	images
META-INF	Tomcat's context.xml or other application servers configuration	yes
WEB-INF
WEB-INF/xml	Common Screens (menu, users, etc) and global control templates (controls.xml)
WEB-INF/xml/APPNAME	application level screens and controls (controls.xml)	yes
WEB-INF/lib	3rd party libraries such as iText, jfreechart and log4j
WEB-INF/docs
WEB-INF/docs/APPNAME	application level files and forms (PDF)	yes
WEB-INF/fonts
WEB-INF/classes
WEB-INF/classes/dictionary.properties	global dictionary (also _el _en for Greek and English)
WEB-INF/classes/APPNAME.properties	application dictionary (also _el _en for Greek and English)	yes
WEB-INF/classes/cy/com/methodosit/common	MetaWareJ classes
WEB-INF/classes/cy/com/methodosit/APPNAME	Application classes	yes

images.properties
Holds the names of the images used at various places in MetaWareJ.

Caveats
All XML files need to have a menu entry even if they are not a menu item. For such files, we do not define a parent menu.
A control's name must not contain the underscore character “_”.
A control (which is optional) and a recordset column must have the same name.
When creating a PDF output, paging is ignored (rowsPerPage) and all matching records are retrieved. This can be dangerous if a large number of records are retrieved.
When filling PDF forms, the buffer="true" attribute is necessary because the generator needs the value of the pdfform field before the rest of the data are used. The pdfform name should exist as a control, usually hidden.
so don't forget the labels when defining the columns attribute
Note that setting the dbname as empty string will not work, because the default for dbname is the control name.
Not all menu items are available for command line processing, only those that were given a “Menu Name”
In nested reports with buffered=false, since the data are not buffered we must make sure that the sort order of the master table matches the sort order of the invisible table.
Remember to change the row status when modifying data; MetaWareJ will not do that automatically.
sourceURL= should not be used on a <table function="FRAME"> that it is linked to a link control, because it will cause it to be loaded twice.
Page 127 18/04/2018