Developing an AJAX portlet
Let us enhance our sample application, the "MyCompany" portal, and implement
AJAX functionality in one of the portlets, using asynchronous server calls and
dynamic HTML.
We will build a simple asset allocation calculator which asks for the user's age
and returns an asset allocation mix of stocks and bonds based on a simple
age-based logic on the server side. The user interface will submit the request
asynchronously to a portlet on the server, which will then process it and
return a markup that will only refresh a segment of the page.
We will also use some special user interface DHTML effects to demonstrate the
effective combination of asynchronous calls with a rich user interface.
The front-end
We will create a new portlet called "AJAXPortlet" in the "MyPortal" project, and
position it in the center column below our current preferences portlet that we
created in the last chapter.
The myportal-object.xml shows the following entry:
<deployments>
...
<deployment>
<if-exists>overwrite</if-exists>
<parent-ref>mycompany</parent-ref>
<page>
<page-name>default</page-name>
<window>
<window-name>MyCompany AJAX Portlet</window-name>
<instance-ref>AJAXPortletInstance</instance-ref>
<region>center</region>
<height>2</height>
</window>
...
</page>
</deployment>
</deployment>
Let's add our form to the JSP:
<!--AJAX submission via form
Actual post takes place in Javascript function -->
<form method='post'
id="assetform"
name="assetcalc"
action=""
onsubmit="ajaxSubmit('<%= renderResponse. createResourceURL()
%>','testdiv', Form.serialize(this),true); return false;">
<p>Your Age: <input type="text" name="age"/> <br><br>
<input id="page" type="hidden" name="page" value="asset"/>
<input id="submit" type="submit" name="Submit"/>
</form>
As we can see, the form has an onSubmit option to delegate submission to a
JavaScript function. We are also using ResourceURL, generated from
renderResponse.createResourceURL(), to submit our form. This allows us to talk
directly to the portlet instead of to the portal. testdiv demarcates the
location of the result.
The ResourceURL looks like this:
/portal/portal/mycompany/default/MyCompany+AJAX+Portlet?action=b&cach
eability=PAGE
The cacheability=PAGE parameter indicates that we want the URL to contain the
state of the complete page, including values such as PortletURLs, and so on.
Now, let's add some JavaScript code to process the form. It is useful to note
that for an AJAX implementation, we rely on JavaScript functions to carry out
our submissions and then track responses from the server asynchronously.
Although we can write the JavaScript code ourselves, using existing popular
libraries gives us a lot more effi ciency and a broader feature set. We will
use scriptaculous.js for the effects and prototype.js for asynchronous calls.
These are available as standard in the headers of JBoss portal. Hence, we can
use them without worrying about adding the library fi les along with the code.
Our AJAX code includes asynchronous calls, and the special effects appear as
follows:
<script type="text/javascript">
// AJAX call using Prototype.js and Scriptaculous for effects
function ajaxSubmit(url,target,params,effects)
{
new Ajax.Updater(target, url, {method: 'GET', asynchronous:true,
parameters:params});
if(effects){
new
Effect.BlindDown(document.getElementById(target));
new
Effect.Highlight(document.getElementById(target),
{startcolor: '#0066CC', endcolor: '#ffffff',
restorecolor: '#FFCC99'});
}
}
</script>
Here, the Ajax.Updater function takes the ResourceURL, which is the target div
for the results, and the parameters entered in the form, to make an
asynchronous call to the server. If the effect is enabled, which it is in our
example, when the server responds back with a markup, the JavaScript code will
slide down, create space, and display the output, while highlighting the
information in three colors for emphasis.
We are all set on the client side. Now let's go back and create our portlet.
The server-side portlet
Our JSP invokes an instance of AJAXPortlet which appears as follows:
public class AJAXPortlet extends GenericPortlet
{
// async requests and responses are processed here
public void serveResource(ResourceRequest req, ResourceResponse resp) throws
PortletException, IOException
{
resp.setContentType("text/html");
PrintWriter writer = resp.getWriter();
String age = req.getParameter("age");
if (age == null || age.equals("")){
writer.print("<P> Sorry, Please enter valid age between 10 and 100! ");
}
else {
String bond = age;
int stock = 100 - Integer.parseInt(age);
writer.print("<P> The recommended asset allocation for your age is: ");
writer.print("<p> <b>Stocks: </b>" + stock + "% <b>
Bonds:
</b>" + bond + "%");
}
writer.close();
}
// parent page delivery
public void render(RenderRequest renderRequest, RenderResponse
renderResponse) throws PortletException, IOException
{
PortletContext context = getPortletContext();
PortletRequestDispatcher rd = context.getRequestDispatcher
("/WEB-INF/jsp/ajax_calc.jsp");
rd.include(renderRequest, renderResponse);
}
}
Let's look at this a bit more closely. The fi rst method, serveResource, gets
invoked when the JSP JavaScript performs a submission. We make a quick
calculation, open a PrintWriter and write our output markup to it. The output
of the PrintWriter goes directly back to the JavaScript call which then parses
the information and displays it in the requested format. We also perform a
quick validation of the input data to demonstrate how effi cient it is to
validate data by using AJAX.
Hence, using this single method, we have achieved asynchronous communication
between a window on a client browser and a portlet.
The render method follows the traditional approach of serving the portlet window
when the page fi rst loads. All we do here is to point it to the JSP page that
houses our AJAX calls.
Deployment
Once we build and deploy the portlet, and the home page is loaded, it looks like
this:
Let's enter some age as data in the fi eld, and then submit the form.
Once we enter the data and click on Submit Query, we should see the result
showing up in the same page in a newly opened area below the portlet, and with
some visual effects.
We can also see validation in action by entering either nothing or a number
greater than 100. The server reinterprets the data and responds back with an
error message, as shown below:
We just saw how simple and effi cient it is to create AJAX-enabled portlets.
Although, this was a simple example, fundamentally, as far as asynchronous call
processing is concerned, most scenarios are likely to be very similar. However,
the dynamic nature and rich content of the portlet user interface can be
dramatically enhanced by adopting the latest DHTML/AJAX libraries.
Up until now, we have been talking about custom development. Let us now look at
how JBoss portal leverages AJAX.
Also read
What is a Portlet? Explain its capabilities.
Explain Portal architecture.
What is PortletSession interface?
What is PortletContext interface?
Why portals?...................
|