Bottom Line: Make sure to include these response headers on every request:
private void fixHeaders(HttpServletResponse response) {
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "GET, PUT, POST, OPTIONS, DELETE");
response.addHeader("Access-Control-Allow-Headers", "Content-Type");
response.addHeader("Access-Control-Max-Age", "86400");
}
If you know the specific domain(s) you want to allow access to the Servlet, make sure "Access-Control-Allow-Origin" is as restrictive as possible for security reasons.
Make sure to include a doOPTIONS() method in your servlet:
protected void doOptions(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
fixHeaders(response);
}
Make sure to catch all Exceptions AND Throwables (If we don't catch all exceptions, the headers that allow cross-domain access won' be included in the response- thus the client won't know what went wrong):
try {
fixHeaders(response);
// Your code here...
} catch (Exception e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.setContentType("text/plain");
response.getWriter().println(buildErrorMessage(e));
} catch (Throwable e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.setContentType("text/plain");
response.getWriter().println(buildErrorMessage(e));
}
Example buildErrorMessage Code:
private static String buildErrorMessage(Exception e) {
String msg = e.toString() + "\r\n";
for (StackTraceElement stackTraceElement : e.getStackTrace()) {
msg += "\t" + stackTraceElement.toString() + "\r\n";
}
return msg;
}
private static String buildErrorMessage(Throwable e) {
String msg = e.toString() + "\r\n";
for (StackTraceElement stackTraceElement : e.getStackTrace()) {
msg += "\t" + stackTraceElement.toString() + "\r\n";
}
return msg;
}