Understanding AJAX GET Requests
AJAX (Asynchronous JavaScript and XML) allows web pages to send and receive data asynchronously without reloading the page. This section covers the imlpementation of GET requests using the XMLHttpRequest object.
Basic GET Request Example
The following HTML page sends a GET request when a button is clicked and displays the server response in a div element.
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Basic AJAX GET</title>
</head>
<body>
<input type="button" value="Fetch Data" id="fetchBtn">
<div id="output"></div>
<script>
window.onload = function() {
document.getElementById("fetchBtn").onclick = function() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState === 4) {
if (this.status === 200) {
document.getElementById("output").innerHTML = this.responseText;
} else if (this.status === 404) {
alert("Resource not found");
} else if (this.status === 500) {
alert("Server error");
}
}
};
xhr.open("GET", "/app/demoServlet", true);
xhr.send();
};
};
</script>
</body>
</html>
On the server side, a servlet handles the GET request and returns a simple string response.
package com.example.web;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/demoServlet")
public class DemoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
PrintWriter out = resp.getWriter();
out.print("Hello from AJAX!");
}
}
GET Request with Query Parameters
Data can be sent to the server via URL parameters. The following example sends a username and age.
<html lang="en">
<head>
<meta charset="UTF-8">
<title>GET with Params</title>
</head>
<body>
<input type="button" value="Send Params" id="sendBtn">
<script>
window.onload = function() {
document.getElementById("sendBtn").onclick = function() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/app/userServlet?name=John&age=25", true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
alert(xhr.responseText);
}
};
xhr.send();
};
};
</script>
</body>
</html>
The server reads the parameters and returns a response.
package com.example.web;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/userServlet")
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String name = req.getParameter("name");
String age = req.getParameter("age");
resp.setContentType("text/xml;charset=utf-8");
PrintWriter out = resp.getWriter();
out.print("Name: " + name + ", Age: " + age);
}
}
GET Request Caching Issues
Older versions of Internet Explorer (and some browsers) may cache identical GET requests. This means the second request may not reach the server, returning stale data. To avoid this, append a unique timestamp or random number to the URL.
// Append a timestamp to prevent caching
xhr.open("GET", "/app/data?t=" + new Date().getTime(), true);
// Or use Math.random()
xhr.open("GET", "/app/data?r=" + Math.random(), true);
POST requests, in contrast, are never cached by browsers.
AJAX POST Requests
POST requests differ from GET mainly in how data is sent. Data is placed in the request body rather than the URL, and the Content-Type header must be set appropriately.
Key Differences in Client Code
var xhr = new XMLHttpRequest();
xhr.open("POST", "/app/submit", true);
// Must set Content-Type for form data
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
xhr.send("username=" + encodeURIComponent(username) + "&password=" + encodeURIComponent(password));
Use Case: Username Availability Check
This example validates a username during registration using a POST request on blur event.
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Username Validation</title>
</head>
<body>
Username: <input type="text" id="usernameField">
<span id="resultMsg"></span>
<script>
window.onload = function() {
document.getElementById("usernameField").onblur = function() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
document.getElementById("resultMsg").innerHTML = xhr.responseText;
}
};
xhr.open("POST", "/app/checkUsername", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var username = document.getElementById("usernameField").value;
xhr.send("username=" + encodeURIComponent(username));
};
};
</script>
</body>
</html>
Server-side servlet checks database for existing username.
package com.example.web;
import com.example.util.DBHelper;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@WebServlet("/checkUsername")
public class UsernameCheckServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
String username = req.getParameter("username");
try (Connection conn = DBHelper.getConnection();
PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE username = ?")) {
ps.setString(1, username);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
out.write("<font color='red'>Username already taken</font>");
} else {
out.write("<font color='green'>Username available</font>");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
A database utility class is used to manage connections.
package com.example.util;
import java.sql.*;
import java.util.ResourceBundle;
public class DBHelper {
private static final ResourceBundle bundle = ResourceBundle.getBundle("config/db");
private static final String DRIVER = bundle.getString("driver");
private static final String URL = bundle.getString("url");
private static final String USER = bundle.getString("user");
private static final String PASSWORD = bundle.getString("password");
private static ThreadLocal<Connection> threadConn = new ThreadLocal<>();
static {
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
Connection conn = threadConn.get();
if (conn == null) {
conn = DriverManager.getConnection(URL, USER, PASSWORD);
threadConn.set(conn);
}
return conn;
}
public static void close(Connection conn, Statement stmt, ResultSet rs) {
try { if (rs != null) rs.close(); } catch (SQLException e) { e.printStackTrace(); }
try { if (stmt != null) stmt.close(); } catch (SQLException e) { e.printStackTrace(); }
try { if (conn != null) { conn.close(); threadConn.remove(); } } catch (SQLException e) { e.printStackTrace(); }
}
}
Configuration file (e.g., config/db.properties):
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb
user=root
password=root
Use Case: Display Student List
This example loads a list of students from the database and populates a table. Note that in production, it's bettter to return data (JSON/XML) rather than pre-formatted HTML.
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Student List</title>
</head>
<body>
<input type="button" value="Load Students" id="loadBtn">
<table border="1">
<thead>
<tr><th>ID</th><th>Name</th><th>Age</th><th>Address</th></tr>
</thead>
<tbody id="studentBody"></tbody>
</table>
<script>
window.onload = function() {
document.getElementById("loadBtn").onclick = function() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/app/studentList", true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
document.getElementById("studentBody").innerHTML = xhr.responseText;
}
};
xhr.send();
};
};
</script>
</body>
</html>
Server returns HTML table rows.
package com.example.web;
import com.example.util.DBHelper;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@WebServlet("/studentList")
public class StudentListServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
StringBuilder html = new StringBuilder();
try (Connection conn = DBHelper.getConnection();
PreparedStatement ps = conn.prepareStatement("SELECT * FROM students");
ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
String addr = rs.getString("address");
html.append("<tr><td>").append(id).append("</td>")
.append("<td>").append(name).append("</td>")
.append("<td>").append(age).append("</td>")
.append("<td>").append(addr).append("</td></tr>");
}
} catch (Exception e) {
e.printStackTrace();
}
out.print(html.toString());
}
}
Drawback of Server-Side HTML Generation
Mixing HTML with server code makes maintenance difficult. A better approach is to return structured data (e.g., JSON or XML) and let the client handle rendering.