Skip to main content

How to Create an AJAX-enabled Phobos Application

This tutorial shows you how easy it is to create an AJAX-enabled Phobos application using a simple example that performs add and remove list operations using AJAX.

Before getting started with this tutorial, you should satisfy the following requirements:

Introducing the List Example

The list example, available in the Phobos workspace, allows you to add items to a list, remove items from a list, and display the list using AJAX. The following figure shows a screenshot of the application. Notice that you add an item to the list by entering it in a field and clicking the Add to List button. After you click the button, the item appears in the list. You can remove an item from the list by clicking it.

Screenshot of List Application

Running the Example

To run the list example, follow these steps:
  1. Make sure you have the NetBeans 5.5 IDE installed and running on your system.
  2. Install the Ajax update center and all the Phobos modules in the IDE following all the instructions on the Phobos download page.
  3. Create a new project selecting "Scripting / Samples" as the category and "Ajax List" as the project:


  • Click "Next" and complete the project creation step.
  • Run the application by right-clicking on the newly created project and selecting the "Run project" menu item. Your browser should open the front page of the application. If it doesn't, point it to the following URL:
    http://localhost:8888/
  • Enter a string in the text field and click Add to List to add an item to the list.  Repeat to add multiple items.
  • Click an item in the list to remove it from the list.
  • How the Application Works

    Those of you who have created AJAX applications before will find that an AJAX-enabled Phobos application is not much different from what you've done before. As with any AJAX-enabled Phobos application, the list application requires the following pieces:
    • A startup script that directs the request to the controller so that the view can be rendered.  In the AJAXlist example, this file is called index.js, and is located in the application/script directory of the project.
    • An embedded JavaScript file that represents the view. This file contains the code to initialize and send the XMLHttpRequest, the HTML that defines the form components that appear on the page, and any style information.  In the AJAXlist example, this file is called list.ejs, and is located in the application/view directory of the project.
    • A controller that handles the incoming XMLHttpRequest and renders the view.  In the AJAXlist example, this file is called list.js, and is located in the application/controller directory of the project.
    Before delving into the different pieces of the calculator application, let's understand how it works. When the browser makes the first request for the page, the following happens:
    1. The index.js file handles the initial request by redirecting it to the /list/show URL. The list part of the URL is a controller, and show is one of its functions. The show function is defined in list.js.
    2. The Phobos runtime creates the List controller and invokes the show function.
    3. The show function creates the list, saves it into the session, and renders the list.ejs view.
    4. The user enters an item to add to the list and clicks the Add to List button.
    5. When the user clicks Add to List, the XMLHttpRequest object is created, and the client sends a POST HTTP request to the /list/compute URL with the request paramenters representing the value that the user entered and the command "add", thereby calling the compute function of List controller with these parameters.
    6. The compute function does the following:
      1. Gets the value the user entered and the value of the command.
      2. Adds the value to the list and saves it into the session.
      3. Sends the list as part of the response back to the client.
    7. When the user clicks an item in the list that is rendered to the page, another XMLHttpRequest object is created and the compute function is called again, this time passing the index of the item to be deleted and the command "remove" as the request parameters.
    8. The compute function does the following:
      1. Gets the value of the index and the command from the request parameters.
      2. Removes the item at the selected index from the list and saves the list into session.
      3. Sends the new list as part of the response back to the client.
    The remaining sections describe how to perform the following tasks to create the list application. You can apply these tasks while developing your own application.

    Handling the Initial Request

    When the browser makes its first request for the list application, it passes the URL, /. This request is dispatched to the index.js script, located in the script directory. This script redirects the request to the URL, /list/show by executing the following line:
    library.httpserver.sendRedirect(library.httpserver.makeURL("/list/show"));
    In this case the request is dispatched to the show function of the List controller. This function will render the view, as described in the next section.

    Rendering the View

    The first thing the show function does is it creates a list and stores it into the session:
     var list = invocation.session.list;
    if (list == undefined) {
    var list = new Array();
    invocation.session.list = library.json.serialize(list);
    }
    Because you can only save String values in session with Phobos, you need to serialize the JavaScript list into JavaScript Object Notation (JSON) format to save it in the session. Note that serializing an object to JSON will not work if the object contains some Java objects.  Finally, the controller renders the view:

    library.view.render("list.ejs");

    The view of a Phobos application is represented by an embedded JavaScript file (an .ejs file). The list.ejs file includes the following:
    • A set of CSS styles
    • The script that initializes the XMLHttpRequest object and sends it to the controller
    • The HTML tags that represent the form elements on the page
    The next two sections focus on creating the form template and writing the script that creates and sends the XMLHttpRequest object to the controller.

    Creating the Form Template

    The following code shows part of the list.ejs file that creates the form, which allows the user to add items to a list and remove items from a list.
      <div id="listForm" class="listContainer">
    <form name="autofillform" onSubmit="submitData(); return false;">
    <input id="entryField" type="text" size="20" value="Enter New Value">
    <input type="button" onclick="submitData(); return false;" value="Add to List">
    </form>
    <div id="list" class="listDiv"></div>
    </div>

    Notice that there are two div tags, one inside the other. A JavaScript function looks for a tag in a page using the unique IDs of div tags. The outer div tag wraps the form component, which includes the field in which the user enters an item, and the button to add the item to the list, as well as the inner div tag. The inner div tag identifies the component that displays the list on the page.

    When the user clicks the button, Phobos gets the ID of the entire list and invokes the submitData method, which the next section discusses.  The response that the server returns includes the updated list, which includes the item the user added.  This response replaces the inner div tag.  The following code is an example of a response that shows a 2-item list:

    <ol>
    <li><div class=\"plain\" onmouseover=\"this.className ='over';\"
    onmouseout=\"this.className ='plain';\"
    onclick=\"removeItem('"0"')\">" + list[0] + "</div></li>
    <li><div class=\"plain\" onmouseover=\"this.className ='over';\"
    onmouseout=\"this.className ='plain';\"
    onclick=\"removeItem('"1"')\">" + list[1] + "</div></li>
    </ol>

    Note that the removeItem function is invoked with the index of the item on which the user clicked.  You'll see in the next section how submitData and removeItem construct URLs with the appropriate request parameters so that the controller appropriately adds an item to or removes an item from the list.

    Creating and Sending the XMLHttpRequest to the Controller

    The previous section showed how the submitData function is invoked when the user clicks the Add to List button and how the removeItem function is invoked when the user clicks on an item in the list.

    As shown by the following code, the submitData function gets the value of the text field in which the user entered the item to add to the list. It then creates a URL that it passes to the initRequest function, which creates the XMLHttpRequest object.
    function submitData() {
    entryField = document.getElementById("entryField");
    var url = <%= library.view.quoteUrl("/list/compute") %>;
    + "?command=add&entryField=" + entryField.value;
    initRequest(url);
    }
    Here, the quoteURL function from the view JavaScript library available in Phobos returns a URL whose protocol, server, and port components are taken from the current request. This path is the specified string, which identifies the compute function of the List controller.

    The add command and the value of entryField are added to the URL as request parameters.  The compute function of the List controller uses the command to determine if it needs to add an item to or remove an item from the list.

    Similarly to submitData, the removeItem function creates a URL, which it passes to the initRequest function.

    function removeItem(index) {
    var url = <%= library.view.quoteUrl("/list/compute") %> + "?command=remove&index=" + index;
    initRequest(url);
    }

    Note that removeItem takes the index of the item to remove and adds it as well as the remove command to the URL as request parameters.

    The initRequest function creates the XMLHttpRequest object and sends it to the URL passed to it by the submitData or removeItem functions. As shown in the following code, the initRequest function is exactly the same as it would be if you were implementing this example with any other web application framework.

    function initRequest(url) {
    var list = document.getElementById("list");
    if (window.XMLHttpRequest) {
    req = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
    isIE = true;
    req = new ActiveXObject("Microsoft.XMLHTTP");
    }
    req.onreadystatechange = processRequest;
    req.open("POST", url, true);
    req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    req.send(null);

    function processRequest () {
    if (req.readyState == 4) {
    if (req.status == 200) {
    list.innerHTML = req.responseText;
    }
    }
    }

    }
    The preceding code does the following:
    • Creates the XMLHttpRequest object, first checking if the user's browser is Internet Explorer or not and creating the object accordingly.
    • Sets the object's onreadystatechange property to the callback function, processRequest. This means that whenever the readyState of the object changes, this function is invoked.
    • The processRequest function checks if the readyState is 4, which means that the request is completed, and then it checks if the status of the request is 200, which means that it was successful. In that case, the processRequest function replaces the list div element with the response from the controller.
    • The initRequest function then calls the object's open function, passing in the HTTP method, the URL to send the request, and a boolean indicating whether or not to make the request asynchronous.
    • Finally, it sends the request to the URL specified, which means that the compute function of the List controller will be invoked.

    Processing the XMLHttpRequest

    The XMLHttpRequest object explained in the previous section sends the URL to the compute function of the List controller. In this section, you'll see how the compute function adds items to the list, removes items from the list, and generates the response.  The JavaScript code described in the previous section runs in the browser, whereas the JavaScript code detailed in this section runs on the server.

    The compute function uses the onMethod function of the Phobos httpserver library to restrict parts of its implementation to only be invoked during certain HTTP methods. In the case of the code that adds items to or removes items from the list and returns the response, the compute function ensures that this code is only executed during a POST:

    this.compute = function() {
    library.httpserver.onMethod({
    POST: function() {
    //code to add items from the list and remove items from the list
    },
    Before adding items to or removing items from the list, the compute function must deserialize the list stored in the session from JSON into a list variable:
    	var list = library.json.deserialize(invocation.session.list);
    Then the compute function checks if the command request parameter is equal to add or remove to determine whether it should add an item or remove an item.
          if (command == "add") {
    var index = list.length;
    list[index] = entryField;
    }
    if (command == "remove") {
    var index = Number(request.getParameter("index"));
    var length = list.length;
    if (index != null) {
    while (index < length - 1){
    list[index] = list[index+1];
    index = index + 1;
    }
    list.length = index;
    }
    After updating the list, the compute function serializes the updated list back into JSON and stores it into the session.

    After it updates the list, the compute function sends the response back to the client:

    	response.setStatus(200);
    response.setContentType("text/html");
    writer = response.getWriter();
    writer.println("&lt;ol>");
    for (var index = 0; index < list.length; ++index){
      writer.println("<li><div class=\"plain\" onmouseover=\"this.className ='over';\"
    onmouseout=\"this.className ='plain';\"
    onclick=\"removeItem('" + index + "')\">" + list[index] + "</div></li>");
     }
    writer.println("</ol>");
    writer.flush();
    Notice that for every item in the list, a div element is rendered. This element has several attributes, including an onclick attribute that is set to the function call removeItem('" + index +"'). When the user clicks on an item in the list, the removeItem function is called with the index of the item the user clicked.

    Deploying the Application


    Once your application is tested and ready for deployment, you can use the "Export as Web Archive (WAR)" context menu item to create a war file. The generated war file can be found under the dist directory of the project. This war file is fully portable and can be deployed on GlassFish or any other J2EE application server or servlet container.

    What's Next


    Now you understand how to create simple AJAX-enabled Phobos applications.  And you can see that the code to implement the AJAX functionality is the same as it would be in any other web application.  What's great about creating AJAX-enabled web applications with Phobos is that you have JavaScript on the client and the server.  Although you can't tell with this small example, having JavaScript on the client and the server makes it easier to transfer data between the client and the server because the data is represented as the same object on both ends.  For example, you could edit the list example so that it sends the list as JSON to the client and lets the client rendedr the HTML there. Another advantage of developing with Phobos is that  you are free to change or add on to the application while it is running.  As Phobos matures, you'll be able to do much more with it.  To keep up to date on the progress of Phobos, visit phobos.dev.java.net and join the project aliases.

     
     
    Close
    loading
    Please Confirm
    Close