How to Create an Ajax Autocomplete Text Field: Part 3 / Page 3 | WebReference

How to Create an Ajax Autocomplete Text Field: Part 3 / Page 3


[prev]

How to Create an Ajax Autocomplete Text Field: Part 3 [con't]

The "complete" Action

Before we can start the search, we have to verify that the searchString isn't empty. At the bottom of the following code snippet, there's a line that sets the HTTP header status to 204, indicating that the request succeeded but that there was no new information to return. After verifying that the searchString isn't empty, we remove both leading and trailing whitespace characters and convert the searchString to lower case so that the matching will be case insensitive. The search itself is contained within a try/catch block because the JSONObject.put() method throws a JSONException. As a result, the IDE will display the following error: "Unreachable catch block for JSONException. This exception is never thrown from the try statement body." Once we add the method call that throws this error, it will stop.

The variables that we'll need to do the search are a JSONObject to hold each fund, an Iterator and the matches member variable that we declared earlier. It can now be instantiated to an empty JSONArray object:

The iterator is used to loop through each fund in the HashMap. Each fund that matches the searchString is stored in a new JSONObject. The put() method is used so we can specify exactly which fields we want. Two of our delegate getters fund.getPrice().doubleValue() and fund.getJsonDate() are used. Finally, the JSONObject is added to the JSONArray:

The previous code will eliminate the JSONFund.put() errors, but it also adds a new one for the searchStringMatches(fund, searchString) method, since we haven't created it yet! As before, click over the "X" icon to display a context menu. Select the first item to create the method (See Figure 9)

The following code will appear at the bottom of the class:

Insert the following code to perform a case insensitive test against the Fund symbol and name fields and return the results:

Getting back the the "complete" action of the doGet() method, all that remains is to return the matches to the browser.

We can tell how many hits we got by using the length() method, which is inherited from the ArrayList class. If the matches array has more than one element, we set the content type to "text/plain" because the JSON objects are not HTML or XML. We also instruct the browser to not cache the results by setting the "Cache-Control" header field to "no-cache." To return the matches, we call the getWriter() method of the HttpServletResponse Object to get the instance of the writer and call its write() method, passing in a String using the JSONArray's toString() method. There are two versions of this method. The first is called without any parameters and returns the Array as one long String. The one that accepts an integer parameter returns a "pretty" String, complete with carriage returns and indentations of the number of spaces passed to it:

Comparison Between the JSONArray toString() and toString(int indentFactor) Methods

We supply an indentFactor because it makes debugging easier:

That covers the "complete" action. Let's move on to the "lookupbyname" one.

The "lookupbyname" Action

The search part is much like the "complete" action except that we're storing the funds in an ArrayList this time. We don't need the JSONObjects because the fund properties will be accessed directly within the JSP page rather than by a script. Therefore, instead of sending the data back to the browser, we create a new request parameter called funds and forward it to the Funds.jsp page:

The "lookup" Action

The "lookup" action is the simplest of the three. It's only used to retrieve a fund directly based on the symbol. Hence, no matching is required other than to verify that it exists in the HashMap. Once that we confirm that it is, we set the "fund" request attribute and forward the information to the Fund.jsp page to display:

The serialVersionUID

Your class should now be good to go, but there's still one warning displayed at the top of the class. If you hover over it , the following message is displayed in a tool tip: "The serializable class AutocompleteServlet does not declare a static final serialVersionUID field of type long." According to the Serializable Interface Sun documentation, a serializable class isn't required to explicitly declare a serialVersionUID. Since a default one will be calculated at runtime, they strongly recommended that serializable classes explicitly declare serialVersionUID values because the runtime version cannot be guaranteed. Therefore, "to guarantee a consistent serialVersionUID value across different Java compiler implementations, a serializable class must declare an explicit serialVersionUID value."

We can see what Eclipse suggests by clicking the warning icon (See Figure 10)

The first two are most useful to us. The first choice would just add a quick and dirty variable for us to set ourselves. The second one, however, does all the work for us, so that's what we'll select! Here's what was generated for me:

Here's the source for the AutocompleteServlet.java file that we just built.

That concludes the Java portion of the Autocomplete control. We'll have to wait until we have some browser components in place to see it in action. We'll be delving into those next time.

References

Original: April 9, 2008

Digg This Add to del.icio.us


[prev]