features - of /ubuntu

nutritionistcornInternet and Web Development

Dec 14, 2013 (3 years and 6 months ago)

43 views

AJAF
: A Java AJAX Framework

AJAF

is a very light weight engine that assists developers in following two areas of web
-
user
-
interface
development


a) AJAX communication between browser and server and

b) HTML rendering to achieve partial page refreshes.


Wi
th AJAF we intend to replace the traditional JSP mechanism of building web user interfaces. There are
several limitations with the current (JSP) mechanism. Some of them are listed below:



JSP based applications are “Page
-
based”


i.e. they take Entire
-
Page
-
Refresh approach for most
of user interaction.



No “asynchronous Browser
-
to
-
Server (JavaScript
-
to
-
Java) event model” which makes
programming in JavaScript even more difficult.



Rending of JSP files is not AJAX based. I.e. it is not “asynchronous”.



Dependency

on Third
-
Party tags (usually open
-
source) that generate HTML / JavaScript giving
very less control to developers for customizing look
-
and
-
feel and behavior.



Creating reusable Components is not easy.



Allows for “messy code” with business
-
logic embedded in
user
-
interface code.


Using this engine we can achieve richer and more user
-
interactive applications. Following are some of the
advantages:



Richer User interfaces in terms of look
-
and
-
feel and user
-
interactivity.



Event driven programming model (that is nat
ural to most developers).



Simple JavaScript API to facilitate AJAX communication. AJAX communication between
browser (JavaScript) and server (Java) is transparently managed.



Rendering is accomplished entirely via AJAX.



Server
-
based updates are rendered in
the smallest form possible, only updating portions
of the HTML document that need to be changed.



Very light weight with a very low learning curve required for new developers (less than
half a day)



Separates the logic of “what
-
to
-
render” from “how
-
to
-
render
” resulting in cleaner (more
manageable) code artifacts.



Allows for easy creation of reusable server
-
side AJAX components.



HTML
need

not
be
“generated”

always
, as in case of JSP tags, hence giving more
flexibility to developers.



Uses some of the standard o
pen source libraries like “Prototype”, “Spring” etc. for core
functionality.



All modern browsers like Firefox, Internet Explorer and Netscape are supported.



Since we have the source code managed internally by team


there won’t be any 3
rd

party proprietary

issues.


AJAX Events Model:

A Flexible Server
-
side Java events
-
management is coupled with convenient JavaScript API.

This
API provides methods that eventually send AJAX events to server. Events
, along with other data,

carry with them
:

a) “Event Name”

b)


Event Handler Name” that must be a Spring Bean name defined in one of the Spring
-
Configuration xml files.

Event Handlers are java classes that look like the class below:


public

class

SampleEventHandler
extends

BaseEventHandler

{


public

void

firstImage
Click(AJAFContext context, AJAFResponse res)
throws

Exception


{


/** ... Code to process event ... **/


}

}


The above sample handler could be triggered simply by using the HTML below:


<img AJA_EventHandler=”
SampleEventHandler
” onClick=”AJAF
.sendEvent(this, ‘click’, ‘’)”

src=”/firstImage.jpg”>


or by calling following javascript statement elsewhere:


AJAF.sendEvent(
null
, ‘
SampleEventHandler.firstImageClick
’, ‘’)
;


Event Handlers
are invoked when either of



AJAF.sendEvent
” or “
AJAF.submitFor
m
” is
called.
Event Handlers send back response using AJAFResponse object. All responses

serialized

to
back to browser

are

executable Javascript

.



JavaScript API
:


The JavaScript API, for general use, is defined with namespace “AJAF.”. Following methods

are
available

that send AJAX requests back to server for various purposes
:



AJAF.sendEvent (element, eventName, data, beforeEventFunct, afterEventFunct)


This function is used to send an event to server. The server side event handler is resolved in
follo
wing way:

-

If “
element
” is not null
-

This method looks for an attribute called “
AJA_EventHandler
” in this
element or up the parentage of this element.

-

If “
element
” is null


The event name must be in a format
-

<HandlerName>.<EventName>


Param “
data
” i
s expected to be in format


“param1=value1&param2=value2&…”


Param “
beforeEventFunct
” (Optional) should be a javascript Function or
null
. If
null
,

ajaGlobalBeforeHandler
” is executed right before the event is sent. If either of these
functions return
fal
se
, the event is not sent.


Param “
afterEventFunct
” (Optional) should be a javascript Function or
null
. If
null
,

ajaGlobal
After
Handler
” is executed after the response from server is executed.



AJAF.
submitForm

(
formName
,
extraData
, beforeEventFunct, after
EventFunct
)


