A pattern for stack of urls - java

I have a following question. We have an application that is a basically a set of JSPs and action classes that control the interaction with the user. The actions set up some parameters required for the page to display properly. The urls in the system always contain the name of the event which defines which page we should go next.
Now, almost every page has a Cancel button that should lead to the previous page. From the start each cancel button url was strictly defined, but eventually, as the system grew larger and larger, it turned out to be quite hard to program the logic for this button so that it would lead exactly to the previous page.
For example, suppose we have three pages, A, B and C. Page A has a link leading to page B, and B has a link leading to C. Therefore C has an url with even leading to B (and also it contains the key of the entity to display on B). However, suppose page A was modified and now also has a link on C. Now we need to check on C page from there we came and set the URL appropriately, and the logic becomes pretty mixed.
So, I proposed to my team the following solution. The user session should contain a special object called the CancelStack. Every action, that leads to the page, should push it's url inside the stack (containing the event and some additional data that is required). On every page the cancel button should now have an url leading to a special event, called cancelStack.
What the cancelStack action does is this:
Retrieve the cancel stack from the session.
Pop the last url and DO NOT use it.
Pop the url again and redirect to that URL.
Why do we retrieve the last url without using? Suppose we have pages A and B, A leading to B. Action for A places it's url inside the stack, and this should be the cancel url for the B page. Now, action for B places it's url inside the stack. Therefore I pop it without using, and then pop the first url, redirect to A action, and this action adds the A url again to the stack (therefore stack size decreases only by 1, not by 2).
It seems like a pretty good scheme, however it seems rather strange that the top element of stack is popped without using. Therefore I have a question. Is there any design patter in order to store the sequence of URLs inside the session in order to organise cancel buttons properly?

What you did seems reasonable to me. To be honest I can't think of a design pattern addressing your issue right now, but I think if besides the cancelStack you keep a reference to the currentURL so that you push the currentURL to the stack only if you don't end up in a cancel page you will get rid of the extra pop that annoys you.
Otherwise you just pop the top of cancelStack.
E.g. in your example:
Suppose we have pages A and B, A leading to B...
currentUrl is A. Action for A is not cancel so currentUrl i.e. A is pushed to the cancelStack. Then it is action for B and currentURL is B but action is cancel so B is not placed in the stack. So the top of cancelStack is A (while currentUrl is B). So if you pop the cancelStack you retrieve A (no extra pop needed)

Related

Should we write separate page-object for pop-up with a selection drop-down?

I am new to Page-Object model automation using selenium and java. I am using the Page Object model and have each page as a single class and the actions in that page as methods.
Should we write separate page-object for a simple pop-up which appears when submitting a form. This pop up is used to select service types and based on the selection correct form will be opened next. I have 'page objects' for the pages before and after this pop up. But for this one I just inserted a direct code to select an option and click next button. Should I create a separate page-object class for this pop-up?(as this is not a Page). Pop-up has 3 options and a Next button to proceed.
Please read this Martin Follower's article - Page Object.
A quotation:
Despite the term "page" object, these objects shouldn't usually be
built for each page, but rather for the significant elements on a page
Imagine a page which has over of dozen tabs, panels etc, and each one have a few fields, buttons etc. It would be impractical to create a huge class for such a page, it would certainly have 300-500 or more lines of code. Such a class would be very hard to maintain.
It's better (in my opinion) to create several small classes (page objects), each for a specific section of the page, each one containing only a few elements, each no more than 50-100 lines of code. We call these classes page fragments instead of page objects, but the concept is the same.
But it will vary from person to person and everyone may have a different opinion on this topic.
I agree with Bill, however I handle my popups a bit differently. I have it as it's own page object within the same class if it is a page specific popup.
For instance, if you have a popup on your dashboard page that is page specific to the dashboard page but not found anywhere else in the web application, I make it it's own class within the dashboard page object.
The reason I do this is I find the tests far more readable when the specific areas of the application are "containerized" within their own objects. Then when you open the popup and do operations on it, they would look like "popup.SetValue" versus "dashboard.SetValue" or something similar to that. Doing it this way you know that you are doing operations on the popup versus testing the dashboard.
If the popups are widespread throughout your application and can be reused easiliy I would suggest making it into it's own Page Object.
There's not really a hard and fast rule. As others have stated, the page object doesn't have to be a page. It really should be any piece of reusable functionality such as a dialog or header or footer, etc. For automation that I have written, I decided to follow the rule that any dialog is a separate page object (actual separate file). I find that it helps me keep track of pages/dialogs, etc.
To further help with this, I name my classes *Page for pages (e.g. LoginPage.cs), *Dialog for dialogs (e.g. AddImageDialog.cs), *Panel for panels (e.g. HeaderPanel.cs), and so on.
If a dialog only exists on a particular page, I named it based on the base page name, e.g. ProductDetailsPage_AddImageDialog.cs. What that does is when I look at the list of files, they will sort in alphabetical order so all the page objects related to the product details page will sort together so I can quickly see how many page objects are associated with that page and what they are. Some examples are below. You can look through the list and quickly determine which page objects are associated with a particular page and which ones aren't.
HeaderPanel.cs
LoginDialog.cs
ProductDetailsPage.cs
ProductDetailsPage_AddImageDialog.cs
ProductDetailsPage_AddTextDialog.cs
ProductDetailsPage_SaveCompleteDialog.cs
ProductDetailsPage_SaveYourProjectDialog.cs
If a dialog occurs multiple times throughout the site (not associated with a single page), I name it as a standalone page object, e.g. LoginDialog.
I used to just name the page object after the dialog, panel, etc. but after you get 50 page objects, it's hard to remember where certain dialogs occur so I came up with the _ naming scheme and it has helped significantly.
I also considered creating the AddImageDialog page class inside of the ProductDetailsPage page class but when you get larger pages with lots of dialogs, it just makes the file bigger and bigger. I prefer to keep the file size as small as is reasonably possible while keeping all the important bits in there. Breaking the files down into pages and dialogs and having them separate maintains the page object model principles while keeping things cleaner... at least in my opinion.
If the pop-up has an ID locator, and is likely to happen on other web pages, I would put it in its own page object, but often the pop-up is tied directly to the current page and would therefore be better included in that page's object definition.
The only reason I would consider putting it in a separate page object is if it did get used in other pages AND used the same ID locator, as if and when that locator changed, you'd only have to edit the one page object instead of locating and fixing all other page objects that also refer to that pop-up.

