I'm new to Stripes and I'm trying to do like this: pass data from JSP1 using Ajax to the actionBean2 which belongs to JSP2 and then display the data on JSP2.
I do like this because JSP2 provides common interface for everything, and I want to redirect the user to JSP2 so that he/she could see the items that were selected in JSP1 using the standard interface of JSP2.
So, the problem occurs when I'm trying to pass the data from ActionBean2 to JSP2. Even though my return statement of actionBean2 looks like this:
return new ForwardResolution("/jsp2.jsp");
It actually doesn't redirect me from JSP1 to JSP2. RedirectResolution doesn't work as well.
I see the AJAX request from JSP1 being sent, the event handler in ActionBean2 receives it but doesn't redirect me from the JSP1. JSP1 even gets GET request for JSP2 url, but still the page doesn't reload. So, it looks like even though I'm in ActionBean2, it still uses JSP1.
My question is - should ForwardResolution redirect me to another page immediately (and reload the browser page)? And also - it my idea of passing data between these pages and actionBeans correct?
OK, I had to use a workaround, which I don't like at all. Still, it works. but if you have any suggestions, please, write.
I passed the parameters from JSP1 to JSP2 in URL using JavaScript redirect. Straight-forward method, but it solved the problem (JSPs didn't redirect when I tried to redirect using Resolution):
window.location.href ="jsp2.jsp?myparameters"+$.param(myparameters);
In JSP2 I used AJAX to call JSP2 actionBean.
if (window.location.search.indexOf("myparameters") != -1){
values = window.location.search.substr(window.location.search.indexOf("myparameters"), window.location.search.length);
values = decodeURIComponent( values );
//some parsing here, didn't include it
$.ajax({
url: "JSP2.action?from_redirect=",
data: {values: values},
type: "POST",
success: function(data) {
displayValues(data)
}
});
And in JSP2.action I made the from_redirect listener return:
return new StreamingResolution("application/javascript", data);
So, this method works, but I don't like 1 extra redirect.
if you have any suggestions, how to solve the problem with Resolutions, please write them. Also I would appreciate any help concerning removing extra redirects in this method.
Related
I have a scenario where from one page in AEM, I need to call another AEM page in the same application and I need to pass some hidden parameters. I choose to do it via POST and below are the steps which I followed:
From page "A", I did a form submission via POST to the sling servlet and passed some parameters.
2. In the servlet, using request dispatcher I redirected the same request and response to a different page in doPost method using the following code snippet:
request.getRequestDispatcher("/content/company/en/apps/welcomepage.html").forward(request, response);
When I run the code, I am able to call the servlet through form submission but I am not able to redirect to a new page. I see the below error in logs:
18.10.2017 14:41:00.802 ERROR [127.0.0.1 [1508352060795] POST /bin/rap/welcomepage HTTP/1.1] org.apache.sling.servlets.post.impl.operations.ModifyOperation Exception during response processing.
javax.jcr.nodetype.ConstraintViolationException: No matching property definition: appointmentTypeId = platform001d
at org.apache.jackrabbit.oak.jcr.delegate.NodeDelegate.setProperty(NodeDelegate.java:522)
at org.apache.jackrabbit.oak.jcr.session.NodeImpl$35.perform(NodeImpl.java:1375)
at org.apache.jackrabbit.oak.jcr.session.NodeImpl$35.perform(NodeImpl.java:1363)
at org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.perform(SessionDelegate.java:208)
at org.apache.jackrabbit.oak.jcr.session.ItemImpl.perform(ItemImpl.java:112)
at org.apache.jackrabbit.oak.jcr.session.NodeImpl.internalSetProperty(NodeImpl.java:1363)
If I try the same code in doGet method it works fine. Also if I use response.sendRedirect("/content/company/en/apps/welcomepage.html") it works fine too. But the problem with this is it initiates it as a new request to the page and it looses all the parameters which I get from the form submission. Could someone please let me know like how can I redirect a request to a page in AEM via POST since I need to pass some hidden parameters whic should not be visible in the url ?
Here is the way I understand your question
User visits page "A"
User fills a form, then submits.
Your custom servlet handles the submitted POST request and calls:
request.getRequestDispatcher("/content/company/en/apps/welcomepage.html").forward(request, response);
You get the ConstraintViolationException
Why do you get this exception?
Since you are using forward the POST request is forwarded to /content/company/en/apps/welcomepage.html that node is most likely of type cq:Page, which has constraints on which properties can be added. Think of it as a simple post request trying to store parameters on the cq:Page node.
What can you do?
Since I don't understand your use-case and particularly why you need to preserve the submit params, I cannot recommend a specific solution. However, since you don't want the parameters in the URL, here is a potential solution you can try:
In your servlet handler, see those hidden params to cookies on the response.
use response.sendRedirect("/content/company/en/apps/welcomepage.html")
On any of the components in /content/company/en/apps/welcomepage.html, you can get the request cookies and process them however you like. same way you wanted to process those hidden params.
Now the flow becomes:
User visits page "A"
User fills a form, then submits.
Your custom servlet handles the submitted POST request, adds your special params to cookies on the response, then calls response.sendRedirect("/content/company/en/apps/welcomepage.html")
User's browser receives a 301 response with the cookies, sets the cookies in the browser then requests "/content/company/en/apps/welcomepage.html"
Your components handle the request and get the params from the cookies, then retuns the appropriate response.
I have an idea to make something pretty sweet but I'm not sure if it's possible. Here is an example of a very basic ajax function that I might use to establish a connection a server...
function getFakePage(userId)
{
var ajaxObject, path, params;
ajaxObject = getAjaxObject();
params = "?userId=" + userId
path = getInternalPath() + "someServlet" + params;
ajaxObject.open("GET", path, true);
ajaxObject.send();
// On ready state change stuff here
}
So let's say I have a URL like this...
https://localhost:8443/Instride/user/1/admin
And I wanted to use javascript to redirect the user to this this URL. Normally I would just do this...
window.location = "https://localhost:8443/Instride/user/1/admin";
But my idea is to create a javascript (no js frameworks please) function that could combine the ajax code with the window.location code. Basically what I would like to accomplish is to create a connection with the server via ajax, send a servlet on that server the url I would like the user to be redirected to, and then redirect the user to that URL. So that for however long it takes the user to connect to my server from wherever they are in the world they see a loading icon instead of a blank white page.
So to clarify exactly what I am trying to accomplish; I do not want to put window.location within the success of my ajax function (because that would be encompass two round trips), and I do not want to return a huge chunk of HTML for the requested resource and add it to the page. I want to establish a connection to the server with ajax, send a servlet the URL the user wants to go to, and then somehow override the ajax function to redirect that user. Is this possible?
And I know some of you might think this is stupid but it's not when you're talking about overseas users with slow dial up connections staring at white pages. If it's possible, I'd love to hear some insight. Thank you very much!
First, let me say that the best solution is finding what is causing the slowness and fixing it.
Now as to your question, yes you could do it. You could even shoehorn it onto an existing application. But it wouldn't be pretty. And it comes with it's own set of problems. But here are the steps:
Browser calls ajax cache service requesting "somepage.html"
Browser loads loading icon
Server creates somepage.html and caches it in a temporary cache, (ehcache or other library would be good, probably with file backing for the cache depending on size)
Server responds to ajax request with ID for cached page
Browser now redirects to "somepage.html?cacheId={cacheId}" where the id is from the ajax call.
Server uses a filter to see if any cache can be served up for the page instead of the actual page, thus speeding up the request.
Having said that, it would be better to just have the new page load quickly with a loading icon while it did any of the heavy lifting through ajax.
You can't do an AJAX request and a location change in one. If you want to do only one request you have to choose one of those methods. ie. return some data and replace content on your current page, or load a completely new page.
It doesn't make any sense to want to want to do both. What you could want is stateful URLs; where your URL matches the content displayed, even if that content comes from an AJAX request. In that case an easy solution is the use the # part of the URL which you can change freely (window.location.hash). Some modern browsers support changing the whole URL without causing the page to reload. I've used # with great success myself.
I have a home-grown MVC implementation. A ControllerServlet like so:
/controller?cmd=EditUser&userid=55
From this URL, the controller creates a EditUserCommand.class instance and calls an execute() method which returns the result page (ex. user.jsp) to display.
The controller servlet then does a ...
getRequestDispatcher(resultPage).forward(request, response);
... and the resulting page is shown.
One of the things the controller does is set messages (error, info, and so on) as request attribtues. For example:
request.setAttribute("infoMessage", "User was edited successfully.");
And that message gets pulled out of the request in the user.jsp page and displayed.
Works fine.
Now here comes my problem.
Sometimes my commands don't return a page like user.jsp but return a URL like cmd=ShowUser&userid=55 for the result. This is because there might be things I want to check before displaying the final page, like permission to view the user and so on.
When I do this the "infoMessage" I placed in the request never appears because the result is a URL that makes a new call to the servlet, which is a new request. The new request doesn't maintain the request attributes from the first request; which makes sense, I just didn't forsee this happening.
How can I make my request variable "stay alive" until it's actually displayed on the final page that results from the original request?
Any suggestions or advice are appreciated. Just FYI, I can't re-write the entire app to go to something like Struts, Spring MVC, of JSF. It's not an option.
Thanks!
Rob
redirect generally looses request data because of brand new request from browser. One possible approach may be append your message to url string as attribute and read it when you need.
Based on your EDIT: After your edit also, my answer make sense. But, only one correction is, it is not brand new request because forward happens on server side.
Have you tried using a RequestDispatcher instead of a Redirect?
RequestDispatcher dispatcher = request.getRequestDispatcher("/myNextPage.jsp");
dispatcher.forward(request, response);
You may be giving a simple example, but your control flow causes the "Resend" Error, perhaps? Basically, after making any change to the data, the controller must immediately do a "Get" via a redirect and the screen should be displayed completely stateless.
Please take a look:
http://en.wikipedia.org/wiki/Post/Redirect/Get
As such, Attributes are not a great help. What you may want to consider is, maintaining a Bean/Object for every login user, and persist this object in a LRU cache (JCache or MemcacheD), and retrieve it on every entry to the application. Once you have that, you can maintain a pseudo-state such as previous results in that object.
In any case, using Attributes to retain state will severely constrain your options. You need to have a more generic flexible routing-independent mechanism.
hi I am querying database to load all items based on some criteria and setting this result in session as
data = service.getData();
session.setAttribute("data", data);
now I am trying to access this data via an Ajax call and my Ajax call is served by a different servlet rather then which fetched the data from DB.
Ajax call using jquery
$.ajax({
type: "POST",
url: "/com/tp/AjaxXML.jsp",
data: ({cmd: "report"}),
dataType: "xml",
success: function(xml) {
$(xml).find('site').each(function(){
var url = $(this).attr('url');
});
}
});
in my AjaxXML.jsp
I am doing
if("report".equals(cmd)){
List<Object> data = (List<Object>)request.getSession().getAttribute("data");
if(data == null){
System.out.println("data is null ");
}
}
every time I am getting the data as null via the Ajax call how ever I try to access the session data normally from my first servlet it works.
could someone let me know if I am doing something wrong?
I noticed one more thing when we do session.getId(); and pageContext.getSession().getId();
both of them are returning different Id's? Is this expected to me they should be same anyone differ on that?
I noticed one more thing when we do session.getId(); and pageContext.getSession().getId(); both of them are returning different Id's? Is this expected to me they should be same anyone differ on that?
No, they should definitely not differ. I however assume that you have examined them within the same request. If you examined them in different requests, then the difference can be explained by the absence of the proper JSESSIONID cookie. Cookies are domain and context specific. You're apparently sending the ajax request to a different domain/context. The leading slash / in the ajax URL also confirms this less or more. Make sure that you're sending it to the same domain/context. Use a context-relative URL, something like as url: "AjaxXML.jsp" and move the code to the same domain/context, or turn on session sharing between different contexts at server level.
Unrelated to the concrete problem, doing the Ajax response handling in a JSP is a bad idea. Rather do it in a servlet.
Replace
url: "/com/tp/AjaxXML.jsp",
by
url: "/com/tp/AjaxXML",
and put the code in doPost() method of the servlet which is mapped on that URL pattern.
See also:
How to use Servlets and Ajax?
I use jQuery and AJAX to load content from links and forms into a content div. In addition I use the Address plugin to enable the back button and refresh. On the server side I use Java and Spring MVC.
Since I'm using jQuery Address and AJAX the only page that is directly loaded is "index.html". Everything else is loaded into a content div, and what page to load is specified in the hash, ie. "index.html#/users/add.html" will load "users/add.html".
Now, "users/add.html" contains a form for creating a new user. When the form is submitted and everything went OK, the controller redirects to "users/index.html". The problem is that jQuery Address doesn't know about the redirect, so the url will remain "index.html#/users/add.html". And this is a problem when you refresh the page and then get sent back to the form, instead of the index page.
Is there a way to fix this problem?
Thanks,
Stian
Take a look at the new Form Sample. It's very basic but will be probably usable.
http://www.asual.com/jquery/address/samples/form/
In your case you won't be able to use $('form').address() function because you will want to change the address after the server response comes back.
You can use a data.redirect property to detect potential response redirects:
How to manage a redirect request after a jQuery Ajax call
I realize my description of the problem wasn't the best, apologies for that.
I reformulated the problem in another question, got no answers but I found a solution myself. :)
AJAX - Get response URL after redirect
First I init my form like that :
$('FORM').submit(function () {
shareData = $(this).serializeArray();
$.address.value($(this).attr('action'));
})
after I have in my change method something like that :
$.address.change(function(event) {
if (event.path != '/' && event.parameters.layout_to_use != undefined) {
// if no json, load don't do a post request
shareData = _arrayToJson(shareData);;
$('#areatoreload')
.html('<span style="background-color:red;">loading...</span>')
.load('myscript.php', shareData, function() {});
}
return false;
});
And i manage my link in the same way. I hope it can help you. shareData is not a very good way, but i don't find something else for the moment. this code is not tested, I just extract some part of my own code.