This function is used to submit an entire form’s data as an event to server. The given HTML form
or one of its parent elements must have the attribute “
AJA_EventHandler
” set to point to a valid
event handler. On the server side event handler i
s invoked with a method named
“<formName>Submit”.


Param “
formName
” specifies “name” attribute of the form that is to be submitted.


Param “
extraData
” (Optional) is data that can also be sent along with this request. It is
expected to be in format


“param
1=value1&param2=value2&…”


Param “
beforeEventFunct
” (Optional) should be a javascript Function or
null
. If
null
,

ajaGlobalBeforeHandler
” is executed right before the event is sent. If either of these
functions return
false
, the event is not sent.


Param “
afterEventFunct
” (Optional) should be a javascript Function or
null
. If
null
,

ajaGlobal
After
Handler
” is executed after the response from server is executed.


A know issue: This method does not work

in IE

-

if there is a field (input element) called “name”

inside the form being submitted.

Also, for IE, the name attribute of the form must be set and be
used as “formName”.




Response Mechanism
:

Every event handler metho
d

is passed

an AJAFResponse object. This object exposes an API to
“set” one or more “respo
nse actions”
. Re
fer to the API docs for details.



Spring Configuration
:

Various handlers in the framework are accessed using Spring
(
http://www.springframework.org
). Event Handlers, for example, are simple beans defined as
below:


<
bean
id
=
"
Test
EventHandl
er"
class
=
"
my.package
.
Test
EventHandler"
></
bean
>

The defined class MUST “extend”
com.ajaf.event.BaseEventHandler
.

For any AJAF request this handler class can be access (as
com.ajaf.event.IEventHandler) using
AJAFContext.getEventHandler
.



Request Handler:

E
very request first goes to a request handler

(if)
defined in ajaf.properties configuration file
.
This
handler class must implement the interface “
com.ajaf.context.IRequestHandler
”. If this
Request handler set
s

an AJAFResponse into the context


that respon
se will be returned to
browser and

it will
prevent
the

EventHandler from getting invoked.



HTML Scripting:

HTML Scripting
complements the Event Model by providing a UI definition mechanism that is
HTML based and is interpreted at run time. Unlike JSPs th
at are pre
-
compiled, this approach is
much more flexible in AJAX environment. This allows developers to define
fine grained
UI
elements that can be independently loaded and rendered at runtime with in each event
-
response cycle.


A UI
Component

in AJAF comp
rises of an HTML file

(refered to as “page” in the remaining
document)
, with embedded markups (for dynamic content) which are demarcated by
[% %]
.
With markups a developer can achieve following:

-

Simple Value Replacement

-

Object Replacement

-

Block Handling


M
arkups generally follow either a simple expression or JSON format for object definitions.


Simple Value Replacement:

Simple value replacement is achieved using syntax
[%=


expression


%]



where
expression

can
be:

-

<attributeName>



like “itemName” where “i
temName” is a key in the “request
parameters” hashtable (accessible through AJAFContext.getRequestParameters()).


-

<attribute
Object.property
>

-

like “order.amount” where “order” is a key in the “request
parameters” hashtable with value being a Java Bean wit
h property called “amount”. This
syntax can be used for nested properties (e.g. customer.address.city)


-

<
request.
attribute
Name
>

-

like “request.itemName” where “itemName” is a key in the
“request parameters” hashtable OR in HttpServletRequest’s parameters
or attributes.


-

<
request.
attribute
Object.property
>

-

like “request.order.amount” where “order” is a key
in the “request parameters” hashtable OR in HttpServletRequest’s parameters or
attributes with value being a Java Bean with property called “amount”. Th
is syntax can
be used for nested properties (e.g. customer.address.city)


-

<
session.
attribute
Name
>

-

like “session.itemName” where “itemName” is a key in the
“session attributes”

(accessible through AJAFContext.getServletSession()).


-

<
session.
attribute
Objec
t.property
>

-

like “session.order.amount” where “order” is a key
in the “session attributes” with value being a Java Bean with property called “amount”.
This syntax can be used for nested properties (e.g. session.customer.address.city)


-

<
page.
attribute
Name
>

-

like “page.itemName” where “itemName” is a key in the “page
attributes”

(accessible through AJAFContext.getPageContext().get/setAttribute()).


-

<
page.
attribute
Object.property
>

-

like “page.order.amount” where “order” is a key in the
“page attributes” wi
th value being a Java Bean with property called “amount”. This
syntax can be used for nested properties (e.g. page.customer.address.city)


Object Replacement:

Object replacement is achieved using syntax
[%

object_def

%]



where
object_def

is of the
format:


<ObjectName>
”:
<JSON Definition of Object>
.

