Example Spring MVC Ajax Hello World

1. Project Structure

 

2. File pom.xml

 

<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.codewr</groupId>

    <artifactId>spring4-mvc-maven-ajax-example</artifactId>

    <packaging>war</packaging>

    <version>1.0-SNAPSHOT</version>

    <name>SpringMVC Maven Ajax Example</name>

 

    <properties>

        <jdk.version>1.7</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, deployed 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>

 

3. Class SpringWebConfig.java

 

package com.codewr.config;

 

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import org.springframework.web.servlet.view.InternalResourceViewResolver;

import org.springframework.web.servlet.view.JstlView;

 

/**

 *

 * @author codewr

 */

@EnableWebMvc

@Configuration

@ComponentScan({"com.codewr.web"})

public class SpringWebConfig extends WebMvcConfigurerAdapter {

 

    @Override

    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");

    }

 

    @Bean

    public InternalResourceViewResolver viewResolver() {

        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

        viewResolver.setViewClass(JstlView.class);

        viewResolver.setPrefix("/WEB-INF/views/jsp/");

        viewResolver.setSuffix(".jsp");

        return viewResolver;

    }

 

}

 

4. Class MyWebInitializer.java

 

package com.codewr.servlet3;

 

import org.springframework.web.servlet.support

.AbstractAnnotationConfigDispatcherServletInitializer;

import com.codewr.config.SpringWebConfig;

 

/**

 *

 * @author codewr

 */

public class MyWebInitializer extends

        AbstractAnnotationConfigDispatcherServletInitializer {

 

    @Override

    protected Class<?>[] getServletConfigClasses() {

        return new Class[]{SpringWebConfig.class};

    }

 

    @Override

    protected String[] getServletMappings() {

        return new String[]{"/"};

    }

 

    @Override

    protected Class<?>[] getRootConfigClasses() {

        return null;

    }

 

}

 

5. Class AjaxController.java

 

package com.codewr.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.codewr.web.jsonview.Views;

import com.codewr.web.model.AjaxResponseBody;

import com.codewr.web.model.SearchCriteria;

import com.codewr.web.model.User;

 

/**

 *

 * @author codewr

 */

@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, limited the json data display to client.

    @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 client.

        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("codewr1", "pass123", "[email protected]", "012-1234567", "address 123");

        User user2 = new User("codewr2", "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;

 

    }

}

 

6. Class WelcomeController.java

 

package com.codewr.web.controller;

 

import org.springframework.stereotype.Controller;

import org.springframework.ui.ModelMap;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

 

/**

 *

 * @author codewr

 */

@Controller

public class WelcomeController {

 

    @RequestMapping(value = "/", method = RequestMethod.GET)

    public String printWelcome(ModelMap model) {

        return "welcome";

    }

 

}

 

7. Class Views.java

 

package com.codewr.web.jsonview;

 

/**

 *

 * @author codewr

 */

public class Views {

 

    public static class Public {

    }

}

 

8. Class AjaxResponseBody.java

 

package com.codewr.web.model;

 

import java.util.List;

 

import com.fasterxml.jackson.annotation.JsonView;

import com.codewr.web.jsonview.Views;

 

/**

 *

 * @author codewr

 */

public class AjaxResponseBody {

 

    @JsonView(Views.Public.class)

    String msg;

    @JsonView(Views.Public.class)

    String code;

    @JsonView(Views.Public.class)

    List<User> result;

 

    public String getMsg() {

        return msg;

    }

 

    public void setMsg(String msg) {

        this.msg = msg;

    }

 

    public String getCode() {

        return code;

    }

 

    public void setCode(String code) {

        this.code = code;

    }

 

    public List<User> getResult() {

        return result;

    }

 

    public void setResult(List<User> result) {

        this.result = result;

    }

 

    @Override

    public String toString() {

        return "AjaxResponseResult [msg=" + msg + ", code=" + code + ", result=" + result + "]";

    }

 

}

 

9. Class SearchCriteria.java

 

package com.codewr.web.model;

 

/**

 *

 * @author codewr

 */

public class SearchCriteria {

 

    String username;

    String email;

 

    public String getUsername() {

        return username;

    }

 

    public void setUsername(String username) {

        this.username = username;

    }

 

    public String getEmail() {

        return email;

    }

 

    public void setEmail(String email) {

        this.email = email;

    }

 

    @Override

    public String toString() {

        return "SearchCriteria [username=" + username + ", email=" + email + "]";

    }

 

}

 

10. Class User.java

 

package com.codewr.web.model;

 

import com.fasterxml.jackson.annotation.JsonView;

import com.codewr.web.jsonview.Views;

 

/**

 *

 * @author codewr

 */

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;

 

    public User() {

    }

 

    public User(String username, String password, String email, String phone, String address) {

        super();

        this.username = username;

        this.password = password;

        this.email = email;

        this.phone = phone;

        this.address = address;

    }

 

    public String getUsername() {

        return username;

    }

 

    public void setUsername(String username) {

        this.username = username;

    }

 

    public String getPassword() {

        return password;

    }

 

    public void setPassword(String password) {

        this.password = password;

    }

 

    public String getEmail() {

        return email;

    }

 

    public void setEmail(String email) {

        this.email = email;

    }

 

    public String getPhone() {

        return phone;

    }

 

    public void setPhone(String phone) {

        this.phone = phone;

    }

 

    public String getAddress() {

        return address;

    }

 

    public void setAddress(String address) {

        this.address = address;

    }

 

    @Override

    public String toString() {

        return "User [username=" + username + ", password=" + password + ", email=" + email + ", phone=" + phone

                + ", address=" + address + "]";

    }

 

}

 

11. File welcome.jsp

 

<%@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>

        <title>Spring MVC 4 + Ajax Hello World</title>

 

        <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>

                &copy; <a href="http://www.codewr.com">Codewr.com</a> 2018

            </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>

 

12. File logback.xml

 

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

<configuration>

 

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

        <layout class="ch.qos.logback.classic.PatternLayout">

            <Pattern>

                %d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n

            </Pattern>

        </layout>

    </appender>

 

    <logger name="org.springframework" level="debug" additivity="false">

        <appender-ref ref="STDOUT" />

    </logger>

      

    <logger name="com.codewr.ajax" level="debug" additivity="false">

        <appender-ref ref="STDOUT" />

    </logger>

        

    <root level="error">

        <appender-ref ref="STDOUT" />

    </root>

 

</configuration>

 

13.  Run web

http://localhost:8080/spring4-mvc-maven-ajax-example/

 

Input Codewr1 and search:

 

14. Link down full code:

https://github.com/sieurobo196/Spring-MVC/tree/master/SpringMVC-Ajax-Example