Makumba Specification

$Revision: 1.3 $

OLDSTYLE features that are still accepted for     y are presented in darkblue
INTENDED features are presented in red

Content:

Data Definition Language
     - Types, objects, databases
     - Fields
     - Default fields
     - Simple field types
     - Structural (relational) types
     - Macro types
     - Field attributes
     - Object title
     - Include mechanism
OQL language
Business Logic
     - Attributes
     - Java Handler classes
     - Login , <mak:login>, <mak:logout/>
Presentation and internal representation principles
Presentation with JSP taglib
     - <mak:list>
        - Attributes and OQL in <mak:list > and <mak:object >
        - <mak:value/>
        - <mak:attribute>
     - <mak:object>
     - Forms
        - <mak:newForm>
        - <mak:addForm>
        - <mak:editForm>
        - <mak:form>
        - <mak:input/>
     - <mak:deleteLink/>
     - <mak:response/>

Data Definition Language

(the Makumba abstract level)

Types, objects, databases

Data definitions describe data types (or classes). They are placed in files contained in directory hierarchies, and the directory name is part of the type name (similar to Java packages). For example the file best/Student.mdd describes the type best.Student. Type names can contain letters, digits, underscores and dashes and cannot contain slashes and dots. Usually, the directories are used to separate organisations and projects.
Note: current Java implementation finds the data definition files as follows:
Data objects (records) are stored in databases.

The actual implementation of the database is not part of this specification but implementation suggestions will be made. Data can be copied or replicated between different databases.

Note: replication is not yet implemented, but the design is prepared for it

Fields

Every data definition file contains field definitions, separated by newline.
Note: there will be another separator, to accomodate for more fields defined per line
A field definition looks like:
fieldname= [attributes] fieldtype [parameters] [; description]
Note: default values are supported internally, but not by the parser

Note: this might change like this in the future

