Building Portlets with Ajax Behavior

Sang Shin, sang.shin@sun.com, Sun Microsystems, www.javapassion.com/ajaxcodecamp



In this lab, you are going to build several portlets that have Ajax functionality.


Expected duration: 120 minutes (excluding homework)



Software Needed

Before you begin, you need to install the following software on your computer. 


OS platforms you can use

Change Log


Things to be done (by Sang Shin)


Lab Exercises


Exercise 0: Installation and conifguration

In this step, you are going to install and configure necessary software for performing this lab, mainly NetBeans Portlet plug-in's and Portlet Container.


(0.1) Configure Portlet Container  to the Sun Java System App Server


This step is not needed if you are using NetBeans 6.0.

1. Open a terminal window.
2. Peform the following operations.
For example, for Windows platform, you might do the following. (Figure-1.10 below)
For Solaris/Linux/MacOS, you might want to the following.


3. Observe that "INFO: Portlet Container Configuration Successful" message is displayed.


(0.2) Install NetBeans Portlet plug-in's to the NetBeans IDE






















Exercise 1: Build, deploy, access, and manage "HelloWorldPortlet" portlet application

In this exercise, you are going to build, deploy, access, and manage simple "Hello World" portlet application using NetBeans. 

    1. Create, build, and run "HelloWorldPortlet" portlet application
    2. Look under the hood of the "HelloWorldPortlet" portlet application


(1.1) Create, build, and run "HelloWordPortlet" sample portlet application

1. Create a Portlet NetBeans project.


Figure-1.10: Create Portlet Application project

Figure-1.11: Give project name

2. Use Portlet Container as the deployment platform.

Figure-1.12: Select Properties

Figure-1.13: Use Portlet Container as the server

3. Build and run the project.

Figure-1.14: Build and run the project

Figure-1.15: Display of the portlet


Trouble-shooting: If you experiencing a problem (404 error) or a dialog box indicating that the portlet container is not configured correctly, please stop the Open Portlet Container and restart it again following steps mentioned below:


5. Change the mode of the portlet.

Figure-1.16: Edit mode of the portlet

6. Add another window of the same portlet.

Figure-1.17: Create a portlet window

Figure-1.18: New window is now displayed

(1.2) Look under the hood of the HelloWorldPortlet application


1. Display and study the HelloWorld.java which contains portlet code.

Figure-1.20: HelloWorld.java
package com.test;
import javax.portlet.GenericPortlet;
import javax.portlet.ActionRequest;
import javax.portlet.RenderRequest;
import javax.portlet.ActionResponse;
import javax.portlet.RenderResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletURL;
import javax.portlet.PortletMode;
import javax.portlet.PortletPreferences;
import javax.portlet.WindowState;
import java.io.IOException;
import java.io.PrintWriter;
import javax.portlet.PortletRequestDispatcher;

public class HelloWorld extends GenericPortlet {

    public void processAction(ActionRequest request, ActionResponse response) throws PortletException,IOException {

    }
   

    public void doView(RenderRequest request,RenderResponse response) throws PortletException,IOException {
        response.setContentType("text/html");       
        PortletRequestDispatcher dispatcher =
        getPortletContext().getRequestDispatcher("/WEB-INF/jsp/HelloWorld_view.jsp");
        dispatcher.include(request, response);
    }

    public void doEdit(RenderRequest request,RenderResponse response) throws PortletException,IOException {
            response.setContentType("text/html");       
        PortletRequestDispatcher dispatcher =
        getPortletContext().getRequestDispatcher("/WEB-INF/jsp/HelloWorld_edit.jsp");
        dispatcher.include(request, response);
    }

    public void doHelp(RenderRequest request, RenderResponse response) throws PortletException,IOException {

        response.setContentType("text/html");       
        PortletRequestDispatcher dispatcher =
        getPortletContext().getRequestDispatcher("/WEB-INF/jsp/HelloWorld_help.jsp");
        dispatcher.include(request, response);
    }

}
Code-1.21: HelloWorld portlet

2. Display and study JSP code fragments.

Figure-1.22: HelloWorld_view.jsp
3. Study the portlet.xml.

