From my client side code, I am making an AJAX call to my servlet. If I use GET as request method. Everything works and I get response back. But when I send request as POST, servlet fails to send the response. From log I found out that in servlet "request" object is null when made ajax call with POST. According to this post:
Servlet response to AJAX request is empty , I'm setting headers for same-origin policy.
Below is my code for reference:
function aimslc_ajaxCall(url,callback, postParams){
var xmlhttp = null
if (window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
eval( callback+"("+xmlhttp.responseText+")" );
}
}
if(postParams!=null && typeof postParams!="undefined" ){
xmlhttp.open("POST",url,true);
xmlhttp.send(postParams);
}else{
xmlhttp.open("GET",url,true);
xmlhttp.send();
}
}
Servlet Code:
public void doProcess (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
logger.info("doProcess::start..."+request.getQueryString());
response.setHeader("P3P","CP='NOI ADM DEV PSAi COM NAV OUR OTR STP IND DEM'");
response.setHeader("Access-Control-Allow-Origin","*");
response.setHeader("Access-Control-Allow-Credentials","true");
response.setHeader("Access-Control-Allow-Methods","POST, GET");
}
Throws a null exception on request.getQueryString()
if you do a post all the data is in the request body, not on the url. From here you see that getQueryString only gets the stuff on the url.
See here for how to get the request body.
Also, if your data is name/value pairs, you might want to use getParameter and associated methods.
If the request is null, I ask do you implement doPost on your servlet?
Related
I'm working with Spring and have 2 controllers, one of them is:
#RequestMapping("/meni/{id}")
public String meni(#PathVariable String id, Model model, HttpServletRequest request, HttpServletResponse response){
cookie = new Cookie("fake_session",id);
cookie.setMaxAge(30*60);
response.addCookie(cookie);
return "meni";
}
Then in the 'meni' static HTML page, I have a post request that goes to:
#PostMapping("/index/{id}")
public void post(#PathVariable String id,#RequestBody TestDTO testDTO, HttpServletResponse response, HttpServletRequest request){
Cookie [] cookies = request.getCookies();
for (int i=0;i<cookies.length;i++){
Cookie cookie = cookies[i];
if (cookie.getName().equals("fake_session")){
System.out.println("Same cookie!");
}
}
However, the if never gets passed. If i go to the get controller twice, it recognizes the cookie, but if i go the post controller, it the if does not get passed. Everything else is running smoothly in the post controller, it does all its other tasks well.
I go to the Post controller by clicking a button that calls a ajax function in my java script that sends a POST request to that URL. Am I suppose to do something with the cookie there maybe ? I always go to the GET controller before going to the post controller so that the cookie gets created.
Try using Spring MVC's #CookieValue(value = "fake_session", defaultValue = "default") to access data set within any HTTP cookie in your post method.
I am trying to set an attribute to session cookie and use that attribute for subsequent requests (after the very first request). Following is my code. Here I am using check variable to check the functionality of the code. For the very first request, it should give me "init" and "original" for subsequent requests. But, I am getting "init" as the output for all requests. What is the reason for this issue?
#Override
protected void doGet(HttpServletRequest reqest, HttpServletResponse response) throws IOException {
HttpSession ssn = reqest.getSession();
reqest.getSession(true);
String check="original";
if(ssn.getAttribute("currentQuestion")==null){
check="init";
ssn.setAttribute("currentQuestion","0");
}
response.addHeader("Access-Control-Allow-Origin", "*");
response.getWriter().println(check);
}
I am using folloeing AJAX client to send requests
function submitAnswer() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML = this.responseText;
}
};
xhttp.open("GET", "http://example.com:8080/Simple/hello?username=malintha", true);
xhttp.send();
}
The logic of your code is fine. However, I notice you are calling getSession twice. This is not necessary. Try removing the second getSession(true) call.
Also, make sure you use an external browser such as Chrome or Firefox instead of the browser built into eclipse.
I have a single page application, written using Jquery, java is used at the back-end.
After session timeout, If user do some activity which triggers Ajax call, then user should be redirected to login screen.
If It would have been an another page request, then following solution might have worked, but as it is Ajax call, redirection just give another response to success function.
I Tried
In main Filter
HttpSession session = request.getSession(false);
if(session != null && !session.isNew()) {
chain.doFilter(request, response);
}else {
response.sendRedirect("/login.jsp");
}
Refreshing the tab by sending below header on ajax call, from inside main filter
httpResponse.setHeader("Refresh", "0; URL=" + targetUrl);
server side: Add a filter, which will be processed for every single request, inside that filter's doFilter method add following code:
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpSession session = httpRequest.getSession(false);// don't create if it doesn't exist
if(session == null || session.isNew()) {
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // status code is 401
}else{
// pass the request along the filter chain
chain.doFilter(request, response);
}
client side: configure ajax such that when it receives any response with status code 401, it reloads the tab or change the window.location. This is how it can be done using jquery:
$(window).load(function(){
$.ajaxSetup({
statusCode: {
401: function(){
location.reload(); // or window.location="http://www.example.com"
}
}
});
});
for me reloading was enough, to take the user to login screen
One way you can do it is by
having a common code for doing your ajax call
Calling the backend from there
Have logic setup
if(response.status==403 || 404 or any code){
window.location = "http://your.login.page";
}
I am using JSF2. I have implemented a custom faces servlet like so:
public class MyFacesServletWrapper extends MyFacesServlet {
// ...
}
wherein I'm doing some authorization checks and sending a redirect when the user is not logged in:
public void service(ServletRequest request, ServletResponse response) {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
if (...) {
String loginURL = req.getContextPath() + "/LoginPage.faces";
res.sendRedirect(loginURL);
}
}
This works when the user tries to navigate to another page. However, this does not work when a JSF form is submitted by a JSF command link/button. The line sendRedirect() line is hit and executed, no exception is been thrown, but the user stays at the same page. Basically, there's no visual change at all.
Why does this work on page navigation, but not on form submit?
Your concrete problem is most likely caused because your JSF command link/button is actually sending an ajax request which in turn expects a special XML response. If you're sending a redirect as response to an ajax request, then it would just re-send the ajax request to that URL. This in turn fails without feedback because the redirect URL returns a whole HTML page instead of a special XML response. You should actually be returning a special XML response wherein the JSF ajax engine is been instructed to change the current window.location.
But you've actually bigger problems: using the wrong tool for the job. You should use a servlet filter for the job, not a homegrown servlet and for sure not one which supplants the FacesServlet who is the responsible for all the JSF works.
Assuming that you're performing the login in a request/view scoped JSF backing bean as follows (if you're using container managed authentication, see also 2nd example of Performing user authentication in Java EE / JSF using j_security_check):
externalContext.getSessionMap().put("user", user);
Then this kickoff example of a filter should do:
#WebFilter("/*") // Or #WebFilter(servletNames={"facesServlet"})
public class AuthorizationFilter implements Filter {
private static final String AJAX_REDIRECT_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<partial-response><redirect url=\"%s\"></redirect></partial-response>";
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
String loginURL = request.getContextPath() + "/login.xhtml";
boolean loggedIn = (session != null) && (session.getAttribute("user") != null);
boolean loginRequest = request.getRequestURI().equals(loginURL);
boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER + "/");
boolean ajaxRequest = "partial/ajax".equals(request.getHeader("Faces-Request"));
if (loggedIn || loginRequest || resourceRequest)) {
if (!resourceRequest) { // Prevent browser from caching restricted resources. See also https://stackoverflow.com/q/4194207/157882
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.
}
chain.doFilter(request, response); // So, just continue request.
}
else if (ajaxRequest) {
response.setContentType("text/xml");
response.setCharacterEncoding("UTF-8");
response.getWriter().printf(AJAX_REDIRECT_XML, loginURL); // So, return special XML response instructing JSF ajax to send a redirect.
}
else {
response.sendRedirect(loginURL); // So, just perform standard synchronous redirect.
}
}
// ...
}
See also:
Using JSF 2.0 / Facelets, is there a way to attach a global listener to all AJAX calls?
FullAjaxExceptionHandler does not show session expired error page on ajax button
FacesContext.getCurrentInstance().getExternalContext().redirect("newpage.xhtml"); try this.... in place of res.sendredirect(cpath).
In the blog-edit.html, JQuery was used to send the post request to the sever side(java servlet).
$("#btn").click(function() {
$.post("/blog/handler",{"content":$('#textarea').val()},
function(data){
alert("Data Loaded: " + data);
if(data.toString().length>1){
alert("Saved!")
}else{
alert("Failed!")
}
})
In the server side:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String content = request.getParameter("content");
System.out.println(content);
response.sendRedirect("/blog/list");
return;
}
What I saw is the server side is printing the content from the html, and the alert window pops up to say "Saved!". But the redirect function doesn't work
After searching I have no choice but to use jquery to redirect:
if(data.toString().length>1){
alert("Saved!")
window.location.replace("/blog/list")
}
it works, but it's not what i want
please help
While using ajax. you can not execute server side redirect.
However, there are better way how to redirect on client in such a scenario.
See Here