Cleaning Old Makumba Application Code


This document is intended to providea guide to developers that want to cleanup code by taking advantage of latest mak features.

This version is a paste from an e-mail dating Jan 6th 2005, which itself contained a forward from an email  from mid 2004. It may not be entirely up-to-date but it may be worth updating.

Since 0.5.14
- search is more supported (bug 63)
- the form orderBy="label.$fieldName" will change to label.#{fieldName},  etc (bug 786)
- complex chosers containing scriptlets should be replaced with mak:option (bug???)
- scriptlet code that limits mak:list iterations should be replaced by limit= and offset= (bug???)

Since 0.5.11 (or stuff that should have been there anyway) are
- bug 25 (count(*) instead of <mak:list .../>)
- JSTL/EL.
- mak:count(), mak:lastCount(), mak:maxCount()
- mak:list and query offset and limit (bug 55, 57)
- mak:option (bug 59, 60)

***********

Karamba, the flagship Makumba app was mostly written using makumba 0.5.3. since then then we added a lot of features that are used at present. karamba is still full of workarounds for these features or bugs. such workarounds are dangerous for new BEST programmers, since they learn a lot by example from existing code. using the new makumba features will lead to much cleaner code => easier to follow by the newcommers.

new features typically replace java code. so whenever you see <% java scriptlets %> in JSP pages or complicated/long methods in the business logic, you should start becoming suspicious and wonder if the respective problem can't be solved with new makumba features or simply using a formerly buggy makumba feature. if not, try to see if the problem is an unfixed bug, especially a bug targeted 0.6. please group these problems and add them to makumba's bugzilla. please try to specify which of these bugs are most important for BEST, to give priorities to the makumba development process.

here are the main improvements since 0.5.3 (the numbers show the bugzilla entries for those interested). if i forget some, please correct me. do note that _loads_ of _bugs_ (i.e. not new features) were fixed by dedicated volunteers like Stefan and Fred. Adler also helped. thanks to all.

- (3, 4) many BL methods (only) do uniqueness tests (such tests were not even correct: in another thread, some other user may insert precisely the same value). instead, the "unique" MDD keyword can be used, and the uniqueness test is done automatically in the DB rather than at java level. this feature may still need improvement to ensure the right experience for the user. try it out.

don't forget to set alter#typeName=true when you set a field to unique in typeName.mdd; follow the log output and see that a new index is created, after that, remove the alter# directive!

mind you, for now only individual fields can be made unique (513)

- (48) some very complicated BL methods (many written by Fred in Johnny) try  to achieve synchronization between concurrent accesses. since 0.5.10, all BL is executed in separate transactions ("transaction isolation" which usually provides synchronization), so this problem is gone away. it's high time to review such code.

- (48) if you still need synchroniztion, makumba now offers named locks. you can lock a symbol using org.makumba.Database#lock(String), and as long it's locked, all simmultaneous accesses that want to lock it will block. you can unlock it explicitely, or it will unlock when your BL method finishes (with or without error), or when you use close() your db object. this is similar to ordinary java locking (Object#wait() and Object#notify()) but unlike java locking, it works across java virtual machines (JVMs) that access the same makumba databases.

- (62) mak:if can replace a lot of Java <%if( )%>. mind you, the expression of mak:if will be evaluated _in_the_database_. that's very good if you are making comparisons between values in the database and/or constants. if you are, however, testing java variables declared in the page, keep using java if(), but do ask yourself if a makumba feature could help eliminate that

- lots of mak:forms have action=<%=java expression %> . that ugly detour into java can be eliminated using <mak:...form...> <mak:action> compose the action </mak:action> ... </mak:form>

- (37) mak:...form can now include other mak:...form's ("multiple forms"), resulting into very complicated actions that can be taken by your page. all these little actions are executed together, in a single transaction, so they only make sense together (if one produces error, the effect of all others is cancelled). this can eliminate a lot of JSP scriptlets, Javascript and Java business logic.

look at the present johnny evaluation and compare with the multiple form version...
http://tallinn.best.eu.org/cristi/MF.jsp
http://tallinn.best.eu.org/cristi/MFedit.jsp