<?xml version="1.0" encoding="UTF-8"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd/etc/opt/SUNWportal/dtd/portlet.xsd" version="1.0">


 <portlet>
        <description>HelloWorldPortlet</description>
        <portlet-name>HelloWorld</portlet-name>
        <display-name>HelloWorldPortlet</display-name>
        <portlet-class>com.test.HelloWorld</portlet-class>
        <expiration-cache>0</expiration-cache>
        <supports>
            <mime-type>text/html</mime-type>         
            <portlet-mode>VIEW</portlet-mode>
            <portlet-mode>EDIT</portlet-mode>
            <portlet-mode>HELP</portlet-mode>
        </supports>
        <portlet-info>
            <title>HelloWorldPortlet</title>
            <short-title>HelloWorld</short-title>
        </portlet-info>
 </portlet>
</portlet-app>
 Code-1.23: portlet.xml

4. Study the portlet.tld.

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<taglib>
   
    <tlibversion>1.0</tlibversion>
    <jspversion>1.1</jspversion>
    <shortname>portlet</shortname>
    <uri>http://java.sun.com/portlet</uri>
    <info>Portlet Tag Library</info>
   
    <tag>
        <name>defineObjects</name>
        <tagclass>com.sun.portal.portletcontainer.portlet.taglib.DefineObjectsTag</tagclass>
        <teiclass>com.sun.portal.portletcontainer.portlet.taglib.DefineObjectsTagExtraInfo</teiclass>
        <bodycontent>empty</bodycontent>
        <info>define portlet objects</info>       
    </tag>
   
   
    <tag>
        <name>namespace</name>
        <tagclass>com.sun.portal.portletcontainer.portlet.taglib.NamespaceTag</tagclass>
        <bodycontent>empty</bodycontent>
        <info>produce a unique value for current portlet</info>
    </tag>
   
    <tag>
        <name>actionURL</name>
        <tagclass>com.sun.portal.portletcontainer.portlet.taglib.ActionURLTag</tagclass>
        <teiclass>com.sun.portal.portletcontainer.portlet.taglib.PortletURLTagExtraInfo</teiclass>
        <bodycontent>JSP</bodycontent>
        <info>create action url</info>
        <attribute>
            <name>portletMode</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <name>windowState</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>       
        <attribute>
            <name>var</name>
            <required>false</required>
        </attribute>
        <attribute>
            <name>secure</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
   
    <tag>
        <name>renderURL</name>
        <tagclass>com.sun.portal.portletcontainer.portlet.taglib.RenderURLTag</tagclass>
        <teiclass>com.sun.portal.portletcontainer.portlet.taglib.PortletURLTagExtraInfo</teiclass>       
        <bodycontent>JSP</bodycontent>
        <info>create render url</info>
        <attribute>
            <name>portletMode</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <name>windowState</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>       
        <attribute>
            <name>var</name>
            <required>false</required>
        </attribute>
        <attribute>
            <name>secure</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
   
    <tag>
        <name>param</name>
        <tagclass>com.sun.portal.portletcontainer.portlet.taglib.ParamTag</tagclass>
        <bodycontent>empty</bodycontent>
        <info>setup portlet url parameters</info>
        <attribute>
            <name>name</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <name>value</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>               
    </tag>
   
</taglib>
Code-1.24: portlet.tld

      

Summary

In this exercise,  you have built and run a simple Hello World portlet application using NetBeans plug-in.

                                                                                                                        return to the top




Exercise 2: Modify the "Hello World" portlet application to have Ajax behavior

In this exercise, you are going to modify the "Hello World" sample application you built in Exercise 1 to have an Ajax behavior.  First, you are going to build "ajax-hello" sample Ajax application - it is not a portlet application by the way.  The exercise is basically to add the Ajax behavior of the "ajax-hello" sample application to the "Hello World" portlet application.

    1. Open, build, and run "ajax-hello" sample Ajax application
    2. Modify "myhelloportlet" portlet application to have Ajax behavior of the "ajax-hello" application


(2.1) Open, build, and run "ajax-hello" sample Ajax application

1. Open ajax-hello NetBeans project. 

2. Remove broken references and add libarary files to the project.

3. Build and run ajax-hello project. 


Figure-2.10: ajax-hello application



