July 2006 Archives
AJAX enabling Java Web applications
Posted by mode on July 18, 2006 at 03:07 PM | Permalink
| Comments (4)
Sun recently announced two initiiatives at JavaOne 2006 to AJAX enable JSPs and JSF components -
jMaki
and
JSF-Extensions. When we announced the efforts, there was confusion about the two and it was viewed as the two technologies were competing. This document helps resolve the confusion and show that the two technologies are complimentary.
Before we move to the discussion of jMaki and JSF-Extensions a quick note on JSP and JSF and when to use which one. Generally JSP is used when you want to have some dynamic content generated in your page but not necessarily
a lot of user interaction. JSF on the other hand is designed for user interaction and has a very well defined request processing life cycle. One key design requirement for JSF was scalability of applications. While this is generally true, however take care while designing applications as it can start off with some dynamic content and can quickly develop into an application that has a lot of user interaction.
jMaki and JSF-Extensions both AJAX enable JSPs and JSF components. So how do you decide when to use jMaki and when to use JSF-Extensions? jMaki and JSF-extensions work well together. Through this document this assertion will become more clear.
jMaki
The name, jMaki, was derived from "j," for Java, and "maki," a Japanese word for “wrap” that is commonly used when descriping the roll type of sushi. jMaki acts as a wrapper for existing JavaScript libraries giving access to the JavaScript widgets from JSP pages or JSF components. jMaki today provides access to common widgets like the Yahoo map widget and Google Search widgets among others. It also provides access to widgets from other AJAX
frameworks like the Dojo toolkit. jMaki will support future JavaScript frameworks and it
allows you to use these frameworks together in the same page. jMaki enables the use of these widgets in Java using it either as a JSP tag or as a JSF component. jMaki is specially useful when your application uses only JSPs and Servlets and does not use JSF. jMaki when used as part of a JSF component has access to all the backend APIs in Java EE like persistence while adding dynamism to the front end of the appliation. Below is an example of how to use jMaki from within JSPs and JSF.
jMaki sample in JSP
Below is a code snippet that shows how to use the scriptaculous inplace editor widget from within a JSP using jMaki -
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@ taglib prefix="a" uri="http://java.sun.com/jmaki" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<h1>JSP Page</h1>
<a:ajax type="scriptaculous" name="inplace" service="inplaceService.jsp" value="click me to replace"/ >
</body>
</html>
The code in red above is of particular interest showing the usage of
jMaki. First we declare jMaki as a tag in the JSP page
by using the @taglib directive.
Once we declare that we then use it in the JSP page by including it using
the <a:ajax .... > directive that specifies
type of Javascript library that you want to use (in this case Scriptaculous) with
all the other attributes that are needed by jMaki. For details on the attributes to
use with the jMaki tag see
ajax.dev.java.net/developer.html
jMaki sample in JSF
Below is an example of how to use jMaki in a JSF data table from a resultset. The
same jMaki widget used above (the scriptacuous inplace editor) is used in the
data table here to set a new value for one of the columns of the table.
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib prefix="jsfExt" uri="http://java.sun.com/jsf/extensions/avatar" %>
<%@ taglib uri="http://java.sun.com/blueprints/ui" prefix="d" %>
<%@ taglib prefix="a" uri="http://java.sun.com/jmaki-jsf" %>
<f:view>
<html>
<head>
<title>Result Set Example
<link rel="stylesheet" type="text/css"
href='<%= request.getContextPath() + "/result-set.css" %>'>
<script type="text/javascript"
src='<%= request.getContextPath() + "/devtime.js" %>'>
</head>
<body bgcolor="white">
<a href='<%= request.getContextPath() + "/index.html" %>'>Back to home page.
<hr>
<h3>The Scroller Component
<h:form id="form">
Rendered via Faces components:
<jsfExt:ajaxZone id="subview1" style="position: relative;"
postInstallHook="postInstallHook">
<h:dataTable columnClasses="list-column-center,list-column-center,
list-column-center, list-column-center"
headerClass="list-header"
rowClasses="list-row-even,list-row-odd"
styleClass="list-background"
id="table"
rows="20"
binding="#{ResultSetBean.data}"
value="#{ResultSetBean.list}"
var="customer">
<h:column>
<f:facet name="header">
<h:outputText value="Account Id"/>
</f:facet>
<h:outputText id="accountId"
value="#{customer.accountId}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Customer Name"/>
</f:facet>
<a:ajax type="scriptaculous" name="inplace" value="#{customer.name}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Symbol"/>
</f:facet>
<h:outputText id="symbol"
value="#{customer.symbol}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Total Sales"/>
</f:facet>
<h:outputText id="totalSales"
value="#{customer.totalSales}"/>
</h:column>
</h:dataTable>
</jsfExt:ajaxZone>
<jsfExt:ajaxZone id="subview2">
<d:scroller id="scroller" navFacetOrientation="NORTH" for="table"
actionListener="#{ResultSetBean.processScrollEvent}">
<f:facet name="header">
<h:panelGroup>
<h:outputText value="Account Id"/>
<h:outputText value="Customer Name"/>
<h:outputText value="Symbol"/>
<h:outputText value="Total Sales"/>
</h:panelGroup>
</f:facet>
<f:facet name="next">
<h:panelGroup>
<h:outputText value="Next"/>
<h:graphicImage url="/images/arrow-right.gif" />
</h:panelGroup>
</f:facet>
<f:facet name="previous">
<h:panelGroup>
<h:outputText value="Previous"/>
<h:graphicImage url="/images/arrow-left.gif" />
</h:panelGroup>
</f:facet>
<f:facet name="number">
<!-- You can put a panel here if you like -->
</f:facet>
<f:facet name="current">
<h:panelGroup>
<h:graphicImage url="/images/duke.gif" />
</h:panelGroup>
</f:facet>
</d:scroller>
<script type='text/javascript'>
document.forms[0].submit = function() {};
var a = $('form:subview2').getElementsByTagName('a');
$A(a).each(function(e) {
new Faces.Command(e, 'mousedown', { subtrees: 'form:table,form:subview2' });
});
</script>
</jsfExt:ajaxZone>
</h:form>
</body>
</html>
</f:view>
In the example above again looking at the code in red we see how to use jMaki
inplace editor on one of the columns of the resultset data table.
JSF-Extensions
JSF-Extensions is another project that is intended to AJAX enable JSF
components. The JSF-Extensions project builds on the JSF framework.
If the application that you want to AJAX enable is already using the JSF
framework then jsf-extensions is a good choice. jsf-extensions introduces the notion
of partial updatable sub-views. jsf-extensions is used as a tag library and introduces
the concept of ajaxZones that are used to define subtrees that allow partial updates
rather than the traditional full page refresh. The approach taken by JSF-Extensions is to
create a custom Lifecycle AjaxLifecycle that decoarates the standard
Lifecycle to AJAX enable a JSF application. The
AjaxLifecycle checks to see if a request is an AJAX
request by inspecting request headers to see if it is an asynchronous request.
If the header is not set then the standard Lifecycle methods are invoked that does
normal JSF processing. Below we see an example of how to use jsf-extensions.
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib prefix="jsfExt" uri="http://java.sun.com/jsf/extensions/avatar" %>
<%@ taglib uri="http://java.sun.com/blueprints/ui" prefix="d" %>
<%@ taglib prefix="a" uri="http://java.sun.com/jmaki-jsf" %>
<f:view>
<html>
<head>
<title>Result Set Example
<link rel="stylesheet" type="text/css"
href='<%= request.getContextPath() + "/result-set.css" %>'>
<script type="text/javascript"
src='<%= request.getContextPath() + "/devtime.js" %>'>
</head>
<body bgcolor="white">
<a href='<%= request.getContextPath() + "/index.html" %>'>Back to home page.
<hr>
<h3>The Scroller Component
<h:form id="form">
Rendered via Faces components:
<jsfExt:ajaxZone id="subview1" style="position: relative;"
postInstallHook="postInstallHook">
<h:dataTable columnClasses="list-column-center,list-column-center,
list-column-center, list-column-center"
headerClass="list-header"
rowClasses="list-row-even,list-row-odd"
styleClass="list-background"
id="table"
rows="20"
binding="#{ResultSetBean.data}"
value="#{ResultSetBean.list}"
var="customer">
<h:column>
<f:facet name="header">
<h:outputText value="Account Id"/>
</f:facet>
<h:outputText id="accountId"
value="#{customer.accountId}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Customer Name"/>
</f:facet>
<a:ajax type="scriptaculous" name="inplace" value="#{customer.name}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Symbol"/>
</f:facet>
<h:outputText id="symbol"
value="#{customer.symbol}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Total Sales"/>
</f:facet>
<h:outputText id="totalSales"
value="#{customer.totalSales}"/>
</h:column>
</h:dataTable>
</jsfExt:ajaxZone>
<jsfExt:ajaxZone id="subview2">
<d:scroller id="scroller" navFacetOrientation="NORTH" for="table"
actionListener="#{ResultSetBean.processScrollEvent}">
<f:facet name="header">
<h:panelGroup>
<h:outputText value="Account Id"/>
<h:outputText value="Customer Name"/>
<h:outputText value="Symbol"/>
<h:outputText value="Total Sales"/>
</h:panelGroup>
</f:facet>
<f:facet name="next">
<h:panelGroup>
<h:outputText value="Next"/>
<h:graphicImage url="/images/arrow-right.gif" />
</h:panelGroup>
</f:facet>
<f:facet name="previous">
<h:panelGroup>
<h:outputText value="Previous"/>
<h:graphicImage url="/images/arrow-left.gif" />
</h:panelGroup>
</f:facet>
<f:facet name="number">
<!-- You can put a panel here if you like -->
</f:facet>
<f:facet name="current">
<h:panelGroup>
<h:graphicImage url="/images/duke.gif" />
</h:panelGroup>
</f:facet>
</d:scroller>
<script type='text/javascript'>
document.forms[0].submit = function() {};
var a = $('form:subview2').getElementsByTagName('a');
$A(a).each(function(e) {
new Faces.Command(e, 'mousedown', { subtrees: 'form:table,form:subview2' });
});
</script>
</jsfExt:ajaxZone>
</h:form>
</body>
</html>
</f:view>
The code in red above is of particular interest showing the usage of jsf-extensions.
First we declare jsf-extensions component in the JSP page by using the @taglib
directive. Once we declare that we then use jsf-extensions in the JSP page by
including it using the <jsfExt:ajaxZone .... > directive. For details on the attributes
to use with the jsf-extensions tag see
jsf-extensions.dev.java.net/nonav/mvn/ajax/tlddocs/index.html
Conclusion
As seen above jMaki and jsf-extensions work well with each other. Also there are
situations where you could use on or the other depending on the architecture of
the application.
|