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/>
Note: current Java implementation finds the data definition files as follows:Data objects (records) are stored in databases.
- the designated file extension is mdd (Makumba Data Definition)
- relative to CLASSPATH (e.g. classes/best/Student.mdd)
- in a directory called "dataDefinitions" in the CLASSPATH (e.g. classes/dataDefinitions/best/Student.mdd)
- OLDSTYLE: if no mdd file is present, the no-extension file (i.e. best/Student) is looked up
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
Note: there will be another separator, to accomodate for more fields defined per lineA field definition looks like:
fieldname= [attributes] fieldtype [parameters] [; description]
Note: default values are supported internally, but not by the parserThe 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.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
Comment lines can be inserted in the data definition files as follows:
# comment
shoeSize= int; Shoe sizeIf the int can have a limited number of values, it can be described as follows
gender= int{ "male"=0, "female"=1 }; SexThis 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
name= char[80]; Username"encrypted" is a field attribute, it will be explained below.
password= encrypted char[6..10]; Secret password
If the char can have a limited number of value, it can be described as follows
gender= char{ "male", "female" }; SexThis 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
application= text; Application letter
image= text; Picture attachement
birthdate= date; Date of birth
arrivalTime= date; Arrival time
citizenship= ptr general.Country; Citizenship
Note: the ptr keyword might be ommitted in future parsersThe type can be defined on-the-spot for a single usage. For example
addres= ptr ; Address
address->street= char[80]; Street
address->number= int; NumberNote: future parsers might read this:
address= ptr{
street= char[80]; Street
number= int; Number}; address
Note: this type is known internally as ptrOne
language= set general.Language; Spoken languagesThis 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 awayThe type which the set is made of can be defined on the spot:Note: this is currently known internally as setintEnumplace= set char {"home", "away"} ; Home or awayNote: It means that place is a set that can take only the "home" and "away" values. This is currently known internally as setcharEnum
addresses= set; Addresses
addresses->street= char[80]; Street
addresses-> number= int; NumberNote: 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
!type.yesno= int{"yes"=1, "no"=0}
!title=genderNote: for the on-the spot types in the current implementation, the following notation works:
address->!title= street
!include=name_of_included_typeThe 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)
SELECT expression [[AS] label] {, expression [[AS] label] }Notations like label.field{.field} only allow "field" to be of pointer type in expression and set type in FROM.
FROM {type [AS] label | label.field{.field} [AS] label }
[ WHERE expression
[ GROUP BY expression {,expression}
[ HAVING expression {,expression} ]
]
]
[ORDER BY expression {,expression} [(ASC|DESC)] ]
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.
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.
| 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 |
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 tagsfrom 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. 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:
tag parameter description comments type Makumba type for record creation, or OQL label for subrecord creation Fixed, mandatory. handler the Java class.method that handles the response defaults to on_new+NameOfMakumbaType. Arguments:
(Dictionary newData, Attributes a, Database db)action the response page of the form Mandatory if a <mak:action> is absent method the HTTP method (get or post) Defaults to GET name the name of the created object in the response page Fixed. Defaults to __mak__edited__. message the message that is displayed in the response page upon success Fixed. Defaults to "changes done". // 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);If the handler class is present but both handler methods are missing (on_new and after_new), the action is not allowed.
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 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:
tag parameter description comments object The label of the object whose sub-object will be created Fixed, mandatory field The field name that denotes the sub-object. Fixed, mandatory. handler the Java class.method that handles the response defaults to on_add+MakumbaType+fieldname. Arguments:
(Pointer baseObject, Dictionary newData, Attributes a, Database db)action see newForm method name message
<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:
tag parameter description comments object The label of the OQL object to edit Fixed, mandatory. handler the Java class.method that handles the response defaults to on_edit+MakumbaTypeOfEditedObject. Arguments:
(Pointer object, Dictionary changedFields, Attributes a, Database db)action see newForm method name message
<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:
tag parameter description comments handler the Java method that handles the response Arguments:
(Dictionary formFields, Attributes restOfArguments, Database db)
Not mandatory. A form without handler will simply set attributes (as makumba objects) for the next pageaction the response page of the form Mandatory method the HTTP method (get or post) Defaults to GET name name of the attribute that will store (within the response page) the result of the handler method message message displayed by <mak:response > in the response page on succesfull completion
<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:
- <mak:input> produces objects prepared for setting/comparing makumba fields (e.g. Pointer, Date, Text).
- the fields produced by <input> will be available as page $attributes but will all be of type String
- the fields produced by <mak:input> are available separately as a Dictionary to the handler method
More HTML params will be added, as needed.
tag parameter description comments name
(or field)Makumba field (from the edited record or via base pointers or sub-record pointers) Fixed, mandatory value OQL expression relative to enclosing query tags or a $attribute computed previously in the page (with <mak:value var=.../> or pageContext.setAttribute(...)), or read by in the previous page by an <mak:input /> Fixed type HTML INPUT type to be used
- "hidden" works for all fields
- for char[] , type can be "text" or "password", default is "text"
- default type for int{}, char{}, ptr and set is select/option. other types are not accepted for now
- date is splitted in 3 inputs, <fieldname>_0 (day), _1 (month), _2 (year)
- for text, default is textarea, "file" will create supplementary attributes <fieldname>_filename, <fieldname>_contentType and <fieldname>_contentLength that have to be handled separately by the handler method
Fixed display If false, it will not show the <input> but it will expect to read it in the next page. This allows the page designer to format the input control manually dataType The makumba type of the data (needed if there is no value, no default expression for the value, or no makumba type associated with an attribute) can be char, char[xx], int, date, text, ptr Type, set Type format Format string, according to java.text.SimpleDateFormat
Can only countain d,M, y, H, m, s formatting chars, and any kind of separators. Ex:
'the day' dd 'of the month' MMMM 'in the year' yyyy.
Default is "dd MMMM yyyy"only for date. size Size of the input control char[], int (size of the textbox)
set, ptr (height of the select)maxLength Max length of a text control only for char[] and int. Defaults to makumba width of the char[] rows, cols Number of textarea rows and columns only for text
Fields of related records can be included as well, via pointers.Restrictions for differnt field types:
- fixed fields: cannot be edited
- relational and index pointer: cannot be edited
- timestamps (create and modify): cannot be edited
- subset, subpointer: cannot be edited as a field, only as a separate object
<mak:action>....</mak:action>
If the action URI of a form or deleteLink is more complex, possibly including other makumba tags the action attribute of the form tag can be ommitted, and the action URI can be indicated in a mak:action, anywhere inside the form tag.Example:
<mak:editForm object="ins" method="post">
<mak:action>memberView.jsp?person=<mak:value expr="p"/></mak:action>
...
</mak:editForm><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>Example:
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
<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.