(2.2) Modify "myhelloportlet" portlet application to have Ajax behavior of the "ajax-hello" application


1. Modify HelloWorld_view.jsp under myhelloportlet->Web Pages->WEB-INF->jsp as shown in Code-2.21 below.  The change is to add Ajax-fied input text field as shown in step 2.1 above for the view mode.

<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>

<%-- Uncomment below lines to add portlet taglibs to jsp --%>
<%@ page import="javax.portlet.*"%>
<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet"%>

<portlet:defineObjects />
<%PortletPreferences prefs = renderRequest.getPreferences();%>
<%-- --%>

<b>Ajaxfied HelloWorld - VIEW MODE</b>


<!-- JavaScript code starts from here -->
<script type="text/javascript">
            var req;
            var <portlet:namespace/>_target;
            var isIE;

            // (3) JavaScript function in which XMLHttpRequest JavaScript object is created.
            // Please note that depending on a browser type, you create
            // XMLHttpRequest JavaScript object differently.  Also the "url" parameter is not
            // used in this code (just in case you are wondering why it is
            // passed as a parameter).
            //
            function <portlet:namespace/>_initRequest() {
             
                if (window.XMLHttpRequest) {
                    req = new XMLHttpRequest();
                } else if (window.ActiveXObject) {
                    isIE = true;
                    req = new ActiveXObject("Microsoft.XMLHTTP");
                }
            }

            // (2) Event handler that gets invoked whenever a user types a character
            // in the input form field whose id is set as "userid".  This event
            // handler invokes "initRequest(url)" function above to create XMLHttpRequest
            // JavaScript object.
            //
            function <portlet:namespace/>_getCharacterCount() {
            
                if (!<portlet:namespace/>_target) <portlet:namespace/>_target =
                       document.getElementById("<portlet:namespace/>_myinputid");
                console.log("<portlet:namespace/>_target.value = %s", <portlet:namespace/>_target.value);
                //var url = "validate?id=" + escape(target.value);
                var url = '<%= renderRequest.getContextPath() %>' + "/validate?id=" + escape(<portlet:namespace/>_target.value);
 
                // Invoke initRequest() to create XMLHttpRequest object
                <portlet:namespace/>_initRequest();
  
                // The "processRequest" function is set as a callback function.
                // (Please note that, in JavaScript, functions are first-class objects: they
                // can be passed around as objects.  This is different from the way
                // methods are treated in Java programming language.)
                req.onreadystatechange = <portlet:namespace/>_processRequest;
                req.open("GET", url, true);
                req.send(null);
            }

            // (4) Callback function that gets invoked asynchronously by the browser
            // when the data has been successfully returned from the server.
            // (Actually this callback function gets called every time the value
            // of "readyState" field of the XMLHttpRequest object gets changed.)
            // This callback function needs to be set to the "onreadystatechange"
            // field of the XMLHttpRequest.
            //
            function <portlet:namespace/>_processRequest() {
             
                if (req.readyState == 4) {
                  if (req.status == 200) {
      
                    // Extract "true" or "false" from the returned data from the server.
                    // The req.responseXML should be in the format <number>count</number>
                    var message = req.responseXML.getElementsByTagName("number")[0].childNodes[0].nodeValue;
          
                    // Call "setMessageUsingDOM(message)" function to display the # of characters typed
                    <portlet:namespace/>_setMessageUsingDOM(message);
                   
                  }
                }
            }

            // (5) Function in which message indicating the validity of the data gets displayed
            // through the "myInputIdMessage" <div> element.
            //
            function <portlet:namespace/>_setMessageUsingDOM(message) {
             
                var userMessageElement = document.getElementById("<portlet:namespace/>_myInputIdMessage");
                var messageText;
           
               userMessageElement.style.color = "green";
               messageText = message + " characters are typed!";
            
                var messageBody = document.createTextNode(messageText);
                // if the messageBody element has been created simple replace it otherwise
                // append the new element
                if (userMessageElement.childNodes[0]) {
                    userMessageElement.replaceChild(messageBody, userMessageElement.childNodes[0]);
                } else {
                    userMessageElement.appendChild(messageBody);
                }
             
            }
          
</script>

