sofs1
sofs1

Reputation: 4176

How to use the AJAX response to modify existing url in a Spring mvc project?

I am working on a Spring MVC project where the homepage has two input fields. Both input fields are of String type. But the regNo field gets number and if the user enters the regNo it should be taken to the corresponding method in controller. If the user enters the name, it should be taken to the corresponding method in controller.

web.xml

<web-app version="2.2" id="WebApp_ID">

    <!-- <display-name>Archetype Created Web Application</display-name> -->

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appContext.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/dispatcher-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/mvc/*</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>/WEB-INF/jsp/template.jsp</welcome-file>  
    </welcome-file-list>
</web-app>

1) What is the purpose of id="WebApp_ID"?

tiles.xml

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

<!DOCTYPE tiles-definitions PUBLIC    
  "-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"   
     "http://tiles.apache.org/dtds/tiles-config_2_1.dtd">


<tiles-definitions>
    <definition name="template" template="/WEB-INF/jsp/template.jsp">
        <put-attribute name="title" value=""/>
        <put-attribute name="header" value="/WEB-INF/jsp/header.jsp" />
        <put-attribute name="body" value="/WEB-INF/jsp/ads.jsp  "/>
        <put-attribute name="center" value="/WEB-INF/jsp/ads.jsp" />
        <put-attribute name="footer" value="/WEB-INF/jsp/footer.jsp" /> 
    </definition>

    <definition name="header" extends="template">
        <put-attribute name="title" value="" />  
        <put-attribute name="body" value="/WEB-INF/jsp/ads.jsp" />  
    </definition>

    <definition name="numberResult" extends="template">
        <put-attribute name="title" value="" />  
        <put-attribute name="body" value="/WEB-INF/jsp/nResult.jsp" />  
    </definition>

    <definition name="nameResult" extends="template">
        <put-attribute name="title" value="" />  
        <put-attribute name="body" value="/WEB-INF/jsp/neResult.jsp" />  
    </definition>

dispatcher-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:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
                    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd     
                    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <context:component-scan base-package="com.ProjectCtxt.www.controller"/>

    <mvc:annotation-driven />

    <mvc:resources mapping="/resources/**" location="/resources/" />

  <!--   <bean id="jspViewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/WEB-INF/jsp/"
          p:suffix=".jsp" /> -->

      <bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
            <property name="definitions">
                <list>
                    <value>/WEB-INF/tiles.xml</value>                       
                </list>
            </property>        
        </bean>

       <bean class="org.springframework.web.servlet.view.tiles2.TilesViewResolver"/>

        <bean id="tilesViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
            <property name="viewClass">
                <value>
                    org.springframework.web.servlet.view.tiles2.TilesView
                </value>
            </property>
        </bean>  

</beans>

ProjectController.java

@Controller("resultController")
public class ResultController {

    private final ResultService resultService;

    @Autowired
    public ResultController(ResultService resultService) {
        this.resultService = resultService;
    }


    @RequestMapping(value ="/template", method = RequestMethod.GET)
    public String getPersonList(ModelMap model) {
        System.out.println("We are coming into this place");
        return   "header";
    }


    @RequestMapping(value = "/search/s", method = RequestMethod.GET, params = { "regNo" })
    public String getStudentResult(@RequestParam(value = "regNo", required = true) String regNo, ModelMap model){
        System.out.println("I am coming here when I enter regNo and AJAX works");
        model.addAttribute("studentResult",resultService.getStudentResult(regNo));      
        return "numberResult";
    }


    @RequestMapping(value = "/search/l/studentName={studentName}", method = RequestMethod.GET, params = { "studentName" })
    public String anotherMethod(String studentName, ModelMap model){

        return "nameResult";
    }
}

header.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>


 <head>
 <script src="http://code.jquery.com/jquery.min.js"></script>

 </head>


      <form method="GET" >
                <input  type="text" id="regNo" name="regNo" size="30" maxLength="50" placeholder="Enter Register Number"></input>      
                <input  type="text" id="studentName" name="studentName" size="30" maxLength="50" placeholder="Enter Student Name"></input>

                <button onclick="processInput();">Search
                </button>
    </form>

<script>
 function processInput(){  
     if (document.getElementById('regNo').value !=""){

          $.ajax({  
                type : 'GET',  
                url : "search/s",  
                data : { "regNo":$("#regNo").val()},
                success : function(studentResult) {  
                    //show your result
                   // alert("Value");
                    $('#displayArea').html(studentResult);  }  
            });  
        }else if (document.getElementById('studentName').value !=""){
            $.ajax({  
                type : 'GET',  
                url : "search/l",  
                data : { "studentName":$("#studentName").val(),
                success : function(result) {  
                    //show your result
                }}  
            });
        }  
}  
 </script>

template.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
   <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>

<!DOCTYPE   html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

</head>
<center>
    <table width="750" border="0" cellpadding="2" cellspacing="2" align="center">
    <tr>
        <td><tiles:insertAttribute name="header" />
        </td>
    </tr>
    <tr>       
        <td><tiles:insertAttribute name="body" /></td>
    </tr>
    <tr>
        <td height="225"><tiles:insertAttribute name="footer" />
        </td>
    </tr>
</table>
</center>
</html>

numberResult.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>



 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
 <c:out value="This is working"/>
  <c:out value="${studentResult.name}"/><br/>
  <c:out value="${studentResult.regNo}"/><br/>
    <c:out value="${studentResult.deptName}"/><br/>
      <c:out value="${studentResult.collName}"/><br/>

<div id="displayArea">
 <c:out value="${studentResult.name}"/><br/>
  <c:out value="${studentResult.regNo}"/><br/>
    <c:out value="${studentResult.deptName}"/><br/>
      <c:out value="${studentResult.collName}"/><br/>

</div>       

2) User enters the regNo in header.jsp,and I want the result to be shown in numberResult.jsp

3) My first url is localhost:8080/ProjectCtxt/mvc/template goes to homepage. When I enter regNo in the input field, my url in browser shows localhost:8080/ProjectCtxt/mvc/template/regNo=123&studentName= . And I am reaching the getStudentResult method as I could see my System.out in console, but I am not able to see the output in browser.

Since I am using tiles, I am not sure the problem is with tiles resolver or the AJAX. Could you please help me? Thanks.

PS: Please answer all questions if possible with numbers so that it will help others. Thanks.

UPDATE: I changed my header.jsp as follows and now I see "numberResult" in UI. But I don't see the numberResult jsp as body of template.jsp. I guess the "numberResult" text is returned to success part of AJAX.

  <input  type="text" id="regNo" name="regNo" size="30" maxLength="50" placeholder="Enter Register Number"></input>      
  <input  type="text" id="studentName" name="studentName" size="30" maxLength="50" placeholder="Enter Student Name"></input>
  <input id="inputFields" type="button" value="Search" />


<script>
$(document).ready(function(){
    $('#inputFields').click(function(){
       processInput();
    });
  });


 function processInput(){  
     if (document.getElementById('regNo').value !=""){

          $.ajax({  
                type : 'GET',  
                url : "search/s",  
                data : { "regNo":$("#regNo").val()},
                success : function(studentResult) {  
                    //show your result
                    alert("Value");
                    $('#displayArea').html(studentResult);  //this line displays text //"numberResult". But it doesn't change the jsp as well as the url. Now my url looks as //localhost:8080/mvc/template and the body of the jsp doesn't have numberResult.jsp
                    }  
            });  
        }else if (document.getElementById('studentName').value !=""){
            $.ajax({  
                type : 'GET',  
                url : "search/l",  
                data : { "studentName":$("#studentName").val(),
                success : function(result) {  
                    //show your result
                }}  
            });
        }  
}  
 </script>


<div id="displayArea">
 <c:out value="${studentResult.name}"/><br/>
  <c:out value="${studentResult.regNo}"/><br/>
    <c:out value="${studentResult.deptName}"/><br/>
      <c:out value="${studentResult.collName}"/><br/>

</div>  

Upvotes: 1

Views: 2067

Answers (2)

woemler
woemler

Reputation: 7169

EDIT

Okay, I think I misunderstood the initial problem and the expected result. There are a couple problems with your approach.

  1. You are trying to attach an AJAX event to a button that submits a form in a non-asynchronous manner.
  2. You are trying to display the response from the AJAX request in a JSP tag.

Both of these problems are issues of incompatible components. When you submit a form in a non-asynchronous manner, you are requesting a new page, which the browser loads, and your JavaScript does not have time to complete and display results. JSP tags can not be loaded and displayed asynchronously because they need to be processed on the server. This leaves you with two possible solutions:

1. Make the process completely asynchronous.

Remove the form tag, and leave the inputs and buttons:

<input  type="text" id="regNo" name="regNo" size="30" maxLength="50" placeholder="Enter Register Number"></input>      
<input  type="text" id="studentName" name="studentName" size="30" maxLength="50" placeholder="Enter Student Name"></input>
<button id="searchButton">Search</button>

Now there is no form to submit, so you don't have to worry about accidentally overriding your AJAX functionality. Update your JavaScript to read the input values, execute the proper AJAX request, and display the results:

$("#searchButton").on("click", function(){
   if ($('#regNo').val() !=""){

      $.ajax({  
            type : 'GET',  
            url : "search/s",  
            data : { "regNo":$("#regNo").val()},
            success : function(studentResult) {  
                $('#displayArea').html("<p>" + studentResult.id + "</p><p>" + studentResult.name + "</p><p>etc...</p>);  }  
        });  
    }else if (document.getElementById('studentName').value !=""){
        $.ajax({  
            type : 'GET',  
            url : "search/l",  
            data : { "studentName":$("#studentName").val(),
            success : function(result) {  
                //show your result
            }}  
        });
    }  
});

Make sure that the controller handling your AJAX method is set up to return an object JavaScript can understand. Spring should be able to serialize most objects you give it:

@RequestMapping(value = "/search/s", method = RequestMethod.GET, params = { "regNo" })
public @ResponseBody StudentResult getStudentResult(@RequestParam(value = "regNo") String regNo){
    return resultService.getStudentResult(regNo);
}

2. Make the process completely non-asynchronous

If you are set on using your JSP tag to display the data, you can scrap the AJAX and submit the form in the usual fashion:

<form method="POST">
    <input  type="text" id="regNo" name="regNo" size="30" maxLength="50" placeholder="Enter Register Number"></input>      
    <input  type="text" id="studentName" name="studentName" size="30" maxLength="50" placeholder="Enter Student Name"></input>
    <button id="searchButton">Search</button>
</form>

You can supply an action attribute if you would like the form to POST or perform a GET to a different URL. Create a single controller method to handle the submission:

@RequestMapping(value = "/someUrl", method = RequestMethod.POST)
public String getStudentResult(@RequestParam(value = "regNo", required = false) String regNo, @RequestParam(value = "studentName", required = false) String studentName, ModelMap model){
    if (regNo != null && !regNo.equals("")){
        model.addAttribute("studentResult",resultService.getStudentResult(regNo));      
        return "numberResult";
    } else if (studentName != null && !studentName.equals("")){
        model.addAttribute("nameResult", someOtherObject);
        return "nameResult";
    } else {
        model.addAttribute("errorMessage", "No form data supplied!");
        return "someOtherView";
    }
}

Now, as long as you have your views set up to accept the returned objects and map them in your JSTL, your tags should work just fine.

Upvotes: 1

Tung Vo
Tung Vo

Reputation: 2549

Try put anotation @ResponseBody to your controller

@RequestMapping(value = "/search/s", method = RequestMethod.GET, params = { "regNo" })
@ResponseBody
public String getStudentResult(@RequestParam(value = "regNo", required = true) String regNo, ModelMap model){
    System.out.println("I am coming here when I enter regNo and AJAX works");
    model.addAttribute("studentResult",resultService.getStudentResult(regNo));      
    return "success";
}

Upvotes: 1

Related Questions