- (17, 371, 372, 375, 451) mak:input has a much more powerful value= as follows:
* "new" means the OQL label "new". if the mak:input is not inside a
mak:list/object, this makes no sense.
* "$new" is an attribute (not really OQL syntax, but makumba JSP-OQL syntax).
* "\'new\'" is a string constant. value="'new'" also works
* "\'2003-03-28\'" is a date constant. value="'2003-03-28'" should also work
* "0" is an integer constant
* "nil" is the OQL null value
all of the above can be combined into OQL expressions ("new=nil" will be an int, boolean-like expression, "\'2003-03-28\'<\'2003-03-29\'" will be an int of value 1

- mak:input supports new attributes like default=, empty= (572, 501). choices can now be presented as lists or radio buttons, etc (585)

- in general, lots of bugs were fixed on forms and inputs. if you see a form that contains lots of scriptlets, or a place where a html <form > or a generic <mak:form>  is used instead of <mak:new/add/edit Form > (though it does a DB operation in the end), please become suspicious and try to do it again the "clean" way, eliminating scriptlets, reducing business logic code (eventually also using multiple forms described above)

- (28) int{"name1"=1 "name2"=2 }  now supports deprecation of some alternatives. when deprecated, they won't be shown in newForms so new records with that value won't be created.

- (601) int{"name1"=-1 "name2"=2 } negative values allowed

- (544) makumba now supports @include. if you want to repeat the same piece of code across many pages, it is ideal. for example, suppose two mak:lists below use the same labels, a, b, c, of the same types (A.mdd, B.mdd, C.mdd). then they can @include the same body that has mak:value's using a, b, and c. unlike when using jsp:include, the @include-d page cannot be executed on its own! however, you can't do the above code repetition (two mak:lists that include the same body) with jsp:include

@include is also handy when you want to use two kinds of forms (e.g. a newForm and an editForm) that have the same content (mak:input's and all).
the above MF.jsp and MF.edit.jsp can use common, @include'd code, to display the form fields
http://tallinn.best.eu.org/cristi/MF-include.jsp
http://tallinn.best.eu.org/cristi/MFedit-include.jsp
the included file:
http://tallinn.best.eu.org/cristi/MFfields.jsp

do note that @include (textual inclusion) is in a way a step back as a programming paradigm, yet there is no alternative in makumba today (since this stuff can't be done with jsp:include). the included pages really make no sense without the pages that include them, and make no reference to them (there is no "contract" between the two). e.g. MFfields above should be able to specify "i can only be included in a <mak:...form> that creates or edits data of the type general.survey.Response".

finally, note that in some simple cases (e.g. HTML-only JSP) jsp:include and @include are interchangeable. @include is faster, though jsp:include was recommended up to now. you will have to test @include more before changing that recommendation

- (430) float (real) type is now supported

- (101) you now have much more HTML CSS and javascript power in the mak:tags by being able to use class= id= onSubmit=, etc (i.e. most standard attributes supported by HTML)

- mak:value now supports maxLength= (449), default= (572), empty= (501) (default and empty do not yet accept OQL expressions)

- (41) you may find that orderBy="label.$someArgument" works better now. some pages may want to sort information by different columns, depending on a certain CGI argument. there used to be problems with that (though it worked) in makumba. see http://bugs.best.eu.org/show_bug.cgi?id=41 . please try to avoid making 2 JSPs only because you need to sort in two ways, and the rest of the page is the same. if that can't be avoided, please give input to bug 41 and say why/how, and at least use @include to avoid repeating code, because if you repeat code, you'll have to fix it twice (or more times)

- (93) org.makumba.copy was fixed (had been long broken since some 0.5.3) and can be used to copy from a mak database in any format supported (mysql, informix, db2, odbc, etc), to another mak database. similar fixes were done for for org.makumba.delete and org.makumba.db.open (which checks whether the physical DB corresponds to the MDDs)

- (34) mak:logout now support wildcard (*). that logs out every actor who logged in in the session (lbg, member, johnny student, etc)

- (557) mak:list/object header= and footer= will _not_ be supported anymore. please remove them (use jsp:include or @include instead)

******
some advice:

- (444) choose carefully when to use UnauthenticatedException (no rights) and when to use UnauthorizedException (no good password)
- (351) whenever you create a org.makumba.Database object, make sure you close() it in a finally{} block

******

two ugly workarounds are present in many pages and not needed anymore (indeed, they are not _desirable_):

- (6, 36, 85, etc) workarounds for "first-makumba-tag" (fixed since 0.5.6)
you will see a lot of <mak:attribute... "dummyFirst" ..."dummyMak"/> . they are obsolete. take them away. the only effect that they have left is to puzzle newcomers.

- (5, 384, etc) workarounds for "first-load-errors" (fixed since 0.5.7)
you will see a lot of instanceof tests in the karamba JSPs. they are obsolete. take them away. a <mak:value printVar /> will always have type String, and a <mak:value var /> will always have the Java type that corresponds to the respective makumba type (java.lang.Integer for OQL int, java.util.Date for OQL date, etc). most null tests are also obsolete, especially if the field is not null in the mdd

*********

become suspicious when you see pageContext.setAttribute, pageContext.getAttribute, pageContext.findAttribute, request.get/setAttribute, session.get/setAttribute.

either the thing can be done in a simpler way (see example below) or there is a need for some makumba feature.

for example, the right way to use a countVar is

<mak:list ... countVar="cnt" >
<% int count= cnt.intValue(); %>
...

and not

<%int count= ((Integer)pageContext.findAttribute("cnt")).intValue()); %>

that is, mak:list countVar is always an Integer, so is maxCountVar. mak:value printVar is always a String. mak:value var= is an Object and that will need casts to more specialized classes (see bug 718)

so: become suspicious when you see casts in karamba JSPs :) . if the casted variables were defined with countVar, maxCountVar or printVar, the cast is most probably useless. if the cast is used to read a page, request or session attribute, the whole attribute usage is questionable.

what's more, when you will upgrade to Java 1.5 (presently in beta 2), you will be able to transparently use Integers as ints, so in the example above you can use cnt directly, no need for count.