<form name="updateAccount" action="validate" method="post">
    <input type="hidden" name="action" value="create"/>
    <table border="0" cellpadding="5" cellspacing="0">
        <tr>
            <td><b>Enter something</b></td>
            <td>
                <!-- (1) Input form field whose id is set as "userid" and "validateUserId()" function is
                        associated with the onkeyup event -->
                <input    type="text"
                          size="20"
                          id="<portlet:namespace/>_myinputid"
                          name="<portlet:namespace/>_myinputfield"
                          onkeyup="<portlet:namespace/>_getCharacterCount()">
            </td>
            <!-- The "userIdMessage" div element specifies the location where input validation
                    message gets displayed. -->
            <td>
                <div id="<portlet:namespace/>_myInputIdMessage"></div>
            </td>
        </tr>
    </table>
</form>
Code-2.21: Modified HelloWorld_view.jsp

2. Modify web.xml under myhelloportlet->Web Pages->WEB-INF as shown in Code-2.22 below.  You might want to select XML tab window as shown in Figure-2.23 below.  The change is to add Servlet mapping of the ValidationServlet that performs sever side operation.

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
     version="2.4">

  <servlet>
    <description>Validates Form Input using XmlHttpRequest Objects</description>
    <servlet-name>ValidationServlet</servlet-name>
    <servlet-class>com.sun.j2ee.blueprints.bpcatalog.ajax.ValidationServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ValidationServlet</servlet-name>
    <url-pattern>/validate</url-pattern>
  </servlet-mapping>
</web-app>
Code-2.22: Modified web.xml


Figure-2.23: Modified web.xml
.
3. Add ValidationServlet.java under com.sun.j2ee.blueprints.bpcatalog.ajax.ValidationServlet package.

Figure-2.25: Create a new Java Class

Figure-2.26: ValidationServlet.java
package com.sun.j2ee.blueprints.bpcatalog.ajax;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class ValidationServlet extends HttpServlet {
   
    
    public  void doGet(HttpServletRequest request, HttpServletResponse  response)
    throws IOException, ServletException {
       
        // Extract the data of the input form field whose name is "id"
        String targetId = request.getParameter("id");
       
        //  Send back in the format "<number>count</number>"
        //  where count is the # of characters typed
        //  Note that the content type is "text/xml".
        // && !accounts.containsKey(targetId.trim())
       
        if (targetId != null)  {
            int characterCount = targetId.length();
            response.setContentType("text/xml");
            response.setHeader("Cache-Control", "no-cache");
            response.getWriter().write("<number>" +characterCount + "</number>");
        }
    }
   
}
Code-2.27: ValidationServlet.java

Figure-2.28: Compile errors for javax.servlet.* package

4. Add servlet.jar to the class path of the project.

Figure-2.29: Project properties

Figure-2.30: Add servlet.jar
5. Build and run the application.

Figure-2.31: Type in some characters

Figure-2.32: Type in some characters in the 2nd window

Solution


The solution to this exercise is provided in  <LAB_UNZIPPED_DIRECTORY>/ajaxportlet/samples/myhelloportlet.  You can just open the project and run it.

Summary

In this exercise,  you have added some Ajax behavior to the myhelloportlet application.

                                                                                                                        return to the top

Exercise 3: Build and run "ajaxportlet" sample application

In this exercise, you are going to build and run "ready-to-build" sample portlet application that supports Ajax behavior underneath.   This sample application is based on the article and sample application described in the Best Practices for Applying Ajax to JSR 168 Porlets article from developers.sun.com.


(3.1) Open, build, and run "ajaxportlet" sample application

1. Open ajaxportlet NetBeans project. 

2. Remove broken references and add libarary files to the project.

3. Build and run ajaxportlet project. 


Figure-3.10: Ajax based application

Figure-3.11: Create the 2nd window of the AJAX Portlet


Figure-3.12: Two windows performing Ajax operations independently


(3.2) Look under the hood of the HelloWorldPortlet application


1. Display and study the view.jsp paying special attention to bold-fonted code fragments.

<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<%@ page import="javax.portlet.PortletSession" %>
<%@ page session="false" %>
<portlet:defineObjects/>

