Using hash symbol in forward URL with RequestDispatcher - java

I'm trying to forward a request to another URL which includes the hash symbol ('#'):
request.getRequestDispatcher("/some/path.jsp#somehash").forward(request, response);
Tomcat, however, tells me that "the requested resource is not available". If I remove the hash from the URL, everything works fine. Are hashes not allowed or am I not treating them right?

The # symbol is a browser thing, not a server thing. When you type a URL with a # into the browser, the browser doesn't send that part to the server. It sends the URL without it, then jumps to the named anchor when it gets the page back.
When you ask the container to get that URL for you, it doesn't treat the # any differently to any other URL - it has no special meaning for it, so it looks for a JSP page called /some/path.jsp#somehash, which of course doesn't exist.
You'll need to keep that jump-to-anchor logic on the client somehow. Perhaps you could put some javascript on the resulting page to scroll to that point in the document.

URL fragments are purely client side. The RequestDispatcher#forward() is entirely server-side. The in the forward given URL won't be sent to the client side. You can however redirect to the given URL using HttpServletResponse#sendRedirect(). The URL fragment will then be sent to the client side and reflected in browser address bar as well. Redirecting the request has however the disadvantage that the current request will be garbaged and a brand new one will be created. If that's not affordable, then you'll indeed have to look in the JavaScript corner for the solution.

Related

'Framed' tomcat6 losing sessions

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 ;-) )

URL not changing on page redirection in Jersey and MongoDB

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()).

How to generate a navigable URL for a particular slotted place?

How do I generate the URL to navigate to a particular place in slotted? I know that to navigate the current user to a particular place, it would just be (assuming slottedController is defined and pointing to a valid SlottedController instance):
slottedController.goTo(new MyDesiredPlace(param1, param2));
However, my use case is to generate a URL to be inserted into an e-mail, and when the recipient receives the e-mail, they'll click the URL and should be navigated to the specified place. How would I generate such a URL in slotted?
SlottedController has two method for helping create Urls: createToken() and createUrl(). The createToken() will create a history token that appears after the #, which can be used with GWT Hyperlink. The createUrl() is the same as the token method, but prepends the current URI, which can be used with Anchor or external links like an email.
As a note, SlottedController can only be run on the client, so there is currently no way to create the URL on the Server side. The URL must be created on the client and passed back to the server.

HtmlUnit: Request website from server in a specific language