Java Servlet Need Browser Back Button to Resubmit Request

So here is my situation.
I have jsp A that does a query and displays data. On jsp A I have a form which will POST to a new servlet, the action on the form is "/data" or too the servlet directly. The doPost method will forward the request to a new jsp (jsp B) I am working on. This jsp B allows the user to select a second data point and, on submit, will forward two data sets back to jsp B where the data sets are presented side by side for comparison.
Now jsp B allows the user to drill down several layers of increasing detail. Each drill down makes a new POST back to the servlet which, in turn, forwards the new data back to jsp B. Again, the form on jsp B has an action of "/data", the servlet itself.
So goes to jsp B does a comparison and drills down two levels. Now the user wants to go back up on level. If the user clicks the browser "Back" button, the browser displays an error. A refresh of the page then displays the proper level of data.
I want the back button to automatically go back a level, resubmitting the form if necessary, and displaying the proper data.
In researching this, I found mentions of Post/Redirect/Get patterns. I also found this SO question and answer indicating that once a post is made that redirect should be used in lieu of forward.
How do I achieve the desired result without forcing the user to a) start the comparison over, and b) not have to hit refresh after the the back button.
Thank you

Java web development: transfer control from one servlet to another while passing the request object [duplicate]

This question already has answers here:
Design Patterns web based applications [closed]
(5 answers)
Closed 6 years ago.
EDIT: I have posted a somewhat shorter and revised question here: Java web development: transfer control from one servlet to another while passing the request object (Version 2)
As more or less a beginner at Java web development, I’m unsure about how I should structure the flow between servlets/pages when a form is submitted (POST). It’s an elementary issue, I suspect this may be an easy question to answer for the experts. (Still, my book and some googling didn’t deliver a clear answer.) My question is a bit long, and that's because I want to make it clear where I'm coming from. Thanks for you patience.
Let’s say we have two servlets A en B, with each having its ‘own’ .jsp-page; let’s call those pages a.jsp and b.jsp respectively. Now as long as there are no forms on either page (i.e., no POST method used), it’s clear how things should go. That is, before any .jsp-page is shown, the corresponding servlet is activated, doing some preparation for the .jsp-page by setting the relevant data elements (most notably, as attributes of the request object) that the .jsp-page needs, then forwarding the request object (etc.) to the .jsp-page, which then actually displays the page with the data. So for example, a link on page a.jsp may link to the servlet B, and on clicking that link a GET-request for servlet B is triggered, which then does some preparation (setting some request attributes), before forwarding to its ‘own’ .jsp-page (i.e. b.jsp).
But now let’s assume that page a.jsp displays a form with a submit button, method=”POST” and action=”B”. Then yes, servlet B is activated, and this servlet has to determine whether the data entered by the user is valid. If the data is in fact valid, we can simply forward to b.jsp, no problem there. But what if the data is NOT valid?
In that case, we obviously want to show a.jsp (the form page) again, with the data that the user entered the first time still present. One way to achieve this, is to simply have servlet B forward to a.jsp (thus bypassing servlet A). However, there is a big problem with that: the URL shown to the user, in the address bar, will still read “……/B”. So the user will see the correct page (i.e., a.jsp, containing the form), but with the wrong URL (/B). So for example, if we take “Register” and “ThanksForRegistering” instead of “A” and “B”, the user will see register.jsp – but with URL “……/ThanksForRegistering”! Not good.
And calling ‘include()’ instead of ‘forward()’ on the request-dispatcher doesn’t seem to work either. If we do that, not only does it result in a GET-request (as opposed to the POST-request we want), but we actually lose the whole (original) request-object with its attributes (which we need, after all, to re-populate the form). At least, that’s what my own experimentation seems to show. So using ‘include()’ doesn’t seem like a viable option at all.
Another obvious idea is to have "action=A" (instead of "action=B") for the submit. Then the servlet A itself can handle the validation, and if validation fails it can simply forward to a.jsp again, no problem. BUT then what if validation succeeds? Then we want to show the follow-up page b.jsp, but that page may well need the attributes from the original request-object (from the form-submit) again; for example, to have the user check that his entered data was in fact all correct. So basically we have the same problem as before, but with the roles of A and B (and their respective .jsp-pages) reversed. So this doesn't seem like a real solution either.
And I don’t see any other alternatives.
So basically, I’d simply like to be able have one servlet give control back to another servlet, but with the request object being passed from the former to the latter servlet. Or, if that’s not possible, I’d want to be able to forward from servlet B to a.jsp directly, but with the correct URL shown to the user. Or any other way to accomplish what I want.
Many thanks.
I think that the assumption that there has to be one page per servlet is causing the problem here....have one servlet which based on input redirects,forwards or includes a particular page....you dont really need to always invoke a different servlet for a page.....you can have a single front controller with a view resolver the combination of which will redirect or forward to a page.
You can use filters to achieve the same thing or think of setting attributes in HttpSession if validation is successful and retrieve the data in all the pages whenever it is required.
session.setAttribute("object", object);
I hope this is what you are looking for.