<%
    // check for invoice in session
    String selectedInvoice = (String)renderRequest.getPortletSession().getAttribute(
            "com.sun.portal.ajaxportlet.invoicenumber",
            PortletSession.APPLICATION_SCOPE);
    if ( selectedInvoice != null ) {
        pageContext.setAttribute("selectedInvoice", selectedInvoice);
    }
%>

<div id="<portlet:namespace/>_main">
<script type="text/javascript">

/* Load Dojo library, if it hasn't already */
if (typeof dojo == "undefined") {
    /* build script tag */
    var script = document.createElement("script");
    script.src = "<%=renderResponse.encodeURL(renderRequest.getContextPath() + "/js/dojo.js") %>";
    script.type= "text/javascript";
    /* insert at top of portlet main */
    var <portlet:namespace/>_main = document.getElementById("<portlet:namespace/>_main");
    <portlet:namespace/>_main.insertBefore(script, <portlet:namespace/>_main.firstChild);
}
</script>

<script type="text/javascript">
/* Use Dojo.io.bind to asynchronously get invoice content */
function <portlet:namespace/>_loadInvoice(invoice) {
    /* If an invoice was selected */
    if (invoice != null && invoice != "null") {
        /* Put selectd invoice value on query string */
        var querystring = new Array();
        querystring['invoice'] = invoice;
        /* Set up bind arguments: */
        /* url:        url for request */
        /* method:    http method */
        /* content:    key/value mapping of parameters sent with request */
        /* handle:    function to run when there is a response */
        /* mimetype:mimetype of response */
        var bindArgs = {
            url: "<%=renderResponse.encodeURL(renderRequest.getContextPath() + "/InvoiceServlet")%>",
            method: "POST",
            content: querystring,
            handle: function(type, data, evt) {
                if (type == "error") {
                    /* Swap returned error message */
                    data = "<p style='color:red'>" + data.message + "</p>";
                }
                /* Swap returned data into div tag */
                var div = document.getElementById("<portlet:namespace/>_content");
                div.innerHTML = "";
                div.innerHTML = data;
            },
            mimetype: "text/html"
        };
        dojo.io.bind(bindArgs);
    }
};

/* load invoice from session */
<portlet:namespace/>_loadInvoice(<%=selectedInvoice%>);

</script>

<jsp:useBean id="invoiceServlet" class="com.sun.portal.ajaxportlet.InvoiceServlet"/>   
<b>Invoice:</b>
<select onChange="<portlet:namespace/>_loadInvoice(this.value);" size="1">
    <option value="null">Select an invoice...</option>
<c:forEach var="invoice" items="${invoiceServlet.invoices}">
    <c:choose>
        <c:when test="${invoice == selectedInvoice}">
            <option selected value="<c:out value="${invoice}"/>">
                <c:out value="${invoice}"/>
            </option>
        </c:when>
        <c:otherwise>
            <option value="<c:out value="${invoice}"/>">
                <c:out value="${invoice}"/>
            </option>                   
        </c:otherwise>                   
    </c:choose>
</c:forEach>
</select>
   
<div id="<portlet:namespace/>_content"></div>
</div>
Code-3.21: view.jsp

Summary

In this exercise,  you have built and run a ready-to-build-and-run "ajaxportlet" sample application.

                                                                                                                        return to the top

Exercise 4: Build and run "mashupportlet" sample application

In this exercise, you are going to build and run "ready-to-build" mashupport sample application.  This sample application is based on the article and sample application described in the Building Mashup Porlets article from developers.sun.com.


(4.1) Open, build, and run "mashupportlet" sample application

1. Open mashupportlet NetBeans project. 

2. Remove broken references and add libarary files to the project.

3. Build and run mashupportlet project. 


Figure-4.10: Mashup

(4.2) Look under the hood of the HelloWorldPortlet application


1. Display and study the view.jsp paying special attention to bold-fonted code fragments.

<%@ page contentType="text/html" %>
<%@ page import="javax.portlet.PortletURL" %>
<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>

<%
   String [] mashupUrls = (String[])request.getAttribute("mashupUrls");
%>
<portlet:defineObjects/>

<script type="text/javascript"
src="http://api.maps.yahoo.com/ajaxymap?v=3.0&appid=YahooDemo"></script>
<style type="text/css">
#mapContainer {
height: 450px;
width: 100%;
}
</style>

