HI,
This question is from previously answered question by BalusC. The excerpt of the answer as follows:
This happens only if under the covers
a forward by
RequestDispatcher#forward() takes
place. In a forward, the
servletcontainer basically reuses the
same HTTP request/response for a view
(JSP/XHTML page). It does not
force/instruct the webbrowser to send
a brand new request.
What this means is every new view is rendered using the forward. The following are my questions:
If the above is the case, then all the views displayed with the same request?. Because, we are always seeing the same URL in the address bar.
Is it that the values in the previous request is retained for the new request?
In this case, if every request is same then is it like storing in the session, for long time. I am bit confused on the view handling by JSF. Want to understand more internal work flow of JSF.
When we use the <redirect/> in faces-config.xml, will the URL in address bar get changed?
If the above is the case, then all the views displayed with the same request?. Because, we are always seeing the same URL in the address bar.
If it concerns a HTTP POST request and the JSF bean action navigates to a different view, then per saldo you will indeed have two different views in the same request. One for the initial view which is been used to gather/convert/validate the necessary request parameters and update the model values and other for the result view which is been used to show some result.
Is it that the values in the previous request is retained for the new request?
In a forward there's no means of a new request. It's the same request.
In this case, if every request is same then is it like storing in the session, for long time. I am bit confused on the view handling by JSF. Want to understand more internal work flow of JSF.
This is definitely not the case. As to your confusion, it may help to put JSF aside for a while and go playing with plain vanilla JSP/Servlet (which is what JSF is using under the covers). I think the following links may help in getting new insights about how basic JSP/Servlet works and how the average MVC framework on top of JSP/Servlet works:
Servlets tag info page
Design patterns Java web applications
When we use the <redirect/> in faces-config.xml, will the URL in address bar get changed?
Yes. A HTTP redirect sends a HTTP location: newpage.jsf header which in turn instructs the webbrowser to fire a new HTTP GET request on the given location. This get reflected in the browser address bar. You may want to install a HTTP debugging tool like Firebug or Fiddler2 to track HTTP traffic. You'll see that a forward happens inside the same request and a redirect comes with a new request.
If the above is the case, then all the views displayed with the same request?. Because, we are always seeing the same URL in the address bar.
if the url is the same in the web-browser then there can be two cases. either the same request is being forwarded as he mentioned OR new GET request is issued with same URL [which is lesser the case]
Is it that the values in the previous request is retained for the new request?
request life cycle will be from request to response. so after response all the managed bean with request scoped will get destroyed.
When we use the in faces-config.xml, will the URL in address bar get changed?
Yes it will instruct browser to issue new GET request for new URL.
Related
IWS is a desktop application with its own webBrowser component to call Scripting web-app when needed. Scripting is located in a Tomcat6.
Scripting is basically an JSP application. (Really it is an engine who builds an JSP application from the human actions over its graphical interface, like define flows, buttons, content, etc, but I am talking about the "Script" it generates as an JSP)
I need to hack Scripting so it can share space (via frames) in that webBrowser component of IWS application.
The IWS call 2 times to start.jsp:
the first time, in a hidden way (probably a direct http query from IWS code), without any special parameters. The original start.jsp do 2 302 (so the call visits 3 pages total) it ends using the jsesionId both in cookie and as a parameter (but not at the last 302)
second time, with the jSessionId and a bunch of important parameters. It only uses the jSessionId as the parameter. As far as I have seen in fiddler, no cookie is used when it works correctly as jsessionId is inside its own
So I guess that the first time ìt is just to get a new jSessionId.
The solution I am trying now is to replace Scripting starting page with a new frames page which, in one of the two frames it holds, it loads the web aplication, and another application in the second frame. Depending on data from the first frame it will update the second frame.
So something like to:
we had start.jsp... (really it is called something different)
and we end with:
start.app.jsp (which is original start.jsp, just renamed)
start.jsp (is the new including html which wraps the previous start.jsp)
The new start.jsp uses its own url, changing start.jsp into start.app.jsp, to invoke the true Scripting application inside an iframe.
But I have been suffering from like session problems. I am not an expert in tomcat. I learned that it controls the session with cookies or with parameters. I think it is configured to work with the URL sessionId but I am not really sure. I have set META-INF/settings.xml to disable cookie use in sessions, but it still show the cookie in the cookies list.
My problem is that in that second time start.jsp is called, it appear than somethink like an "old cookie" is being used, ignoring the jsessionId from the URL. Some weird errors appear at WWG00000E: WWGAIL - Error: ID was not provided for function getInteractionKVPair Detail:
It is like it is returning to an old cookie with another jsessionid. That 'old' jsessionid is the same each time the error shows up.
Sniffing with fiddler, I see that the second start.jsp starts with the right jsessionId in the URL, but its cookies are like from another session, and it stops to add the jsession id with each redirection since this happens. It is like it is executing in a completely different universe. Is this normal?????
Currently I am trying without avail to force the cookie jSessionId and also the links so they include the jSessionId.
Please, do you have any idea?
Thanks!
Edited2: if I place it without frames (restoring default start.jsp). At IWS works only the first time (interaction), while in any subsequent one the problem start to appear...
Ok, solved at last...
At least with this version of Tomcat:
A call to a jsp without jSessionId creates a new jSessionId in your app cookie.
Any further on in time html request will use the cookie jSessionId instead of the one present on the URL, so you lose any type of multisession support.
It is something special than in a webBrowser component, doing a two steps connections, the first request never have an associated cookie, so it works OK, giving you a cookie with a new jSessionId, and then you can do a new, cookieless, second request which uses the jSessionId of the URL and have not cookie or have "a default" cookie without jSessionId. When this webBrowser requests a jsp page without jSessionId in its URL, as said, the problem starts, so if the first request includes a non jSessionIded call, Tomcat gives you a jSessionId which is set on your "default app cookie", so the second request ignores any URL jSessionId to use the one on that cookie.
In a web browser, I have observed that in at least firefox, cleaning the cookies is not enough to eliminate this "default cookie". But maybe it could be the classic "It takes too long so you think it is clean but really it is not". Not sure.
I know this sounds confusing. I have not the time to do further testing about this.
As far as I have understood, it is like, when it works OK, it is working like with an "session cookie" (without jSessionId), while when it does not work it takes the "default cookie" (with jSessionId) and starts ignoring URL jSessionId.
I have sent an email to the dev mailinglist of Tomcat. (One said that the correct place was the user mailinglist... but here you are ;-) )
My scenario is like this:
I'm building a website where I'm posting an ad regarding a topic. So, after the form filling of ad, the request goes to a REST service class as:
http://localhost:8080/cloudproject/postadvaction?title=tution&tag=tution&description=tution+%401000+%2F+month&category=TUTOR&location=indore
Here, the details of ad go in the database which is MongoDB. After all of this is done I'm redirecting to the profile page of user using Viewable model of jersey, where he can see all the ads posted by him. It is done as:
return new Viewable("/profile.jsp");
After this the response is redirected to profile page of the user.
But the problem is that, on redirecting the response to simply profile.jsp, the URL in the address bar has not changed to http://localhost:8080/profile.jsp, instead, it has remained the same as mentioned above. So, when user refreshes the page, the request of same ad post triggers and the whole process is followed again. Since, database is MongoDB, same ad is stored twice in it and same is displayed on the profile page of user with 2 identical ads.
So, how can I redirect to profile page without having the address of servlet in address bar?
Update: The question is related to PRG technique & Duplicate Form Submissions and not to just redirection.
See Post/Redirect/Get
When a web form is submitted to a server through an HTTP POST request, a web user that attempts to refresh the server response in certain user agents can cause the contents of the original HTTP POST request to be resubmitted, possibly causing undesired results, such as a duplicate web purchase.
To avoid this problem, many web developers use the PRG pattern[1] — instead of returning a web page directly, the POST operation returns a redirection command. The HTTP 1.1 specification introduced the HTTP 303 ("See other") response code to ensure that in this situation, the web user's browser can safely refresh the server response without causing the initial HTTP POST request to be resubmitted. However most common commercial applications in use today (new and old alike) still continue to issue HTTP 302 ("Found") responses in these situations.
With Jersey you can use
Response.seeOther(URI) - Create a new ResponseBuilder for a redirection. Used in the redirect-after-POST (aka POST/redirect/GET) pattern.
You just need to change your method signature to return a Response and return the built Response
return Response.seeOther(URI.create(...)).build();
Also stated about the URI parameter
the redirection URI. If a relative URI is supplied it will be converted into an absolute URI by resolving it relative to the base URI of the application (see UriInfo.getBaseUri()).
This question already has answers here:
RequestDispatcher.forward() vs HttpServletResponse.sendRedirect()
(9 answers)
Closed 6 years ago.
I have got a problem with my page jump when I use JAVA,
if I use:
response.sendRedirect("login.jsp")
then I get this url: http://localhost:8080/login.jsp
But if I use
request.getRequestDispathcer("login.jsp").forward(request, response)
then I get this url: http://localhost:8080/Shopping/login.jsp (the "Shopping" is the name of my module).
What's the difference?
To simply explain the difference,
response.sendRedirect("login.jsp");
doesn't prepend the contextpath (refers to the application/module in which the servlet is bundled)
but, whereas
request.getRequestDispathcer("login.jsp").forward(request, response);
will prepend the contextpath of the respective application
Furthermore, Redirect request is used to redirect to resources to different servers or domains. This transfer of control task is delegated to the browser by the container. That is, the redirect sends a header back to the browser / client. This header contains the resource url to be redirected by the browser. Then the browser initiates a new request to the given url.
Forward request is used to forward to resources available within the server from where the call is made. This transfer of control is done by the container internally and browser / client is not involved.
forward
Control can be forward to resources available within the server from where the call is made. This transfer of control is done by the container internally and browser / client is not involved. This is the major difference between forward and sendRedirect. When the forward is done, the original request and response objects are transfered along with additional parameters if needed.
redirect
Control can be redirect to resources to different servers or domains. This transfer of control task is delegated to the browser by the container. That is, the redirect sends a header back to the browser / client. This header contains the resource url to be redirected by the browser. Then the browser initiates a new request to the given url. Since it is a new request, the old request and response object is lost.
For example, sendRedirect can transfer control from http://google.com to http://anydomain.com but forward cannot do this.
‘session’ is not lost in both forward and redirect.
To feel the difference between forward and sendRedirect visually see the address bar of your browser,
in forward, you will not see the forwarded address (since the browser is not involved)
in redirect, you can see the redirected address.
The main difference between the forward() and sendRedirect() methods is
that in the case of forward(), redirect happens at the server end and
is not visible to the client, but in the case of sendRedirect(),
redirection happens at the client end and it's visible to the client.
Other difference between Forward(ServletRequest request, ServletResponse response) and sendRedirect(String url) is
forward():
The forward() method is executed on the server-side.
The request is transferred to another resource within the same server.
It does not depend on the client’s request protocol since the forward () method is provided by the servlet container.
The request is shared by the target resource.
Only one call is consumed in this method.
It can be used within the server.
We cannot see the forwarded messages, it is transparent.
The forward() method is faster than sendRedirect() method.
It is declared in the RequestDispatcher interface.
sendRedirect():
The sendRedirect() method is executed on the client-side.
The request is transferred to another resource to a different server.
The sendRedirect() method is provided under HTTP so it can be used only with HTTP clients.
New request is created for the destination resource.
Two request and response calls are consumed.
It can be used within and outside the server.
We can see redirected address, it is not transparent.
The sendRedirect() method is slower because when new request is created old request object is lost.
It is declared in HttpServletResponse.
Which one is good? It depends upon the scenario for which method is more useful.
If you want control is transfer to a new server or context, and it is
treated as a completely new task, then we go for sendRedirect.
Generally, a forward should be used if the operation can be safely
repeated upon a browser reload of the web page and will not affect the
result.
1.redirect return the request to the browser from server,then resend the request to the server from browser.
2.forward send the request to another servlet (servlet to servlet).
Redirect and Request dispatcher are two different methods to move form one page to another.
if we are using redirect to a new page actually a new request is happening from the client side itself to the new page.
so we can see the change in the URL.
Since redirection is a new request the old request values are not available here.
I'm redirecting to another page:
String uri = "../test/planOutput.jsf?job_id=121250";
FacesContext.getCurrentInstance().getExternalContext().dispatch(uri);
It works, but the URL doesn't change,
I must see the new URL with the parameter.
What is the solution?
You aren't redirecting the request to a different target at all. You are dispatching the request to a different source. Use ExternalContext#redirect() instead of ExternalContext#dispatch().
FacesContext.getCurrentInstance().getExternalContext().redirect(uri);
A redirect basically instructs the webbrowser to fire a new HTTP request on the given URL. That's also why you see the URL change being reflected in webbrowser's address bar. A dispatch basically instructs the webserver to use a different source for the current request/response. Since this happens internally and does not end up in a new HTTP request, the webbrowser know nothing about the change and the address bar won't be changed.
Is it possible to prevent user from opening JSF page in more than one browser tab or window?
I agree with the accepted solution, but if you still have to do it, these steps worked for me (pseudo code/pseudo python):
On the JS side:
if tabId not set:
. generate random number
. set property in sessionStorage
otherwise:
. get it from sessionStorage
make an ajax callback and send tabId
onError:
. alert();
. close current tab (if possible);
. logout
Backend:(JSF):
Create custom filter:
if request contains the tabId info:
if it matches session's tabId: (being tabId not null)
sent response status code to an error such as forbidden
Optionally invalidate session
otherwise apply session filtering (do nothing)
#BalusC The problem concerns old JSF application that is entirely stateful. Why try to figure out some way to inform users that openning the app in two separate tabs is potentially dangerous. In no way can we change session managed beans to request managed beans.
Make all those beans request scoped, install Tomahawk, add <t:saveState value="#{bean}" /> for every bean to every view of which you'd like to retain exactly the same bean state in the subsequent request. This works independently across tabs/windows.
Without Tomahawk, the alternative would be adding <h:inputHidden /> for every bean property which you'd like to retain in the subsequent request. I can however imagine that this may produce nasty boilerplate code when there are much or when they aren't of the standard EL types (for which you have thus to create a Converter). But that's what you get paid for.
One scenario I have in mind:
Put a javascript component in the page that will constantly sending heartbeat to the server via AJAX. As long as there are heartbeat sent from browser, this page will be flagged as 'currently_viewing'. And as long as a page have that flag on, other requests to that page should be rejected.
The detail may be a lot messier than this simple story (e.g. you might need to have some sort of 'page id' to be sent with the heartbeat), but you get the idea (... i hope :).
Everything is possible as long as you are willing to pay the price.