0

I was told that writing HTML to the response.getWriter() in a Servlet is not a good practice and thats why JSP comes into picture.

But in case of Ajax what I have seen is that I have to write HTML to the response.getWriter() in a Servlet for it to be picked by responseText property of the XMLHttpRequest object in the JSP.

Is there any other way for Ajax to accomplish the same task?

This is my example. I have 2 dropdowns Location and Department. When user selects a specific location, I display its departments in Department dropdown using Ajax. For testing purpose Locations and Departments are hard-coded.

I have 2 classes Location and Department:

public class Location implements Serializable {
    private int id;
    private String description;
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    public String getDescription() { return description; }
    public void setDescription(String description) { this.description = description; }

    @Override
    public String toString() {
        return "Location [id=" + id + ", description=" + description + "]";
    }
}

public class Department implements Serializable {
    private int id;
    private String description;
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    public String getDescription() { return description; }
    public void setDescription(String description) { this.description = description; }

    @Override
    public String toString() {
        return "Department [id=" + id + ", description=" + description + "]";
    }
}

I have a JSP LocationDepartment.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
function locationChanged() {
    var newLocation = document.getElementById("select_location").value; 
    var ajaxCallObject = getAjaxCallObject();
    ajaxCallObject.onreadystatechange=function() {
        if (ajaxCallObject.readyState==4) {
            if (ajaxCallObject.status==200) {
                alert("locationChanged(): success of ajaxCallObject");
                document.getElementById("div_department").innerHTML = ajaxCallObject.responseText;
            } else {
                alert("locationChanged(): failure of ajaxCallObject");
            }
        }
    }

    ajaxCallObject.open("GET", "DepartmentServlet?location=" + newLocation, true);
    ajaxCallObject.send(null);  
}

function getAjaxCallObject() {
    if (window.XMLHttpRequest) {
        return new XMLHttpRequest();
    } else {
        return new ActiveXObject('Microsoft.XMLHTTP');
    }
}
</script>
</head>
<body>
<form action="">
<table>
    <tr>
        <td>Location</td>
        <td>
        <div id="div_location">
        <select id="select_location" onchange="locationChanged();">
            <option></option>
            <option id="1">Head Office</option>
            <option id="2">Regional Office</option>
        </select>
        </div>
        </td>
    </tr>
    <tr>
        <td>Department</td>
        <td>
        <div id="div_department">
        <select id="select_department">
        </select>
        </div>
        </td>
    </tr>   
</table>
</form>
</body>
</html>

And this is my servlet DepartmentServlet:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("DepartmentServlet: doGet(): START -----");
    String location = null;
    List<Department> departmentList = null;
    Department department = null;
    StringBuffer sb = null;


    location = request.getParameter("location");

    if (location != null && location.equalsIgnoreCase("Head Office")) {

        departmentList = new ArrayList<Department>();

        department = new Department();
        department.setId(1);
        department.setDescription("Sales");
        departmentList.add(department);

        department = new Department();
        department.setId(2);
        department.setDescription("Support");
        departmentList.add(department);

    } else if (location != null && location.equalsIgnoreCase("Regional Office")) {

        departmentList = new ArrayList<Department>();

        department = new Department();
        department.setId(1);
        department.setDescription("Sales");
        departmentList.add(department);
    }

    sb = new StringBuffer();        
    sb.append("<select id=\"select_department\">");
    if (departmentList != null) {
        for (Department d : departmentList) {
            sb.append("<option id=\"" + d.getId() + "\">");
            sb.append(d.getDescription());
            sb.append("</option>");
        }
    }       
    sb.append("</select>");

    PrintWriter out = response.getWriter();
    out.write(sb.toString());       
}

One problem I have is that now the Servlet needs to know what is the id of the select tag for Department dropdown in the JSP i.e. "select_department".

UPDATE

I would prefer that the servlet sends the List as the request attribute instead. So basically Servlet does not have these lines of codes:

sb = new StringBuffer();        
sb.append("<select id=\"select_department\">");
if (departmentList != null) {
    for (Department d : departmentList) {
        sb.append("<option id=\"" + d.getId() + "\">");
        sb.append(d.getDescription());
        sb.append("</option>");
    }
}       
sb.append("</select>");
PrintWriter out = response.getWriter();
out.write(sb.toString());       

And instead Servlet have this line of code:

request.setAttribute("DepartmentList", departmentList);

and then in the JSP I can access this attribute of request in the callback function of Ajax and loop through it and build the new HTML of select tag and then replace the current one.

Thanks

ChumboChappati
  • 1,442
  • 4
  • 18
  • 38
  • If the issue is knowing the id of the select, why not just send the options and put them in the select's `.innerHTML`? (rather than sending the whole select and putting it in the containing div's `.innerHTML`) – developerwjk Mar 30 '15 at 19:00
  • Hi, I just update the question. You are right that about select's `.innerHTML`. My real question is how to access the request attribute in case of Ajax call – ChumboChappati Mar 30 '15 at 19:30
  • After setting request attribute, you can forward to a jsp that builds the HTML from that list. What ultimately will be received in the Ajax callback is the output from the response (in that case, what is printed by the JSP you forwarded to). – developerwjk Mar 30 '15 at 19:54
  • @ChumboChappati take a look at JQuery method [getJSON()](http://stackoverflow.com/questions/11269261/passing-json-array-from-jsp-to-javascript-using-jquery) – Sas Mar 30 '15 at 20:23

2 Answers2

0

the whole idea of Ajax calls is to send Data. Instead of sending html response send a json/xml from backend and let the front html/js build the html using a supported template technologies provided by jquery or any other js library.

learningJava
  • 188
  • 6
0

Here is an example with getJSON I've mentioned in the comment:

JSP:

$(document).ready(function() {
      $.getJSON("http://localhost:8080/TestWeb/test", function(data) {
      $.each(data, function(key, val) {
        console.log(key+' '+ val);
    });
  });
});

Servlet:

Map<String, Object> data = new HashMap<String, Object>();
data.put( "name", "Mars" );
data.put( "age", 32 );
data.put( "city", "NY" );
JSONObject json = new JSONObject();
json.putAll( data );
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().println(json);
Sas
  • 2,473
  • 6
  • 30
  • 47