An example of “
JSON Definition of
Object
” is:

{


"name": "
James
",


"
statsObject
":
{“height”: “170”, “weight”: “140”}
,


"
titlesArray
":
[
"
Mr.
"
, “Jr.”]
,


"
numberOfOrders
": "
9
"

}

The entire markup would look li
ke this:

[% “Person”: {
"name": "
James
",

"
statsObject
":
{“height”: “170”, “weight”: “140”}
,

"
titlesArray
":
[
"
Mr.
"
, “Jr.”]
,

"
numberOfOrders
": "
9
"}

Note that all the names and values must be enclosed in quotes (“”).

The object with “
<ObjectName>
” must be def
ined as a Bean in Spring configuration. The object
representing this bean must implement “
IUIComponent

. “
HtmlFileRenderer
” is the base class
(that implements “
IUIComponent
”) responsible for rendering HTML page. This class can be
extended with “process()”
method overridden to create a page file based UI component.


IUIComponent defines one useful method called “invoke” that should return “MarkupResponse”
object. The text property of this response object must be set to HTML that should be rendered in
place o
f this markup.


Using object replacement pages can be nested infinitely deep. A page can be associated to a
HtmlFileRenderer

or a derived class and then be placed anywhere on another page.

In a spring config:

<
bean
id
=
"TestHtml"
class
=
"com.ajaf.ui.html.Ht
mlFileRenderer"
>


<
property
name
=
"htmlFileName"
>



<
value
>
/app/test.html
</
value
>


</
property
>

</
bean
>

This bean when embedded as
[%

TestHtml” %]

on another page will render the

/app/test.html
’ file’s content in corresponding location.


Conversely, the ‘
/
app/test.html
’ can also be opened into a target HTML element by using
AJAF.openPage / AJAF.showDialog (javascript) or AJAFResponse.displayPage (Java)
. When
opening page this way, a “
Page
-
Bean
” can be defined that will be executed right before the page
loa
ds.
In spring config this class
must be

configured as a bean called "_
app
_
test
.html"

(This
name is simply the page’s name with “/” replaced by “_”)
.

(Also note, /app/ is a folder under
WEB_CONTEXT_ROOT and does not include the WEB_CONTEXT_ROOT).


NO other
Scripting or Programming is supported in AJAF’s html files. This results in a much
cleaner “html implementation” of UI Components. No “for” loops are supported. Any repetitive
fragments (mostly grids / tables) should be designed using richer JavaScript API
s like extJS.


Block Handling:

Block handling is achieved using syntax
[%/

object_def

%]


HTML_
BLOCK…
[%
\

%]



Where

object_def

is of the
same
format

as described above
.

The “text” property’s value of the returned
MarkupResponse object replaces the initial

[%/

object_def

%]

markup. An additional “code”
property
in the response object
can be set by these Block processor beans with a value of

CODE_SHOW_CONTENT
” or “
CODE_SKIP_CONTENT

. If “
CODE_SKIP_CONTENT
” is set then the
entire HTML_BLOCK is skipped (not r
endered). Example:

This code implements
Security
Handler

class…

public

class

Security
Handler

implements

IUIComponent

{


private

String
permission
;

...


@Override


public

MarkupResponse invoke(AJAFContext context, AJAFResponse response)


{


super
.invo
ke(context, response);


MarkupResponse resp =
new

MarkupResponse(
""
);


if

(!currentUser.hasPermission(this.
permission
))


{


resp.setCode(MarkupResponse.
CODE_SKIP_CONTENT
);


}


return

resp;


}

...

}

The above class should then be config
ured as a Spring bean:


<
bean
id
=
"Security
Handler
"
class
=
"
my.test
.Security
Handler
"
></
bean
>


This bean then can be used in a markup as follows:

<!
--

...
--
>


[%/
"Security
Handler
"
:
{
"permission"
:
"ADMIN"
}
%]



Secured HTML Content shown only to user wit
h ADMIN permission...


[%
\

%]


<!
--

...
--
>


Simple JavaScript API is also provided to open a page into a target HTML element.


JavaScript API
:


AJAF.
openPage

(
pageName
,
targetElementID
, data, beforeEventFunct,
afterEventFunct)


This function is used to
load a specified “page” in an HTML element with given ID.


Param “
pageName
” specifies path to the page (e.g. “/folder1/fragment.html”) relative to the
context root.


Param “
targetElementID
” is the ID attribute of existing element (DIV / SPAN / TD etc) on
c
urrently loaded HTML, into which this page is required to be rendered.


Param “
data
” is sent along with this request. It is expected to be in format


“param1=value1&param2=value2&…”


Param “
beforeEventFunct
” (Optional) should be a javascript Function or
n
ull
. If
null
,

ajaGlobalBeforeHandler
” is executed right before the event is sent. If either of these
functions return
false
, the event is not sent.


Param “
afterEventFunct
” (Optional) should be a javascript Function or
null
. If
null
,

ajaGlobal
After
Handle
r
” is executed after the response from server is executed.


A Java class can be associated to a “page” that will be executed before page is loaded. This can
be done by defining a Spring
-
Bean with a name that is same as page’s filename with “/”s
replaced by

“_”s. So, for a page name “/folder1/fragment.html” name of the Spring
-
Bean should
be “_folder1_fragment.html”. See
Spring Configuration

for more details.



AJAF.
showDialog

(
dialogID
,
pageName
,
parameters
)


This fun
ction is used to load a specified “page” into a “dialog” generated by ExtJS
(
http://extjs.com
). This dialog box can then be accessed using DialogManager javascript object
(defined in ajafClient.js). For example:

var id = AJAF.showDialog

(
‘MyDialog’
,
‘/some
Info.html’
, {data:'prop1=10000',
width:700, header: did, onHide: 'onPopupHide'});


Param “
dialogID
” specifies a unique identifier for this popup.


Param “
pageName
” specifies path to the page (e.g. “/folder1/fragment.html”) relative to the
context root.


Pa
ram “
parameters



a Javascript object with various parameters that define dialogs
attributes. Supported parameters are:

i)

width


width of dialog box in pixels (default is 640).

ii)