<div id="mapContainer"></div>

<script type="text/javascript">
// Create a map object
var map = new YMap(document.getElementById('mapContainer'));

// Add map type control
map.addTypeControl();

// Add a pan control
map.addPanControl();

// Add a slider zoom control
map.addZoomLong();

// Set map type to either of: YAHOO_MAP_SAT YAHOO_MAP_HYB YAHOO_MAP_REG
map.setMapType(YAHOO_MAP_REG);  

//Get valid map types, returns array [YAHOO_MAP_REG, YAHOO_MAP_SAT, YAHOO_MAP_HYB]
var myMapTypes = map.getMapTypes();

<%
    for (int i=0;i<mashupUrls.length;i++){

%>
        map.addOverlay(new YGeoRSS('<%= mashupUrls[i]%>'));

<%
    }
%>
</script>                         
Code-4.10: view.jsp

Summary

In this exercise,  you have built and run a ready-to-build-and-run "mashupportlet" sample application.

                                                                                                                        return to the top

Exercise 5: Build and run "photoshowajaxportlet" sample application

In this exercise, you are going to build and run "ready-to-build" "photoshowajaxportlet" sample application.  This application is based on the work that is done by Xiaobo Yang.


(5.1) Open, build, and run "photoshowajaxportlet" sample application

1. Open photoshowajaxportlet NetBeans project. 

2. Remove broken references and add libarary files to the project.

3. Build and run photoshowajaxportlet project. 


Figure-5.10: Photoshop portlet

(5.2) Look under the hood of the HelloWorldPortlet application


1. Display and study the photoshow-view.jsp under photoshowajaxportlet->Web Pages->jsps->photoshow paying special attention to bold-fonted code fragments.

<%@ page session="false" %>
<%@ page contentType="text/html" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>

<script type="text/javascript"
        src='<%= renderResponse.encodeURL(renderRequest.getContextPath()
                            + "/dwr/interface/SelectPhoto.js") %>'>
</script>

<script type="text/javascript"
        src='<%= renderResponse.encodeURL(renderRequest.getContextPath()
                            + "/dwr/engine.js") %>'>
</script>

<script type="text/javascript"
        src='<%= renderResponse.encodeURL(renderRequest.getContextPath()
                            + "/dwr/util.js") %>'>
</script>

<script type="text/javascript">
  var timerId = null;

  function <portlet:namespace/>showPhoto(buttonClicked) {
    var action = DWRUtil.getValue("<portlet:namespace/>button");
    if ((action == "Stop") && (buttonClicked == "true")) {
      clearTimeout(timerId);
      DWRUtil.setValue("<portlet:namespace/>button", "Start");
    }
    else {
      SelectPhoto.getNextPhoto(<portlet:namespace/>showNextPhoto);
      if (action != "Stop")
        DWRUtil.setValue("<portlet:namespace/>button", "Stop");
    }
  }

  function <portlet:namespace/>showNextPhoto(photo) {
    var v = '<%= renderRequest.getContextPath() %>' + '/images/' + photo;
    v = '<img src=' + '"' + v + '"' + 'height="485" width="449" alt="photo" border="0"/>';
    DWRUtil.setValue("<portlet:namespace/>image", v);
    timerId = setTimeout("<portlet:namespace/>showPhoto('false')", 4000);
  }
</script>

<h4>Photo Show</h4>

<div id="<portlet:namespace/>image"></div>

<p>
  <input id="<portlet:namespace/>button" type="button" value="Start" onclick="<portlet:namespace/>showPhoto('true')"/>
</p>
Code-5.10: photoshow-view.jsp

Summary

In this exercise,  you have built and run a ready-to-build-and-run "photoshowajaxportler" sample application.

                                                                                                                   return to the top

Homework Exercise (for people who are taking Sang Shin's "Ajax Programming online course")


1. The homework is to modify the HelloWorld_view.jsp of the myhelloportlet project that you did in Step 2.2 as described below.   (You might want to create a new project by copying the myhelloportlet project.  You can name the new project in any way you want but here I am going to call to call it as myhelloportlet2.)
2. Send the following files to ajaxhomework@sun.com with Subject as AJAXHomework-ajaxportlet.