fieldname: [attributes] fieldtype [parameters] [; description]
Note: as an implementation guideline, field names use to stay approximately the same in:
  • http requests
  • Record instances (java.util.Dictionary in the current Java API)
  • database columns
  • etc
  • The field description is used at interface levels to present that field. It is typically shown at the left of, or somewhere near to, the input control (text box, radio button, chooser, etc) that allows for data input in that field. If a field description is not present, its field name stands for its description by default.

    Comment lines can be inserted in the data definition files as follows:

            # comment

    Default fields

    Every type has some default fields, as follows:

    Simple field types

    int

    A 32-bit integer. For example
    shoeSize= int; Shoe size
    If the int can have a limited number of values, it can be described as follows
    gender= int{ "male"=0, "female"=1 }; Sex
    This will help the presentation layer to present a suitable input control (e.g. a HTML SELECT)
    Note: in the present implementation, this type is called "intEnum" internally

    char

    A char field contains a number of Unicode characters. It has a limited width. Maximum, and optionally minimum number of characters can be indicated. For example
    name= char[80]; Username
    password= encrypted char[6..10]; Secret password
    "encrypted" is a field attribute, it will be explained below.

    If the char can have a limited number of value, it can be described as follows

    gender= char{ "male", "female" }; Sex
    This will help the presentation layer to present a suitable input control (e.g. a HTML SELECT)
    Note: in the present implementation, this type is called "charEnum" internally

    text

    An unlimited-length string of bytes or Unicode characters. This type was designed to accomodate large text or binary content. It is implemented with LONGVARBINARY or its counterparts.
    application= text; Application letter
    image= text; Picture attachement

    date

    A date and/or time.
    birthdate= date; Date of birth
    arrivalTime= date; Arrival time

    Structural (relational) types

    Pointers (ptr)

    Pointers define a reference to an object of a certain type. For example
    citizenship= ptr general.Country; Citizenship
    Note: the ptr keyword might be ommitted in future parsers
    The type can be defined on-the-spot for a single usage. For example
    addres= ptr ; Address
    address->street= char[80]; Street
    address->number= int; Number

    Note: future parsers might read this:
    address= ptr{
        street= char[80]; Street
        number= int; Number}; address
    Note: this type is known internally as ptrOne

    Sets (set, bag, list)

    Sets define a number of references to multiple objects of a certain type. For example:
    language= set general.Language; Spoken languages
    This type accomodates sets, bags and lists. The set and list constraints (sets have to contain only one element of a certain value and lists have to be ordered) have to be cared for by the programmer. Lists are easy to represent, just having an integer field, for the order.
    place= set int {"home"=1, "away"=0} ; Home or away
    Note: this is currently known internally as setintEnum
    place= set char {"home", "away"} ; Home or away
    Note: It means that place is a set that can take only the "home" and "away" values. This is currently known internally as setcharEnum
    The type which the set is made of can be defined on the spot:
    addresses= set; Addresses
    addresses->street= char[80]; Street
    addresses-> number= int; Number

    Note:  the future parser might recognize this form:
    addresses: set{
        street: char[80]; Street
        number: int; Number }; Addresses
    Note: this type is known internally as setComplex

    Macro types

    A name can be defined for a more complex type and it can be reused in the file. This can be done with a !type directive
    !type.yesno= int{"yes"=1, "no"=0}

    Field attributes

    Note:  currently only field attributes fixed and not null are working (and the current parser only recognizes fixed and notnull)

    Object title

    One of the fields is always the object title, and is normally presented differently from other fields in user interface . This is the "name" field if it exists, otherwise it is the first non-pointer field in the record description. If another field needs to be title, it can be specified like
    !title=gender

    Note: for the on-the spot types in the current implementation, the following notation works:

    address->!title= street

    Include mechanism

    A record description includes text from one or more files. This is declared as
    !include=name_of_included_type
    The included file has the idd extension and is found in a similar way with data definitions.

    The included file is inserted instead of the !include line. There can be more include lines in a record description file.  If a field is defined that exists also in the included metadata, the defined field takes precedence. If

    fieldname=
    it means that it does not actually exist. this can be used to cancel an included field.
    Note: include might be replaced by more advanced concepts such as inheritance and type inclusion (rather than reference in foreign table)

    OQL language

    The database can be interrogated using the following language ( [] means optional, {} means any number of repetitions). OQL is similar to SQL, a specification can be found at  http://www.odmg.org . Makumba recongizes a subset of OQL at the moment, which it translates to the host SQL when necessary.
    SELECT expression [[AS] label] {, expression [[AS] label] }
    FROM {type [AS] label | label.field{.field} [AS] label }
    [   WHERE expression
        [    GROUP BY expression {,expression}
            HAVING expression {,expression}  ]
        ]
    ]
    [ORDER BY expression {,expression} [(ASC|DESC)] ]
    Notations like label.field{.field} only allow "field" to be of pointer type in expression and set type in FROM.
    If a label appears alone in an expression, a default field will be added. The default field depends on the type of the label:

    Business logic

    Attributes

    Attributes keep the read-only state of a makumba task. They represent the "environment" of that makumba task. The typical example is a JSP page during execution, with its HTTP and session parameters as attributes. Since other kinds of attributes are possible, the attribute specification is kept HTTP-independent. Makumba code sees the attributes as an org.makumba.Attributes object

    Java handler classes

    Java handler classes are classes that implement the "business logic" of the organisation. Every makumba page will look for a handler, and will call its methods when needed.

    Handler Discovery
    is done at first access after a page is recompiled. For example, with the page path /student/mycv/indexPersonal.jsp, the following criteria are applied, in orer:
    criterium Java classes checked for
    page name StudentMycvIndexPersonalLogic
    caps parts of page/directory  name StudentMycvIndexLogic
    directory name StudentMycvLogic
    parent directory name(s) StudentLogic
    Logic

    The class name prefix can be regulated per parts of the site in a file called MakumbaController.properties which can be found in the CLASSPATH (just like MakumbaDatabase.properties). For example, the file can contain:

    /student=org.eu.best
    /makumba=org.makumba
    /=test
    path Java classes checked for
    /student/mycv/index.jsp org.eu.best.MycvIndexLogic
    org.eu.best.MycvLogic
    org.eu.best.Logic
    /makumba/tests/x.jsp org.makumba.TestsXLogic
    org.makumba.TestsLogic
    org.makumba.Logic
    /some.jsp test.SomeLogic
    test.Logic

    There are good reasons to take into account the name of the response page of a form when looking for the business logic. Still, it is the name of the page that contains the form which matters. It is good practice for both pages to actually have the same handler class.

    All methods of the handlers are http-independent. Methods are non-static, so inheritance can be taken advantage of. Still, handlers are singletons (only one of a certain class in a JVM, if the class changes on disk, the handler object might be rebuilt). For example, the validation of a form can be in a class that is closer to the actual JSP application (view level) while the more view-independent methods can be in the parent of that class. For example:

    org.eu.best.minerva.StudentHandler extends org.eu.best.StudentHandler

    Role of Java handlers:
    1) find attributes unknown by pages. e.g.
    <mak:object from="best.Student stud" where="stud=$student"> ...</mak:object>
    If the $student attribute is not known in the page (from a http argument) or in the session, the find{AttributeName}(Dictionary existingAttributes, Database d, String expression) method is called for the Handler object. In this case findStudent(). The handler has to compute the attribute, based on existing attributes, making DB accesses.

    for example "lbg.$lbg_order" above, will generate a call
    findLbgOrder(otherAttributes, db)
    and the Java handler will return the default odering for LBGs (say "name").

    If the attribute is computed susccesfully, it is associated with the session

    If not, an exception will be thrown (typically UnauthenticatedException), and the engine will act accordingly (i.e. ask for authentication).

    2) execute action methods in response to makumba forms. See makumba forms and actions below.

    3) later: return query parts, as methods. e.g.
    <mak:value expr="lbg.$title()" />
    will generate a call to
    methodBestInternalLbgTile(lbg)
    which can return an OQL expression "concat(lbg.id, \"-\" lbg.name)"
    (such methods can be put directly in the Mak data definitions)
    (for now, OQL only accepts count() and sum(), but that can be easily fixed, till then, the method can be replaced by hand:
    <mak:value expr="lbg.id"/>-<mak:value expr="lbg.name"/>
    )

    Handler Initialization
    Whenever a handler is used in a new context (i.e. with a different set of attributes, e.g. a new page access), a method called checkAttributes(Attributes a, Database db) is looked for and executed, if it is defined.
    checkAttributes can perform sanity checks for attributes used in the respective logic (in case of mismatches, org.makumba.UnauthorizedException is usually thorwn), can load attributes that are absolutely needed for page execution (formerly given by the requiredAttributes()  method), etc.

    Login.

    Login is done as a result of a missing attribute (possibly invoked in checkAttributes), when a findXXX method is called. The missing attribute is the principal that needs to log in.

    If the attribute cannot be found due to wrong login information, org.makumba.UnauthenticatedException is usually thrown.

    The principal can have more members (e.g. group, Lbg, Company representatives). E.g. the findCompany() method will check to see if the authentication (email_address and password) corresponds to any company representative of that company. If yes, it will return that company.

    Login can be done in 2 ways:
    1)Http login: will set the attributes $username, $password
    2)cookie login: done in a page called login.jsp, in that dir or in any of the parents. It should conain at least:
    <mak:login>
    <input type=text name=username>
    <input type=password name=password>
    <input type=submit>
    </mak:login>

    The login form will pass further (as hidden arguments) all the http parameters it got. Note that <mak:login> is only needed upon automatic login (a page displayed when the user requested another page, that needs authentication). If you wish to ask for login manually in a startup page, a normal HTML form is enough.

    To cancel out a certain attribute, in order to produce a new login, the logout tag is available

    <mak:logout actor="student"/>

    (later on, automatic logout request might be done by the business logic, such as with a method deleteAttributes() that can return "*", a String or a String[])

    Later: to accomodate servers that don't do session tracking, login can be done by a query condition rather than by doing a query (once per session) to find an attribute. This way, it won't need to do a query (to check the authentication) at every access, but that condition will make sure that authentication is done.

    <mak:object from="best.Student stud" where ="stud.$login()"> ...</mak:object>
    then methodBestSudentLogin("stud") will return
    "stud.auth.email=$username AND stud.auth.password=$password"
    This can be used for http authentication with no session tracking.

    Later: if an attribute has multiple values, a choose{AttributeName}.jsp page is shown. For example, a super user (for that area) can choose to act as any student, Lbg, or company... A student member of more local Vivaldi teams can choose to act for any of the viv teams, etc.

    Presentation and internal representation summary

    This table describes the data types and their default user interface representation. That user interface can be altered with the Presentation language described below. Orientative SQL and Java types are presented.
     
     
    Data definition type Default user interface Relatioal database type (orientative) Java type (orientative)
    type (table) list of records, with add, delete, edit controls; titles emphasized table
    record all fields, as shown below record java.util.Dictionary
    int  text field or slider integer java.lang.Integer
    int{}  simple choice or radio button
    char[]  text field limited char java.lang.String
    char{} simple choice or radio button
    text text area 
    or upload
    unlimited byte org.makumba.Text
    date date date and time java.util.Date
    ptr  link to the pointed record preferrably a long org.makumba.Pointer
    xx=ptr
    xx->...
    the record, if any preferrably a long 
    + table
    Index field (nothing) preferrably long, 
    autoincrement, or other unique
    creation date 
    modification date
    date, not editable timestamp java.sql.Timestamp
    set  multiple choice of record titles table with ptrRel to the parent table and ptr to the foreign table java.util.Vector of org.makumba.Pointer
    xx=set
    xx-> ...
    like a table, under corrent record  table with ptrRel to the parent table, and the rest of the fields
    set int{ ...} multiple choice from values table with ptrRel to the parent table, and an int field java.util.Vector of java.lang.Integer
    set char{ ...} multiple choice from values table with ptrRel to the parent table, and an int field java.util.Vector of java.lang.String

    Presentation with JSP taglib

    Data can be presented and adjusted per record and field. The current presentation language uses JSP taglibs and corresponding notation, but principles can be applied in any other HTML-centric presentation language such as PHP

    Makumba tags are written according to Servlet 2.2 specification and JSP 1.1 specification. The corresponding WEB-INF/web.xml and WEB-INF/makumba.tld can be found in the distribution.

    <mak:list...>...</mak:list>

    Displays query results. Queries are generated on the spot. Queries can be nested.
    Example:
    <mak:list from="best.Student s" where="s.gender=\"male\"" orderBy="s.name"
        countVar="counter" maxCountVar="number">
    <% if(counter.intValue()==1) {
    %> There are <%=number%> students: <p> <%}%>
        <%=counter %>.
        <mak:value expr="s.person.surname"/>
        <mak:value expr="s.person.name"/> <br>
        <mak:list from="s.person.addresses a">
            <mak:value expr="a.streetno"/>
        </mak:list>
    </mak:list>
    <% if(counter.intValue()==0) { %> There are no students. <%}%>
     
    Fixed tag parameters cannot be runtime expressions, but can contain makumba attributes like $attr
     
    tag parameter description comments
    db The makumba database to connect to n Host_SQLEngineType_DatabaseName format.
    If not present, the default database is used. See database configuration and lookup.
    cannot contain arguments, for now
    the default database is chosen if this argument is not set
    can only be set for top-level (root) query tags
    from OQL FROM   section. If the query is nested, the FROM section is added to the parent query's FROM Fixed, Mandatory.
    where OQL WHERE  section. If the query is nested, the WHERE section is added to the parent query's WHERE Fixed
    Note: string constants have to be quoted like \"xxx\" due to JSP conventions.
    groupBy OQL GROUP BY  section Fixed
    having OQL HAVING  section Fixed
    orderBy OQL ORDER BY  section Fixed
    countVar The Java Integer variable that will contain the number of the curent iteration. 
    Note that counting iterations using simple Java counting might not lead to the correct result.
    Fixed
    maxCountVar The Java Integer variable that will contain the maximum number of iterations. Fixed
    separator Separator between two list elements. It is not included before the first or after the last
    header A header page to be included before the list.  Can only be present for the root tag. These parameters are only needed due to JSP 1.1 lack of <jsp:include flush="false"> and are obsolete for JSP 1.2 servlet containers, they can use normal <jsp:include flush="false">.
    footer A footer page to be included after the list. 

    Attributes and OQL in <mak:list > and <mak:object >

    Attributes are accessible through $AttributeName to any makumba tag. Typically they will be present in OQL sections instead of $number attributes (therefore the OQL sections of these tags is not "pure"). For example

    <mak:list from="best.internal.Lbg" where="lbg.country=$country" orderBy="lbg.$lbg_order"> ...</mak:list>

    If a $ sign needs to be in the string, the escape is $$
    If at the end of an attribute there has to be a Java identifier letter, the attribute name can be written as  text1$attrName$text2, that is, with $ at both ends.

    The http parameters are automatically set as page attributes. Other atributes can be set by the Java code as session attributes (visible in all pages accessed in the session) using pageContext.setAttribute(name, value, scope).

    The query generator is setting all the attributes that are logically possible as prepared query parameters. For example, the $country above is a query parameter since it's a value, but the $lbg_order will not be accepted as query parameter, since it's a field name.

    If an attribute has multiple values, it is expanded into multiple OQL parameters. For example:
     <mak:list from="best.internal.Lbg" where="lbg.status in set($status)" >

    For view-level attributes such as lbg_order above, the value range can be defined

    <mak:defineAttribute name="lbg_order" values="name, id" default="name"/>

    Later: Maybe the page might want to set attributes. Something like
    <mak:setAttr name="lbg" from="best.internal.Lbg lbg" where ... scope="session" />
    Then the attribute could be used as $lbg in the rest of the page/session/application... Con: such stuff is normally done by the Java code.

    <mak:value  .../>

    Displays the value of an expression from within the query.
    Example:
    <mak:list from="best.Student s" where="s.gender=\"male\"" orderBy="s.name">
        <mak:value expr="s.person.name"/>
        <mak:value expr="s.person.surname"/>
        <mak:value expr="s.person.birthdate" var="birth" printVar="printBirth"/>
        <% // we only print the birthdate if it's after some date
          if(birth instanceof java.util.Date && birth!=null)
             if(((java.util.Date)birth).after
                    (new java.util.Date(1980, 1,0))
                out.print(printBirth);
        %>
    </mak:list>
     
    tag parameter description comments
    expr OQL SELECT  projection expression. Nothing is displayed if the value is null or var or printVar are present. Fixed, Mandatory.
    var The name of the Java Object variable where to store the attribute value. A $attribute with the same name will be set.
    Note that you will have to cast it to its specific type (Integer, String, Date, Text, Pointer, Vector).
    Warning: such objects may not be of the expected type at the first iteration after re-compiling the page. Casting to another type without checking (instanceof) first will result in a ClassCastException (though the page might work at later runs).
    Fixed
    printVar The name of the Java String varialble where to store the formatted object, as it would have been printed in the page. A $attribute with the same name will be set.
    Warning: such objects may be null at the first iteration after re-compiling the page. Calling a String method withoug checking for null will result in a NullPointerException (though the page might work at later runs).
    Fixed
    urlEncode Tell if the expression will be part of an URL or not only for char[] for now
    html If "true", inhibits the HTML escape of the content. If "auto", heuristically checks the content for HTML tags and inhibits escape if there are any. Default is "false" only char[] and text
    format Format string, according to java.text.SimpleDateFormat only for date. Defaults to "dd MMMM yyyy"
    lineSeparator Separator for long lines  only for text, default "<p>"
    longLineLength The length over which a text is considered to have long line only for text, default "30"

    <mak:attribute  .../>

    Displays the value of an attribute, or sets it to a Java variable.
    Example:
    <mak:attribute name="pattern" var="pattern" exceptionVar="exception"/>
    <% if(exception!==null)
    {
    pageContext.setAttribute("pattern", (String)pattern+"%");
    %>
    <mak:list from="type t" where="t.field like $pattern" >...</mak:list>
    <% }else { %>
    No pattern argument. Please indicate one.
    <% } %>
     
    tag parameter description comments
    name the name of the attribute. Will be printed if var is not present and there is no exception when finding the argument. If there is an exception but exceptionVar is indicated, nothing will be printed. Fixed, Mandatory.
    var The name of the Java Object variable where to store the attribute value. Note that you will have to cast it to its specific type. Fixed
    exceptionVar The name of the Java Throwable variable that will store eventual exceptions raised when trying to compute the attribute. If exceptionVar is missing, any raised exception will stop page execution. If it is present, and AttibuteNotFoundException occurs, the attribute is set to null (so a next requst for the attribute will return null) Fixed
    db The database in which the business logic (if any) will compute the attribute. The default database is normally used. Fixed

    <mak:object  ...>.... </mak:object>

    Like list, but the query can only have zero or one result. A zero value for maxCountVar and countVar indicate that the object does not exist.
    Example: See <mak:list>

    Forms

    Makumba can produce 4 types of forms: new, add, edit and generic forms. All forms have a number of common features.
    They can include <mak:input >  tags (except for the <mak:form > forms). They all can have "action", "method", "handler", "name" and "message" arguments.

    Handler methods (if they exist) are executed at the point of the first makumba tag in the response page.

    Non-generic forms
    New, edit and add forms are type specific. Their fields must be named after the fields in the respective type (and related fields).

    If there is a business logic class, the engine will look (once after each page compilation) for the corresponding handler method. The handler methods are execute before the default action and may prevent the action from being executed by throwing an exception.

    If the handler class exists but no handler method can be found, an error is thrown (the site is not allowed to do the operation, e.g. StudentHandler will never have a newBestMinervaCompany() method). If the handler class wishes to allow the action, it can define an empty handler method.

    Later, new and edit forms that have no body, will build default forms.
     

    <mak:newForm  ...>.... </mak:newForm>

    Makes a form for creating a new object of the indicated type. At form response, makumba invokes the following methods:
    // by defining on_new, the handler class gets the opportunity
    // to validate/adjust the data
    // if the data is not correct, the handler can throw an exception
    handler.on_newTypeName(data, attr, db);

    // the standard Database call
    Pointer created= db.insert(type, attr);

    // by defining after_new, the handler class gets the opportunity
    // to do supplementary operations with the inserted record
    handler.after_newTypeName(created, data, attr, db);

     
    argument Java type comments
    data java.util.Dictionary The new record to create. It is read from the HTTP query string by interpreting the form.
    attr org.makumba.Attributes Other attributes in the page (sent as HTTP arguments or present in the HTTP session).
    db org.makumba.Database The database where the record will be inserted
    created org.makumba.Pointer The pointer to the created record. Only for after_new 
    If the handler class is present but both handler methods are missing (on_new and after_new), the action is not allowed.

    Example (personEdit.jsp):
    <mak:newForm type="general.Person" action="personView.jsp" method="post">
            <mak:input field="name"/>
            <mak:input field="surname"/>
            <input type="submit"/>
    </mak:newForm>

    At response:

    PersonLogic handler; // see handler discovery
    handler.on_newGeneralPerson(data, attr, db);
    Pointer created= db.insert("general.Person", attr);
    handler.after_newGeneralPerson(created, data, attr, db);

    <mak:addForm  ...>.... </mak:addForm>

    Makes a form for creating a sub-object of the mandatory enclosing <mak:object>  (ex. a language of a student, an address for a person). Example:
    <mak:object from="best.Student s" where="s=$student">
        <mak:addForm object="s" field="languages" action="studentView.jsp" method="post">
            <mak:value expr="s.name"/>
            <mak:input field="level"/>
            <mak:input field="comments"/>
        </mak:addForm>
    </mak:object>

    This will call the handler methods: (the argument names are adapted to the example)
    on_addBestStudentLang(Pointer student, Dictionary languageData, Attributes pageParams, Database db)
    after_addBestStudentLang(Pointer address, Dictionary languageData, Attributes pageParams, Database db)

    <mak:editForm  ...>.... </mak:editForm>

    Makes a form for editing the object indicated by any of the labels of the mandatory enclosing <mak:object> or <mak:list> Example:
    <mak:object from="best.Student s, s.person p" where="s=$student">
        <mak:editForm object="p" action="studentView.jsp" method="post">
            <mak:input field="name"/>
            <mak:input field="surname"/>
        </mak:editForm>
    </mak:object>

    The response will call the handler method: (the argument names are adapted to the example)
    on_editBestStudent(Pointer student, Dictionary fieldsToChange, Attributes pageParams, Database db)

    <mak:form  ...>.... </mak:form>

    Creates a generic form, that may call a handler method in response. Allows the JSP author to make any kind of form. They are suitable for more complex operations then new, add, edit. Example:
    <mak:object from="best.Student s" where="s=$student">
        <mak:form handler="doSomething" action="studentView.jsp" method="post">
            <mak:input name="xxx" value="s.person.name"/>
            <input type=submit>
        </mak:form>
    </mak:object>

    <mak:input... />

    An input field to be created, depending on the makumba type of the field.
    The difference between <mak:input > and normal HTML <input> in a makumba form are: More HTML params will be added, as needed.
    Fields of related records can be included as well, via pointers.

    Restrictions for differnt field types:

    <mak:deleteLink>...</mak:deleteLink>

    Produces a link to the page that will delete the object indicated by any of the labels of the mandatory enclosing <mak:object> or <mak:list>
     
    object OQL label of the object to delete Fixed
    handler the Java class.method that handles the response defaults to on_delete+MakumbaTypeOfEditedObject. Arguments:
    (Pointer object, Attributes a, Database db)
    action see newForm
    message
    Example:
    <mak:object from="best.Student s, s.languages l" where="s=$student AND l.lang.name=$langname">
    <mak:deleteLink object="l" action="studentView.jsp">delete <mak:value expr="l.lang.name"/></mak:deleteLink>
    </mak:object>

    The response will call the handler method: (the argument names are adapted to the example)
    on_deleteBestStudentLang(Pointer lang, Attributes pageParams, Database db)

    <mak:response/>

    The first makumba tag in a page triggers the execution of the action of a <mak:*form > or <mak:deleteLink> (in previous page).

    <mak:response/> prints information about the results of the action: It either displays the message="..." parameter of the form tag (in green) in case of success, or (in red) the message in a uncaught LogicException resulting from Business Logic. Other exception types will provoke an exception page.

    The jsp page can get hold of the message using e.g.
    <% (String) request.getAttribute("makumba.response") %>
    Similarly, attribute makumba.successfulResponse is set (only) in case of successful action execution.

    A body-tag style (<mak:response>...</mak:response>) will be added later, to display different messages for different circumstances (errors). It will also be possible to get hold of the actual exception object.