height


height of dialog box in pixels (default is 480).

iii)

modal


true (default
) / false.

iv)

header


Text that should be displayed in title bar of dialog.

v)

onHide


JavaScript function that will be executed once user closes the popup.



HTML

Renderers:


Renderers are UI components that generate dynamic HTML (just like JSP tags).


There

aren’t many HTML renderers out of the box. Most of the UI rendering relies on
developer’s HTML skills.
Simple text boxes, textareas, buttons, checkboxes, radio buttons, images
etc. don’t really require renderer since they can be bound with a dynamic value

simply by using
[%= %] markup.


One dynamic element, that I really needed to be generated by Java Code, is SELECT; and hence
the
HtmlListRenderer

(as described below).

HtmlListRenderer

also serves as an example of how
to build custom renderers when using
AJAF’s HTML scripting.
Another renderer that could be
implemented (probably in a future release) is a Grid


for now I am happy with the extJS grid as
demonstrated in samples.


HtmlListRenderer
:

This renders HTML SELECT element (dropdowns and list boxes)

T
o be dropped on a page like this:

[% "HtmlListRenderer": { "name": "defList",


"dataKey": "defDropdownList",


"propText": "testName",


"propValue": "testValue",


"selectedValuesDataKey": "selectedDef"


} %]

Various pro
perties supported are:

/**

HTML

name

of

select

element.

ID

is

set

to

this

same

value

*/

private

String
name
;

/**

expression

that

points

to

a

Collection

that

carries

Beans

to

be

show

in

list

*/

private

String
dataKey
;

/**

name

of

bean

property

that

has

the

display

text

*/

private

String
propText
;

/**

name

of

bean

property

that

has

the

value

*/

private

String
propValue
;

/**

if

true

-

all

other

properties

from

each

Bean

are

added

to

the

"Option

tag"

as

attributes

*/

private

boolean

addOtherProperties
;

/**

Sing
le

selected

value.

This

has

preference

over

the

List

selectedValues

*/

private

String
selectedValue
;

/**

List

of

String

values

as

selected

value(s)

*/

private

List
selectedValues
;

/**

expression

that

points

to

a

List

of

String

values

as

selected

value(s)

*/

private

String
selectedValuesDataKey
;

/**

default

value

*/

private

String
defaultValue
;

/**

default

text

*/

private

String
defaultText
;

/**

hide

if

only

one

option

*/

private

boolean

hide
;

/**

Text

to

display

if

no

values

returned

*/

private

String
ifEm
pty
;

/**

Javascript

events

for

the

select

element

(format

example:

onClick="myOnClick(event)"

onChange="myOnChange()"

*/

private

String
listEvents
;

/**

JavaScript

events

for

each

option

(format

similar

to

listEvents)

**/

private

String
optionEvents
;

/**

Li
st

box

(size

>

1)

-

Dropdown

(size

=

1)

by

default

*/

private

int

size

= 1;

/**

multi
-
select

is

true

by

default

(ofCourse

only

when

List

box

(size

>

1))

*/

private

boolean

multiple

=
true
;

/**

Style

stuff

*/

private

String
style
;



GRIDS:


TODO