Spring 4 MVC Ajax Hello World Example
In this tutorial, we will show you how to create a Spring MVC web project and submit a form via Ajax.
Technologies used :
- Spring 4.2.2.RELEASE
- Jackson 2.6.3
- Logback 1.1.3
- jQuery 1.10.2
- Maven 3
- JDK 1.8
- Tomcat 8 or Jetty 9
- Eclipse 4.5
- Boostrap 3
P.S If the Jackson library is found in the project classpath, Spring will use Jackson to handle the json data to / from object conversion automatically.
Try this – Spring Boot Ajax example
1. Quick Reference
1.1 In HTML, use jQuery $.ajax()
to send a form request.
jQuery(document).ready(function($) {
$("#search-form").submit(function(event) {
// Prevent the form from submitting via the browser.
event.preventDefault();
searchViaAjax();
});
});
function searchAjax() {
var data = {}
data["query"] = $("#query").val();
$.ajax({
type : "POST",
contentType : "application/json",
url : "${home}search/api/getSearchResult",
data : JSON.stringify(data),
dataType : 'json',
timeout : 100000,
success : function(data) {
console.log("SUCCESS: ", data);
display(data);
},
error : function(e) {
console.log("ERROR: ", e);
display(e);
},
done : function(e) {
console.log("DONE");
}
});
}
1.2 Spring controller to handle the Ajax request.
@Controller
public class AjaxController {
@ResponseBody
@RequestMapping(value = "/search/api/getSearchResult")
public AjaxResponseBody getSearchResultViaAjax(@RequestBody SearchCriteria search) {
AjaxResponseBody result = new AjaxResponseBody();
//logic
return result;
}
}
2. Project Directory
Review the project directory, a standard Maven project directory structure.
3. Project Dependencies
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mkyong</groupId>
<artifactId>spring4-mvc-maven-ajax-example</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>spring4 mvc maven ajax example</name>
<properties>
<jdk.version>1.8</jdk.version>
<spring.version>4.2.2.RELEASE</spring.version>
<jackson.version>2.6.3</jackson.version>
<logback.version>1.1.3</logback.version>
<jcl.slf4j.version>1.7.12</jcl.slf4j.version>
<jstl.version>1.2</jstl.version>
<servletapi.version>3.1.0</servletapi.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Need this for json to/from object -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- JSTL for views -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${jcl.slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<!-- compile only, runtime container will provide this -->
<!-- Need this for config annotation -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servletapi.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.11.v20150529</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<webApp>
<contextPath>/spring4ajax</contextPath>
</webApp>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.10</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
<wtpversion>2.0</wtpversion>
<wtpContextName>spring4ajax</wtpContextName>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<!-- Deploy to WildFly -->
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<version>1.1.0.Alpha5</version>
<configuration>
<hostname>127.0.0.1</hostname>
<port>9990</port>
<username>admin</username>
<password>admin</password>
<name>spring4ajax.war</name>
</configuration>
</plugin>
</plugins>
</build>
</project>
4. Spring Components
Only the important classes will be displayed.
4.1 @RestController
to handle the Ajax request. Read the comments for self-explanatory.
package com.mkyong.web.controller;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.annotation.JsonView;
import com.mkyong.web.jsonview.Views;
import com.mkyong.web.model.AjaxResponseBody;
import com.mkyong.web.model.SearchCriteria;
import com.mkyong.web.model.User;
@RestController
public class AjaxController {
List<User> users;
// @ResponseBody, not necessary, since class is annotated with @RestController
// @RequestBody - Convert the json data into object (SearchCriteria) mapped by field name.
// @JsonView(Views.Public.class) - Optional, filters json data to display.
@JsonView(Views.Public.class)
@RequestMapping(value = "/search/api/getSearchResult")
public AjaxResponseBody getSearchResultViaAjax(@RequestBody SearchCriteria search) {
AjaxResponseBody result = new AjaxResponseBody();
if (isValidSearchCriteria(search)) {
List<User> users = findByUserNameOrEmail(search.getUsername(), search.getEmail());
if (users.size() > 0) {
result.setCode("200");
result.setMsg("");
result.setResult(users);
} else {
result.setCode("204");
result.setMsg("No user!");
}
} else {
result.setCode("400");
result.setMsg("Search criteria is empty!");
}
//AjaxResponseBody will be converted into json format and send back to the request.
return result;
}
private boolean isValidSearchCriteria(SearchCriteria search) {
boolean valid = true;
if (search == null) {
valid = false;
}
if ((StringUtils.isEmpty(search.getUsername())) && (StringUtils.isEmpty(search.getEmail()))) {
valid = false;
}
return valid;
}
// Init some users for testing
@PostConstruct
private void iniDataForTesting() {
users = new ArrayList<User>();
User user1 = new User("mkyong", "pass123", "[email protected]", "012-1234567", "address 123");
User user2 = new User("yflow", "pass456", "[email protected]", "016-7654321", "address 456");
User user3 = new User("laplap", "pass789", "[email protected]", "012-111111", "address 789");
users.add(user1);
users.add(user2);
users.add(user3);
}
// Simulate the search function
private List<User> findByUserNameOrEmail(String username, String email) {
List<User> result = new ArrayList<User>();
for (User user : users) {
if ((!StringUtils.isEmpty(username)) && (!StringUtils.isEmpty(email))) {
if (username.equals(user.getUsername()) && email.equals(user.getEmail())) {
result.add(user);
continue;
} else {
continue;
}
}
if (!StringUtils.isEmpty(username)) {
if (username.equals(user.getUsername())) {
result.add(user);
continue;
}
}
if (!StringUtils.isEmpty(email)) {
if (email.equals(user.getEmail())) {
result.add(user);
continue;
}
}
}
return result;
}
}
4.2 The “json data” will be converted into this object, via @RequestBody
.
package com.mkyong.web.model;
public class SearchCriteria {
String username;
String email;
//getters and setters
}
4.2 Create a dummy class for @JsonView
, to control what should be returned back to the request.
package com.mkyong.web.jsonview;
public class Views {
public static class Public {}
}
4.3 User object for search function. Fields which annotated with @JsonView
will be displayed.
package com.mkyong.web.model;
import com.fasterxml.jackson.annotation.JsonView;
import com.mkyong.web.jsonview.Views;
public class User {
@JsonView(Views.Public.class)
String username;
String password;
@JsonView(Views.Public.class)
String email;
@JsonView(Views.Public.class)
String phone;
String address;
//getters, setters and contructors
}
4.4 This object will be converted into json format and return back to the request.
package com.mkyong.web.model;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonView;
import com.mkyong.web.jsonview.Views;
public class AjaxResponseBody {
@JsonView(Views.Public.class)
String msg;
@JsonView(Views.Public.class)
String code;
@JsonView(Views.Public.class)
List<User> result;
//getters and setters
}
The
@JsonView
belongs to Jackson library, not Spring framework.
5. jQuery Ajax
In JSP, create a simple search form and send the form request with jQuery $.ajax
.
<%@page session="false"%>
<%@taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html lang="en">
<head>
<c:url var="home" value="/" scope="request" />
<spring:url value="/resources/core/css/hello.css" var="coreCss" />
<spring:url value="/resources/core/css/bootstrap.min.css"
var="bootstrapCss" />
<link href="${bootstrapCss}" rel="stylesheet" />
<link href="${coreCss}" rel="stylesheet" />
<spring:url value="/resources/core/js/jquery.1.10.2.min.js"
var="jqueryJs" />
<script src="${jqueryJs}"></script>
</head>
<nav class="navbar navbar-inverse">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="#">Spring 4 MVC Ajax Hello World</a>
</div>
</div>
</nav>
<div class="container" style="min-height: 500px">
<div class="starter-template">
<h1>Search Form</h1>
<br>
<div id="feedback"></div>
<form class="form-horizontal" id="search-form">
<div class="form-group form-group-lg">
<label class="col-sm-2 control-label">Username</label>
<div class="col-sm-10">
<input type=text class="form-control" id="username">
</div>
</div>
<div class="form-group form-group-lg">
<label class="col-sm-2 control-label">Email</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="email">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" id="bth-search"
class="btn btn-primary btn-lg">Search</button>
</div>
</div>
</form>
</div>
</div>
<div class="container">
<footer>
<p>
© <a href="https://mkyong.com">Mkyong.com</a> 2015
</p>
</footer>
</div>
<script>
jQuery(document).ready(function($) {
$("#search-form").submit(function(event) {
// Disble the search button
enableSearchButton(false);
// Prevent the form from submitting via the browser.
event.preventDefault();
searchViaAjax();
});
});
function searchViaAjax() {
var search = {}
search["username"] = $("#username").val();
search["email"] = $("#email").val();
$.ajax({
type : "POST",
contentType : "application/json",
url : "${home}search/api/getSearchResult",
data : JSON.stringify(search),
dataType : 'json',
timeout : 100000,
success : function(data) {
console.log("SUCCESS: ", data);
display(data);
},
error : function(e) {
console.log("ERROR: ", e);
display(e);
},
done : function(e) {
console.log("DONE");
enableSearchButton(true);
}
});
}
function enableSearchButton(flag) {
$("#btn-search").prop("disabled", flag);
}
function display(data) {
var json = "<h4>Ajax Response</h4><pre>"
+ JSON.stringify(data, null, 4) + "</pre>";
$('#feedback').html(json);
}
</script>
</body>
</html>
6. Demo
6.1 http://localhost:8080/spring4ajax/
6.2 Empty field validation.
6.3 Search by username.
6.4. Search by email.
5. The Chrome browser, inspect element, network tag.
7. How to run this project?
7.1 Clone the source code from Github
$ git clone https://github.com/mkyong/spring4-mvc-ajax-example
7.2 Run the embedded Jetty container.
$ mvn jetty:run
7.3 Visit this URL – http://localhost:8080/spring4ajax/
Thanks.This tutorial solved my problem
Hi Mkyong,
I always found your examples clear and good,
Thanks lot!
Thanks. tutorial solved my problem
Hey guy, what example! So far the best tutorial i’ve ever seen. Thanks!!!
Thanks for the article . I am quite late but while working on this code, I get following issue.
Multiple markers at this line
– PostConstruct cannot be resolved
to a type
– PostConstruct cannot be resolved
to a type
Anyone know how to resolve this?
Hi, is it possible to save an image in this way? how can I do it? Do you have any example? Thank you
Thank you mkYong for providing this good example.
I am able to deploy and start jetty with this project.
But I am getting below content on hitting http://localhost:2222/spring4ajax/ not showing search page.
Could you/someone please help me here.
Directory: /spring4ajax/
spring4-mvc-maven-ajax-example-1.0-SNAPSHOT.war 13184243 bytes Apr 8, 2020 3:58:31 PM
method post not allowed
how to do CRUD operating in Spring MVC in eclipse without refreshing the page and connection with database
when i “$ mvn jetty:run “in the git bush it shows “No plugin found for prefix ‘jetty”‘
Could you please explain how can i do the same if i’m sending and receiving the data in XML instead of json?
Thanks
good tutorial, but i integration in my project and show this
{
“readyState”: 4,
“responseText”: ”
Estado HTTP 405 – Request method ‘POST’ not supported
type Informe de estado
mensaje Request method ‘POST’ not supported
descripción El método HTTP especificado no está permitido para el recurso requerido.
Pivotal tc Runtime 3.1.5.RELEASE/8.0.36.A.RELEASE
“,
“status”: 405,
“statusText”: “Método No Permitido”
}
Could you please explain to me what the “$” sign mean in the following line:
jQuery(document).ready(function($) {
And also why this line doesn’t start like:
$(document) ?
Thanks in advance!
this is a good example, thanks.
Hi Mkyong,
I have two questions. First, How to create layout file?
And other question, Can we add annotation to validation for view class. i don’t want to write isValidSearchCriteria method.
thanks.
i got the following error while i execute the code …
The server refused this request because the request entity is in a format not supported by the requested resource for the requested method.
“status”: 415,
“statusText”: “Unsupported Media Type”
this is a good example, thanks.
http://localhost:8080/spring4-mvc-maven-ajax-example/
Thanks
Hi Mkyoung,
i’m getting this error :
HTTP ERROR 406 Not Acceptable.
i’m sure that the ‘result’ object from ‘AjaxResponseBody’ class having a value when returned back to ajax response but i always get that error.
I’m using:
– spring 4.0.2
– jackson 2.6.3
– jetty server
HI Mkyong,
I’m uable to run this project in Tomcat 8, I mean the Tomcat starts properly with this project, but when I hit the url, it gives me 404.
Thanks,
Kapil
Hi Mkyong,
Am trying to get this application up and running in JBoss AS7 but am getting a 404 when accessing http://localhost:8080/spring4ajax/search/api/getSearchResult/
I have the same issue with one of my application which works well in Tomcat but not in JBoss AS7, just wondering if there is a workaround if you know off.
Thanks
Article is updated with wildfly-maven-plugin, use this command
mvn wildfly:deploy
to deploy this web application to WildFly.Access http://localhost:8080/spring4ajax/
I am new in java
where should I run this command
1. 404 is resources not found. Make sure ‘spring4ajax’ is your deployed web context.
2. If you get this example and deploy directly, the default web context will be this – http://localhst:8080/spring4-mvc-maven-ajax-example-1.0-SNAPSHOT
3. To update the WildFly web context, try this tutorial – https://mkyong.com/maven/maven-deploy-web-application-to-wildfly/
P.S This web application is tested with WildFly 9, no error.
hey guys , find given solution to compile the project.
you need to add following plugin in pom.xml
maven-war-plugin
2.4
false
Hope it would work for you guys , cheers 🙂
Thanks, article is updated with maven-war-plugin.
still can not work please help.HTTP Status 500 – An exception occurred processing JSP page /welcome.jsp at line 11
can you try that link after starting jetty server
make sure your port should not be used before.
http://localhost:8080/spring4ajax/
It is not compiling:
Error assembling WAR: webxml attribute is required (or pre-existing WEB-INF/web.xml if executing in update mode) -> [Help 1]
Fixed, article is updated with maven-war-plugin.
Raul ,add this in your pom.xml
maven-war-plugin
2.4
false
Jeez, this is not a tutorial, but rather a template. It’s 400+ lines of code and merely a dozen lines of explanation.
Where is the web.xml file ? I have the following error:
org.xml.sax.SAXParseException; systemId: file:/C:/DEV/apache-tomcat-8.0.28/webapps/spring4-mvc-maven-ajax-example-1.0-SNAPSHOT/WEB-INF/web.xml; lineNumber: 1; columnNumber: 2; Pre
mature end of file.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
For servlet container >= 3, web.xml is option. Code is updated, try clone the source code from GitHub again.
you need to add following plugin in pom.xml
maven-war-plugin
2.4
false
Hi Mkyong,
I reckon that you will find that using my library http://www.ajaxanywhere.com makes things a lot easier with a far more maintainable outcome. Ajaxanywhere is intended to provide declarative Ajax for apps that use server side rendering. Because it is declarative, by using HTML markup, you will find that you use very llittle to none javascript code. Please have a look at the examples: http://examples.ajaxanywhere.com
I would appreciate your feedback a lot!
Thanks!
Good stuff, but you should keep it more simple. Some details are not really needed here. For example, the @JsonView annotation only confused me more untill I figured it has nothing to do with the scope of this presentation. Just skip it.
Also, some details are maybe missing. For example, in order to work, I had to add an extention in ajax url (“url: getSearchResult.ext”) and then add this in web.xml:
dispatcher
*.ext
servlet-mapping
servlet-name dispatcher /servlet-name
url-pattern *.ext /url-pattern
/servlet-mapping