Spring 3 MVC – Autocomplete with JQuery & JSON example

Let us implement Autocomplete feature in Spring MVC application using JQuery. Autocomplete is a feature you”ll see in almost all good web apps. It allows user to select proper values from a list of items. Adding this feature is recommended if the field has multiple ( > 20 to 25) values. 

Related:Autocomplete in Java / JSP 

Our requirement is simple. We will have two fields Country and Technologies. Both these fields will have autocomplete feature so user will be able to select from list of countries and technologies. The country field can have only one value. But the technologies field can have multiple values separated by comma (,).

Things We Need

Before we starts with our Spring MVC Autocomplete Example, we will need few tools.

  1. JDK 1.5 above (download)
  2. Tomcat 5.x above or any other container (Glassfish, JBoss, Websphere, Weblogic etc) (download)
  3. Eclipse 3.2.x above (download)
  4. JQuery UI (Autocomplete) (download)
  5. Spring 3.0 MVC JAR files:(download). Following are the list of JAR files required for this application.
    • jstl-1.2.jar
    • org.springframework.asm-3.0.1.RELEASE-A.jar
    • org.springframework.beans-3.0.1.RELEASE-A.jar
    • org.springframework.context-3.0.1.RELEASE-A.jar
    • org.springframework.core-3.0.1.RELEASE-A.jar
    • org.springframework.expression-3.0.1.RELEASE-A.jar
    • org.springframework.web.servlet-3.0.1.RELEASE-A.jar
    • org.springframework.web-3.0.1.RELEASE-A.jar
    • commons-logging-1.0.4.jar
    • commons-beanutils-1.8.0.jar
    • commons-digester-2.0.jar
    • jackson-core-asl-1.9.7.jar
    • jackson-mapper-asl-1.9.7.jar

Note that depending on the current version of Spring MVC, the version number of above jar files may change. Also note that we need jackson mapper and jackson core jars. This is required for generating JSON from our Spring MVC Controller.

Getting Started

Let us start with our Spring 3.0 MVC based application. Open Eclipse and goto File -> New -> Project and select Dynamic Web Project in the New Project wizard screen.

After selecting Dynamic Web Project, press Next.

Write the name of the project. For example SpringMVC_Autocomplete. Once this is done, select the target runtime environment (e.g. Apache Tomcat v6.0). This is to run the project inside Eclipse environment. After this press Finish. Once the project is created, you can see its structure in Project Explorer. This is how the project structure would look like once we finish the tutorial and add all source code.

Now copy all the required JAR files in WebContent > WEB-INF > lib folder. Create this folder if it does not exists.

The Dummy Database

Normally you would need a database from where you’ll fetch values required for autocomplete. But for sake of simplicity of this example we will write a DummyDB java class. Once the project is created, create a package net.viralpatel.springmvc.autocomplete and a Java class file DummyDB.java. DummyDB.java is the class that will simulate the database connection and it will provide the data for our example. 

File: /src/net/viralpatel/springmvc/autocomplete/DummyDB.java

