This post documents an issue I encountered in a legacy Spring MVC environment using a company-wide common framework
It wasn’t just a bug fix , it led me to finally understand the true behavior of Ajax,
how the browser interprets responses, and how legacy frameworks influence the entire flow.
1. The Problem
“The server is fine, no JavaScript errors… but the Ajax callback never fires.”
The page flow looked like this:
Menu Click → openXXX.do → ModelAndView Controller
→ JSP render → JavaScript load → document.ready()
→ Ajax request → callback() updates the table
Plain Text
복사
But the callback was never executed.
Even worse
•
No JavaScript errors
•
Server logs clean
•
HTTP 200 OK
•
Ajax request appears as “successful” in DevTools
Yet… nothing happens on the screen.
This is one of the most frustrating types of problems in web development.
2. Symptoms (The “Drive-You-Crazy” Type)
Server-side : no exceptions
Browser console : no errors
Network tab : HTTP 200 OK
Ajax request appears normal
But : success/callback NEVER fires
This is the kind of issue that will make any developer lose their mind.
And that’s what happened to me, I spent almost an entire day chasing this.
3. The Key Discovery
When I inspected the Network → Response tab more closely…
The Ajax response was not JSON, but a JSP (HTML).
At that moment, everything clicked.
Ajax was expecting JSON,
but the server responded with HTML —
and that is why the callback never fired.
But why did the server return JSP instead of JSON?
To understand this, we need to clarify one huge misconception.
4. The Big Misconception About Ajax Success
Most developers (including me, until this incident) believe this:
“If the server returns HTTP 200 OK and no errors occurred, Ajax success will run.”
This is wrong.
Very wrong.
5. The Truth : Ajax success Does NOT Mean Server Success
Ajax success = Client-side “response parsing success”
jQuery fires success() only if both of these conditions are met:
(1) HTTP status is 2xx
AND
(2) jQuery successfully parses the response into the type specified by dataType
If JSON was expected, but
•
server sends HTML
•
server sends malformed JSON
•
Content-Type is wrong
•
response begins with whitespace
•
session timeout returns login page
→ JSON parsing fails → jQuery does NOT call success/callback.
This is exactly what happened to me.
6. Why Did the Server Return HTML Instead of JSON?
This was the tricky part.
Our company has strict URL conventions:
•
Screen entry URLs always use openXXX.do
•
These URLs must return ModelAndView → JSP
•
Legacy framework routes them through “screen-loading pipelines”
I didn’t know this and made the rookie mistake:
I registered a data-retrieval Ajax URL using the same pattern as screen-entry URLs.
Example
retrieveSftyInscRsltLst.do
Plain Text
복사
The legacy framework interpreted this URL as a screen-render URL,
and therefore returned HTML instead of JSON.
Ajax expected JSON → received HTML → failed parsing → no callback.
Now the entire issue suddenly made sense.
7. The Solution
Separate “screen entry” and “Ajax retrieval” URLs
Since the screen-entry URL cannot be modified (company-wide standard),
I created a separate retrieval-only URL:
retrieveSftyInscRsltLst2.do
Plain Text
복사
New Ajax controller returning JSON
@RequestMapping("/spc/exmlcarg/simlcsl/retrieveSftyInscRsltLst2.do")
public String retrieveList2(..., ModelMap model) {
model.addAttribute("totCnt", totCnt);
model.addAttribute("resultList", resultList);
return "jsonView"; // Ensure JSON response
}
Java
복사
Ajax now calls the new URL
$form.kcs4gAjaxFormSubmit({
url : '/spc/exmlcarg/simlcsl/retrieveSftyInscRsltLst2.do',
type : 'POST',
data : {...},
callback : function(result) {
console.log(result);
...
}
});
JavaScript
복사
Callback started firing immediately. Problem solved.
8. Final End-to-End Flow (Now Cleanly Understood)
[1] User clicks menu → openXXX.do
[2] Legacy controller returns ModelAndView
[3] JSP rendered
[4] JS files loaded
[5] document.ready() triggers the first Ajax call
[6] Ajax hits retrieveXXX2.do (JSON endpoint)
[7] Server returns jsonView
[8] jQuery successfully parses JSON → success
[9] Legacy common success handler → callback(result)
[10] Page table renders normally
Plain Text
복사
This clear separation fixed everything.
9. Bonus : Understanding success vs callback
In our environment:
•
success = jQuery’s native Ajax success handler
•
callback = company’s wrapper function that runs after common logic
(session check, resultCode check, global error handling, etc.)
If callback() is not called,
that means success() itself never fired,
which means parsing failed.
This is how I confirmed the issue was on the Ajax → response → parsing side.
10. Key Lessons Learned
1. Ajax success is based on client-side parsing, not server success
Even if the server is 100% correct,
HTML instead of JSON will prevent success() from firing.
2. Legacy frameworks can override URL behavior
URL naming matters more than you think.
3. Always check Network → Response before debugging code
If the response is HTML, XML, or a login page,
Ajax callback will never fire.
4. Separate screen-entry URLs and data-fetch URLs
Especially in enterprise systems:
mixing them will cause unpredictable behavior.
5. A single URL naming mistake can break the entire flow
This mistake cost me almost a full day, but I learned the lesson well.
11. Conclusion
This issue was more than a bug;
it gave me a much deeper understanding of:
•
Ajax internals
•
JSON parsing
•
HTTP request/response behavior
•
Legacy framework routing
•
jQuery’s success logic
•
And the importance of clean URL design
From now on, whenever an Ajax callback doesn’t fire,
I’ll always ask
“Is the response really in the format my Ajax call expects?”
Because 90% of the time, that’s exactly where the problem is.