XPages: beforePageLoad runs more than once... Why?

We have this XPages application that has one master page (say M.xsp) and several sub-pages, all in separate iframes on the master page (loaded as A.xsp, B.xsp and C.xsp in separate tabs). The application runs fine, generally speaking. Each sub-page shouldn't interfere with the other pages, and as far as I know, it doesn't. Some page-dependent data is stored in viewScope variables, but for the most important parts we developed Managed Beans, with their data mostly in view-scope too.
Now, what we see is the following:
on page A, we do several clicks and some AJAX calls occur to fetch data from the server
we switch to page B, we do 3 AJAX requests for data to the server
we switch back to page A, we do one click to fetch some data again, and a beforePageLoad event occurs! Needless to say, the page is still loaded.
on the same page A, we do a new click to fetch different data, and beforePageLoad is triggered again!
viewScope is lost, my page-dependent bean is lost, very strange.
We checked, but changing the amount of memory dedicated to XPages didn't change anything.
XPages 9.0.1, browser-only.
Can someone please explain this behaviour: how come beforePageLoad is repeatedly executed? How can we prevent it?
Thanks!!
Twas indeed related to the max number of pages in memory. Every time an item in a list on page B was clicked, a sub-page (B1) was loaded in yet another iframe, using a URL with the item as parameter. Many clicks in the list forced many pages to load, causing all other pages disappear from memory. So when we moved back to page A and triggered some partial refresh there, it was as if the the page was new to the runtime environment.
I rewrote the sub-page B2 to stay in memory, and do a partial refresh itself when the list value changes. Quite a lot faster, and no unnecessary page drops.

How to cancel previous actions in java spring mvc application

I am developing a spring MVC application. I ran into some interesting case.
To make it easier to explain i am taking the stackover flow buttons on the top as example( i mean those questions, tags, users, badges, unanswered buttons).
Now in my app i have similar buttons. when user clicks on any button it makes ajax call by passing proper arguments. Server makes sql queries and returns the results back.
Now assume that there is a crazy user like me who keeps on clicking those buttons without break. So each click is making a ajax call. And which ever completes its operation is showing up on front end. So even if the user clicks Tags button in the last it may show up and again the previous click on questions which took long time to return to front end can overwrite the page. How can i fix that? ( i want the tags data to be shown as it is the users last click)
In the first place i know that when user first clicks on question and then on tag i no longer need to query sql for questions button. Is there some way for me to stop processing the sql query for questions button.
Thanks
The best way to handle this is through the user interface - if the user takes some action (clicking an image) that will require significant processing on the backend, your UI should prevent other actions on the page from sending further messages to the backend until the original request is complete.
Ways to tackle this visually would be to disable/gray out other elements, make it obvious that some work is going on (with spinners, progress bars), etc.
On the server side, since each HTTP request is independent it would be cumbersome and difficult to add logic on the server to be able to detect if the user making this current request has another ongoing request currently being processed.
You probably need to take help of cookies. When the first time the action is done, write some cookie. Every time, check that cookie before you process.
You cannot simply disable a link or button from the UI and hope the user cannot do it. It can always be done in multiple ways. Additional checking is must.
(I haven't read your post completely. But from what I understand from the 1st answer...)
I had a similar problem, and I tackled it this way.
I did hand-coded ajax calls (as opposed to jQuery etc.)
I had a single global XMLHTTPRequest.
var xhr = new XMLHTTPRequest();
When the user clicked something, which needed an ajax call, I aborted the previous call, if already running.
if( xhr.readystate !=0 || xhr.readystate !=4 )
xhr.abort();
Then create a new instance of XHR, and do your business.
xhr = new XMLHTTPRequest();
xhr.open("GET", myUrl, true);
//attach callback function etc and do the send

Categories

Resources