package net.viralpatel.spring.autocomplete; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; public class DummyDB { private List<String> countries; private List<String> tags; public DummyDB() { String data = "Afghanistan, Albania, Algeria, Andorra, Angola, Antigua & Deps,"+ "United Kingdom,United States,Uruguay,Uzbekistan,Vanuatu,Vatican City,Venezuela,Vietnam,Yemen,Zambia,Zimbabwe"; countries = new ArrayList<String>(); StringTokenizer st = new StringTokenizer(data, ","); //Parse the country CSV list and set as Array while(st.hasMoreTokens()) { countries.add(st.nextToken().trim()); } String strTags = "SharePoint, Spring, Struts, Java, JQuery, ASP, PHP, JavaScript, MySQL, ASP, .NET"; tags = new ArrayList<String>(); StringTokenizer st2 = new StringTokenizer(strTags, ","); //Parse the tags CSV list and set as Array while(st2.hasMoreTokens()) { tags.add(st2.nextToken().trim()); } } public List<String> getCountryList(String query) { String country = null; query = query.toLowerCase(); List<String> matched = new ArrayList<String>(); for(int i=0; i < countries.size(); i++) { country = countries.get(i).toLowerCase(); if(country.startsWith(query)) { matched.add(countries.get(i)); } } return matched; } public List<String> getTechList(String query) { String country = null; query = query.toLowerCase(); List<String> matched = new ArrayList<String>(); for(int i=0; i < tags.size(); i++) { country = tags.get(i).toLowerCase(); if(country.startsWith(query)) { matched.add(tags.get(i)); } } return matched; } }
Code language: Java (java)

The DummyDB.java contains the list of all the countries and technologies in a comma separated string value and a method getCountryList() and getTechList() that will return the list of countries and technologies starting with the string query passed as argument to that method. Thus if we pass “IN” to this method, it will return as all the countries starting with IN. You may want to change this code and add the database implementation here. Just a simple "SELECT * FROM <table> WHERE country LIKE " query will serve the purpose. Now we write SpringMVC Controller that returns JSON output for Autocomplete.

The Spring MVC Controller

The spring mvc controller class that will process the request and returns JSON output. For this create a class UserController.java under package net.viralpatel.springmvc.autocomplete.

UserController.java

package net.viralpatel.spring.autocomplete; import java.util.List; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; @Controller public class UserController { private static DummyDB dummyDB = new DummyDB(); @RequestMapping(value = "/index", method = RequestMethod.GET) public ModelAndView index() { User userForm = new User(); return new ModelAndView("user", "userForm", userForm); } @RequestMapping(value = "/get_country_list", method = RequestMethod.GET, headers="Accept=*/*") public @ResponseBody List<String> getCountryList(@RequestParam("term") String query) { List<String> countryList = dummyDB.getCountryList(query); return countryList; } @RequestMapping(value = "/get_tech_list", method = RequestMethod.GET, headers="Accept=*/*") public @ResponseBody List<String> getTechList(@RequestParam("term") String query) { List<String> countryList = dummyDB.getTechList(query); return countryList; } }
Code language: Java (java)

Note how we used @ResponseBody annotation in methods getCountryList() and getTechList(). Spring MVC converts the return type which in our case is List into JSON data. Following is the content of spring-servlet.xml file. 

File: /WebContent/WEB-INF/spring-servlet.xml

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="net.viralpatel.spring.autocomplete" /> <mvc:annotation-driven /> <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
Code language: HTML, XML (xml)

The tag is required here. This lets Spring to process annotations like @ResponseBody. The below User.java class is required only to bind a form with JSP. It is not required for this example. But for sake of Spring MVC we are using it. 

File: /src/net/viralpatel/springmvc/autocomplete/User.java

package net.viralpatel.spring.autocomplete; public class User { private String name; private String country; private String technologies; //Getter and Setter methods }
Code language: Java (java)

The JSP View

Now add JSP file which renders User form. Also we will add index.jsp which redirect to proper request. 

File: /WebContent/index.jsp

<jsp:forward page="index.html"></jsp:forward>
Code language: HTML, XML (xml)

File: /WebContent/WEB-INF/jsp/user.jsp

<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> <%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <head> <title>Spring MVC Autocomplete with JQuery & JSON example</title> <link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" /> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js"></script> </head> <body> <h2>Spring MVC Autocomplete with JQuery & JSON example</h2> <form:form method="post" action="save.html" modelAttribute="userForm"> <table> <tr> <th>Name</th> <td><form:input path="name" /></td> </tr> <tr> <th>Country</th> <td><form:input path="country" id="country" /></td> </tr> <tr> <th>Technologies</th> <td><form:input path="technologies" id="technologies" /></td> </tr> <tr> <td colspan="2"> <input type="submit" value="Save" /> <input type="reset" value="Reset" /> </td> </tr> </table> <br /> </form:form> <script type="text/javascript"> function split(val) { return val.split(/,\s*/); } function extractLast(term) { return split(term).pop(); } $(document).ready(function() { $( "#country" ).autocomplete({ source: '${pageContext. request. contextPath}/get_country_list.html' }); $( "#technologies").autocomplete({ source: function (request, response) { $.getJSON("${pageContext. request. contextPath}/get_tech_list.html", { term: extractLast(request.term) }, response); }, search: function () { // custom minLength var term = extractLast(this.value); if (term.length < 1) { return false; } }, focus: function () { // prevent value inserted on focus return false; }, select: function (event, ui) { var terms = split(this.value); // remove the current input terms.pop(); // add the selected item terms.push(ui.item.value); // add placeholder to get the comma-and-space at the end terms.push(""); this.value = terms.join(", "); return false; } }); }); </script> </body> </html>
Code language: HTML, XML (xml)

Check the above JSP. We have added INPUT fields for Country and Technologies. Also we used $().autocomplete() to enable autocomplete. For country it was straightforward $( "#country" ).autocomplete() but for technologies we did some parsing and splitting. This is because we need multiple technologies in textbox separated by comma.

That’s All Folks

You may want to run the application see the result. I assume you have already configured Tomcat in eclipse. All you need to do: Open Server view from Windows > Show View > Server. Right click in this view and select New > Server and add your server details. To run the project, right click on Project name from Project Explorer and select Run as > Run on Server (Shortcut: Alt+Shift+X, R)

Download Source Code

SpringMVC_Autocomplete.zip (4.2 MB)

View Comments

  • Great job. Only I have one slight problem. Not wanting to use JQuery UI just for one widget, and really don't like JQuery UI. How can you use all the same code as you have, but a different AutoComplete widget?

  • i had a doubt in the count text box you are showing the list countries starts with " i " but in the string data doesn't have those name which starts with " i "

    • see carefully the DummyDB.java file...String data contains all the country names and it also contains names starting with 'i'....

  • Good example and works.
    Only comment is, the jackson jar's that is in the example screen needed to be updated with two more jar files that was is in the zip file.

  • Hi Viral.

    Thanks for such a nicely documented blog. I tried implementing the above feature. I am able to get the json response at client side. But I am not getting the auto-populated drop down list. Any idea?

  • Hey great tutorial! I did everything but I got an error when I tried to run it. Can someone assist please? I get the error below:

    HTTP Status 404 - /SpringMVC_Autocomplete/

    type Status report

    message /SpringMVC_Autocomplete/

    description The requested resource (/SpringMVC_Autocomplete/) is not available.

    Apache Tomcat/6.0.35

  • Update: sorry i forgot to put the index file in the right place...now i get a java error. one problem i noticed is that the project explorer view does not look like your example. I figure the reason is that i am using the lastest eclipse "cocoa" . Please advise, Here the java error...

    HTTP Status 500 -

    type Exception report

    message

    description The server encountered an internal error () that prevented it from fulfilling this request.

    exception

    org.apache.jasper.JasperException: java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
    org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:502)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:424)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    root cause

    java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
    org.springframework.web.context.support.WebApplicationContextUtils.getRequiredWebApplicationContext(WebApplicationContextUtils.java:84)
    org.springframework.web.servlet.support.RequestContextUtils.getWebApplicationContext(RequestContextUtils.java:81)
    org.springframework.web.servlet.support.RequestContext.initContext(RequestContext.java:219)
    org.springframework.web.servlet.support.JspAwareRequestContext.initContext(JspAwareRequestContext.java:74)
    org.springframework.web.servlet.support.JspAwareRequestContext.(JspAwareRequestContext.java:48)
    org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:76)
    org.apache.jsp.index_jsp._jspx_meth_form_005fform_005f0(index_jsp.java:184)
    org.apache.jsp.index_jsp._jspService(index_jsp.java:95)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:388)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    note The full stack trace of the root cause is available in the Apache Tomcat/6.0.35 logs.

    • @BigCoder, It seems Spring is unable to locate your WebApplicationContext XML file. That is what the exception hints you - java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?

      Please check for the following -
      1. By default, the naming convention of WebApplicationContext XML file is -servlet.xml. for e.g., if "springmvc" were the servlet name then the WebApplicationContext XML should be available in \WEB-INF folder with the name "springmvc-servlet.xml"

      or

      2. If you have named your WebApplicationContext XML file differently, not adhering to the above naming convention then you should specify the location and name of your WebApplicationContext XML in web.xml with a context parameter and a context loader listener to load it. See below for an example -

      contextConfigLocation
      /WEB-INF/

      org.springframework.web.context.ContextLoaderListener

      Hope the above steps will solve your problem.

Share
Published by
Viral Patel
Tags: autocomplete json JSONObject spring mvc spring-3-mvc-series

Recent Posts

  • Java

Java URL Encoder/Decoder Example

Java URL Encoder/Decoder Example - In this tutorial we will see how to URL encode/decode…

4 years ago
  • General

How to Show Multiple Examples in OpenAPI Spec

Show Multiple Examples in OpenAPI - OpenAPI (aka Swagger) Specifications has become a defecto standard…

4 years ago
  • General

How to Run Local WordPress using Docker

Local WordPress using Docker - Running a local WordPress development environment is crucial for testing…

4 years ago
  • Java

Create and Validate JWT Token in Java using JJWT

1. JWT Token Overview JSON Web Token (JWT) is an open standard defines a compact…

4 years ago
  • Spring Boot

Spring Boot GraphQL Subscription Realtime API

GraphQL Subscription provides a great way of building real-time API. In this tutorial we will…

4 years ago
  • Spring Boot

Spring Boot DynamoDB Integration Test using Testcontainers

1. Overview Spring Boot Webflux DynamoDB Integration tests - In this tutorial we will see…

4 years ago