I am looking for a clean/simple way in HtmlUnit to request a webpage from a server in a specific language.
To do this i have been trying to request "bankofamerica.com" for their homepage in spanish instead of english.
This is what i have done so far:
I tried to set "Accept-Language" header to "es" in the Http request. I did this using:
myWebClient.addRequestHeader("Accept-Language" , "es");
It did not work. I then created a web request with the following code:
URL myUrl = new URL("https://www.bankofamerica.com/");
WebRequest myRequest = new WebRequest(myUrl);
myRequest.setAdditionalHeader("Accept-Language", "es");
HtmlPage aPage = myWebClient.getPage(myRequest);
Since this failed too i printed out the request object for this url , to check if these headers are being set.
[<url="https://www.bankofamerica.com/", GET, EncodingType[name=application/x-www-form-urlencoded], [], {Accept-Language=es, Accept-Encoding=gzip, deflate, Accept=*/*}, null>]
So the server is being requested for a spanish page but in response its sending the homepage in english (the response header has the value of Content-Language set to en-US)
I did find a hack to retrieve the BOA page in spanish. I visited this page and used the chrome developer tool to get the cookie value from the request
header. I used this value to do the following:
myRequest.setAdditionalHeader("Cookie", "TLTSID= ........._LOCALE_COOKIE=es-US; CONTEXT=es_US; INTL_LANG=es_US; LANG_COOKIE=es_US; hp_pf_anon=anon=((ct=+||st=+||fn=+||zc=+||lang=es_US));..........1870903; throttle_value=43");
I am guessing the answer lies somewhere here.
Here lies my next question. If i am writing a script to retrieve 100 different websites in Spanish (ie Assuming they all have their pages in the spanish) . Is there a clean way in HtmlUnit to accomplish this.
(If cookies is indeed a solution then to create them in htmlunit you need to specify the domain name. One would have to then create cookies for each of the 100 sites. As far as i know there is no way in HtmlUnit to do something like:
Cookie langCookie = new Cookie("All Domains","LANG_COOKIE","es_US");
myWebClient.getCookieManager().addCookie(langCookie);)
NOTE: I am using HtmlUnit 2.12 and setting BrowserVersion.CHROME in the webclient
Thanks.
Regarding your first concern the clear/simple(/only?) way of requesting a webpage in a particular language is, as you said, to set the HTTP Accept-Language request header to the locale(s) you want. That is it.
Now the fact that you request a page in a particular language doesn't mean that you will actually get a page in that language. The server has to be set up to process that HTTP header and respond accordingly. Even if a site has a whole section in spanish it doesn't mean that the site is responding to the HTTP header.
A clear example of this is the page you provided. I performed a quick test on it and found that it is clearly not responding accordingly to the Accept-Language I've set (which was es). Hitting the home page using es resulted in getting results in english. However, the page has a link that states En Español which means In Spanish the page does switch to spanish and you get redirected to https://www.bankofamerica.com?request_locale=es_US.
So you might be tempted to think that the page handles the locale by a request parameter. However, that is not (only) the case. Because if you then open the home page again (without the locale parameter) you will see the Spanish version again. That is clearly a proof that they are being stored somewhere else, most likely in the session, which will most likely be handled by cookies.
That can easily be confirmed by opening a private session or clearing the cookies and confirming this behaviour (I've just done that).
I think that explains the mystery of the webpage existing in Spanish but being fetched in English. (Note how most bank webpages do not conform to basic standards such as responding to simple HTTP requests... and they are handling our money!)
Regarding your second question, it would be like asking What is the recipe to not get ill ever?. It just doesn't depend on you. Also note that your first concerned used the word request while your second concern used the word retrieve. I think it should be clear by now that you can only be 100% sure of what you request but not of what you retrieve.
Regarding setting a value in a cookie manually, that is technically possible. However, that is just like adding another parameter in a get request: http://domain.com?login=yes. The parameter will only be processed by the server if it is expecting it. Otherwise, it will be ignored. That is what will happen to the value in your cookie.
Summary: There are standards to follow. You can try to use them but if the one in the other side doesn't then you won't get the results you expect. Your best choice: do your best and follow the standards.

Redirection from Servlet/Filter does not work

I have a problem with redirection - it simply does not work for valid paths.
Right now I use page forwarding in the Servlet, but I need redirection in a filter.
All the pages reside in the 'pages' folder and have a .jspx extension
I've tried the following (this path works with forwarding):
httpResponse.sendRedirect("/pages/login.jspx");
browser url is http://[localhost]/pages/login.jspx, and it shows Tomcat's 404 page, the context path (in my case it's '/hotel') is missing from the url, so, if I add it:
httpResponse.sendRedirect("/hotel/pages/login.jspx");
redirect does not happen, browser url does not change, and I'm shown the browser's 404 page (This program cannot display the webpage).
What am I doing wrong?
The filter which is used to test this has the following mapping:
#WebFilter(filterName = "SecurityFilter", urlPatterns = "/*")
The redirected URL is indeed relative to the initially requested URL. To dynamically prepend the context path it's recommended to use HttpServletRequest#getContextPath() instead of hardcoding it, because the context path value can be changed externally by server-specific configuration.
As to your concrete problem, I'm not sure if I understand "browser's 404 page" properly, perhaps you mean the browser-default error page which can occur when the server is unreachable or when the request has been redirected in an infinite loop (that should however have been made clear in the actual message of the browser default error page, at least Chrome and Firefox do that).
Given that your filter is mapped on /*, it's actually redirecting in an infinite loop because the request URL of the login page in turn also matches the URL pattern of the filter.
You'd need either to put the filter on a more specific URL pattern which does not cover the login page, e.g. on /secured/* where all restricted pages are been moved in there (or map it on /pages/* and put the login page outside there), or to fix your filter as follows:
String loginURL = request.getContextPath() + "/pages/login.jspx";
if (needsToRedirect && !request.getRequestURI().equals(loginURL)) {
response.sendRedirect(loginURL);
}
else {
chain.doFilter(request, response);
}
1 - Have you got logging or some other observable event in your servlet code that confirms it's definitely running?
2 - Redirects can fail if you write any actual response content prior to the redirect - have you anything doing that?
3 - Another option, set up a page in the root directory, even a "hello.html" static page, and see if you can redirect to that using either of "/hello.html" and "hello.html".
Just some ideas I would use in my own debug approach, hope something helps!

Categories

Resources