This is a question what I have been wondering for quite some time.
Often enough I have my jsp which has to post some data to my controller. In this jsp I have some data I need to post to controller, but aren't touched by the user.. (ie, administration data like an ID). As far as I know there are 2 options to give the controller this data.
Use <input type="hidden"> fields
Put everything in a session variable.
Option 2 has my preference since it requires me to type less code, and I can't forget hidden fields. Though this also has downsides, like another page overriding the session attribute.
What are your preferences? And are there any other options?
Thanks!
Davey
I always prefer to make session object as small and as light as possible. I know its convenient but if your site is high traffic then these session object size will soon start adding to the JVM instance of the Web Server.
So I would prefer option 1 over option 2.
Related
I'm working on a web project. The flow is like this
User inputs the parameters
Call to servlet is made (post method)
The servlet loads a large file (300.000 lines , one word per line) in a tree object. Does some calculations.
Redirects to a new page for the results.
My question is this. The user may do this operation more than once. The loading
of the file to the tree object is taking too long. How can I do this, only once?
I've thought to have just one servlet (or jsp) and not redirecting to different pages, but
manipulating the view with javascript. This way I think that I will manage to load the file only once (and whenever the user refreshes). Do you have any suggestions?
EDIT 1. This object is created by a class that is called from the servlet. I'm using apache tomcat 7 and java 1.6 . HTML5 is an option too (someone mentioned the history api).
Is the file specific to the user ? Keep the object in the user's session.
If its common to many users and they only need to read/ view this data keep it in the application object.
If your talking about the view -> browser then yes the way to do is ajax and/or frames and/or iframes
Advantage with frames is you can keep the data in another farme and still access it from other pages, but change the main view area to another page completely
Detail
user's session : available in servlets, filters, jsps etc -> key Object pair. can have any number of keys and objects but remember its all in the RAM, until session expires or if it is explicitly destroyed.
http://docs.oracle.com/cd/E19502-01/819-3669/bnaij/index.html
How to use the "application" object in a Servlet?
Application level http://docs.oracle.com/javaee/5/api/index.html?javax/servlet/jsp/PageContext.html get and setAttribute(String name, Object object)
This object can be read in all pages and jsps. Need to take care if object is already there (getAttribute does not return null) before you do the task of initializing it. Does the main file change? IF so can keep some code that calls a jsps that refreshes it. (like an admin jsp)
Frames/ ajax is for client level and you need to ask a more specific question for this but stack over flow and google have many examples of using this.
You can use ajax for that + html5 history api. So when navigating you will not reload page, but with history api, you will have same visual effect
I am writing a web application using JSP/Spring MVC and would need to customize the UI based on the customer using it. I would need to hide/show certain sections of the screen, hide show certain labels and their text boxes and also modify labels based on different customers. Currently we are controlling the hide/show in the JSPs by elements and divs based on the logged in customer. For example:
if (customer= "A")
show this
else
hide this
The code gets cluttered and the JSP will get bloated as we add more customers.
Another alternative I have thought is split a page into sections and control the sections in the same way, but might end up in code repetition accross the JSPs.
For example
if (customer = "A")
jsp:include headerA.jsp
else
jsp:include genericheader.jsp
Another alternative would be to write different JSPs and route based on the client.
Is there a better way to handle this kind of situations. Can someone suggest the best practices to implement such a solution?
Thanks.
A UI that chooses what to do for each user can't possibly scale beyond your users A and B. You need a role-based authentication and authorization system.
Since you're already using Spring, I'd recommend looking at Spring Security and its role based capabilities. There are tags that can help you.
Another way to look at it is that role-based logic like this does not belong in tags. I'd recommend putting it in controllers and let them assemble pages for you.
Another possibility is something like SiteMesh, which allows you to create composite views.
One more: jQuery was born to manipulate the DOM. Use it along with CSS.
First thing it should be based on Role and not based on customer, and each customer will have certain role. It may possible that many customers will have same role and screen access and UI.
Based on role, you can use Spring Secutiry for Authentication and Authorization.
If you need to use Layout differently as per customer role, preferably you should use some Layout Manager such as Tiles, SiteMesh etc.
or use portlets for different login views to different customers
You just stated if person A logs in from one store, vs person B logs in from another. Hate to say it, but that's a role, no matter how you want to spin it, this is related to user authorization.
In terms of how you want to implement it, you could do a variety of things, you could intercept the login request and set a session variable which prepends a string to determine the correct view (i.e. when user a logs in you get customerA, vs customerB, so when rendering the view you'd retrieve the value and render "customerA/index" vs. "customerB/index", etc.
You could also determine the person's roles within the controller and render the appropriate view, although this couples your user roles to your controller logic, which wouldn't be recommended in my opinion.
If this app is going to have a lot of different backends, I'd recommend portlets that way you can write a new backend for each app, rather than bloating your web application with every new store backend.
Those are just a couple ways, hope this helps.
I have a Java web application which stores some data in the session. The data in the session changes as the user interacts with the application (e.g. flow is managed by a controller, each controller has several form pages, on each form page some data is updated in the session and flow goes to the next form page).
The problem is that some users are opening more than one tab to the application, each tab with a different step in the flow. At this point data in the session is messed up since the tabs share the same session (app uses cookie managed sessions).
Telling the users to use different browsers to avoid sharing the same session id (e.g. one Firefox window and one IE window) is not an option since surely at some point somebody will forget to do this and instead use tabs, thus messing up their data.
Adding some verifications that detect that another flow is requested from another tab and display a message to the user saying this is not allowed is not an option either since it pisses of the users and we don't want that do we? :D
The fact is that using another tab is useful for the users because they are more efficient in what they use the application for, so I am keeping this option. But the question now is how best to manage the one session data for the more tabs?
What I thought of, was to have the controller generate a token when it starts the flow and pass this token to each form page which in turn sends it back to identify itself. If another tab requests the same controller action when there is an ongoing flow then generate another token and pass that around.
Basically, I want each flow to have a token and inside the session I won't just keep one set of data but have a set of data for each token and then match requests based on the token.
Now the problem is that this approach will need a lot of rewritings to the application and I was wondering if there is a best practice for managing such a situation or can someone suggest other approaches. I am open to ideas.
Have you encountered this situation? How did you handle it?
This is usually done by assigning a windowId for each tab/window and passing it on each request. Jsf supports this via orchestra. Spring mvc will support it in the next version.
I recently needed this for a simple case, so I implemented it myself. Took half an hour. However, my scope was very limited:
pass a windowId with each request, and return it back for the next request. The first time - generate it.
for any attribute you want to store in the session, put a Map<String, Object> where the key is the windowId
This is exactly what Seam was created to handle. In Seam there's a concept called a Conversation which basically does exactly what you are explaining. Conversations are basically are a way to divide the Session into many pieces that can expire at some timeout. You can look at the source code for org.jboss.seam.core.Manager class to see how it's actually implemented and get inspired ;)
Depending on the complexity of your application, you may want to investigate implementing tabs within your application. This gives you wholesale control over the flow, while still providing users with the functionality they want. I'd argue it's, bugwise, the most robust solution, since you won't have a dependency on the way the browser handles sessions, minimising the number of "known unknowns".
Of course, there'll be potentially a large upfront cost to this, depending on how your application is structured. Without more information about your app, you're the best placed person to decide.
You can also try to wrap your application inside Adobe Air
And then limit your web application to be only accessable from this air. By doing this you dont need to consider the web browser fragmentation and their unique behaviour.
I develop and maintain small intranet web apps(JSP and Resin).
Some users takes so much time to complete the forms that,
when they submit, they lose all their input data because of session timeout.
Currently I prolonged session timeout to 30 minutes and
display count-down clock till session timeout on top of the page, but,
I think their must be better ways to
protect user inputs.
What is the best practices?
Addendum
Our users make several kind of reports with the web-app,
and the whole contents of each report are stored in a JavaBean stored in the session.
As suggested by some, Ajax or iframe should do the quick fix.
I now know that it is better not to abuse session with heavy objects,
but I'm not sure how best to refactor current mess.
Some people suggested to make the web-app stateless.
Any suggestion for refactoring is welcome.
This may or may not be the case with your framework, but I think that if your page just uses AJAX to call the server every five minutes (or whatever), then that will keep your user's session alive. You don't even have to do a partial save of your form this way.
Make your applications stateless on the server side. You can include any state you need to maintain in hidden input fields. If security is a concern then you can encrypt the data before putting it in the field.
An example is putting something like this in your form:
<input type="hidden" name="user" value="bob" />
<input type="hidden" name="currentRecordId" value="2345" />
<input type="hidden" name="otherStuff" value="whocares" />
The main advantage of this is that your web app can do everything it needs to with just that page. It doesn't need any session variables because everything it needs is in the page it just received. Now it doesn't matter how long they take because there is no session to expire.
A secondary advantage is that it reduces the load on your server because it isn't polling your users periodically.
I've only recently needed to look at solutions to this problem.
The direction that looked most promising was using AJAX to periodically check if data was entered, and send it to the server. If the browsers running in your company support AJAX, this is one possibility.
Another possible solution could be to split the forms up, so that each section is small enough to be filled out and submitted within the session timeout.
If you are creating an application for a limited number of users (e.g., a company intranet) and you don't want people to have to keep logging in all day or have them lose their input information when sitting for extended periods of time, you can keep sessions open indefinitely only for people that have their browser open to your website without setting the session timeout to not expire. As soon as they close the website then the session will expire as normal.
What you need to do is add a hidden iframe somewhere on the page. Have the iframe point to a simple html document served by your app server that has a meta tag in it to refresh every 29 minutes (for a session that expires in 30 minutes). This way, as long as the person has your web page open, their session won't expire. However, when they navigate away from your site it will expire as normal. You get unlimited session lengths without the downside of sessions that grow out of control.
I successfully deployed this solution in an enterprise environment at a previous place of employment. The web app replaced an old green screen application and it was unacceptable for them to go to lunch and have the application expire on them, for example.
Let me know if you need more of an example.
I'd recommend looking into a stateless alternative (something that does not rely on session attributes) to what you're doing.
We may be able to help more if we know what exactly it is you're relying on sessions for.
You could store the data in a cookie every once in a while, use Gears as a temporary storage (if the data is complex or requires more than 4K storage) or send the temporary data to the server every n second using AJAX.
Umm..
What about displaying a prompt to the user about the session about to be expired -- save data (say 5 min before), so that they can save the data. This way they know what they have to save and in case the session really needed to be expired, it will be done afterward if they don't respond.
This is an alternative in case when you want to avoid a continuous ping to server using AJAX.
Don't use the session object. This is a cause of all sorts of usability problems - as you are discovering.
It's my golden rule of web application development: don't use the session.
Having said that, use it sparingly for things that just can't be done otherwise.
I would trigger "after a Ajax check that the session is expired" an popup form in a modal window that the User must sign in again, This popup overlay would be over the current page/form. So the data wouldn't be lost.
P.N Update the session token if U have one... in a hidden field.
I will elaborate somewhat. Jsf is kind-of extremely painful for working with from designer's perspective, somewhat in the range of trying to draw a picture while having hands tied at your back, but it is good for chewing up forms and listing lots of data. So sites we are making in my company are jsf admin pages and jsp user pages. Problem occurs when user pages have some complicated forms and stuff and jsf starts kickin' in.
Here is the question: I'm on pure jsp page. I need to access some jsf page that uses session bean. How can I initialize that bean? If I was on jsf page, I could have some commandLink which would prepare data. Only thing I can come up with is having dummy jsf page that will do the work and redirect me to needed jsf page, but that's kind of ugly, and I don't want to end up with 50 dummy pages. I would rather find some mechanism to reinitialize bean that is already in session with some wanted parameters.
Edit: some more details. In this specific situation, I have a tests that are either full or filtered. It's a same test with same logic and everything, except if test is filtered, it should eliminate some questions depending on answers. Upon a clicking a link, it should start a requested test in one of the two modes. Links are parts of main menu-tree and are visible on many sibling jsp pages. My task is to have 4 links: testA full, testA filtered, testB full, testB filtered, that all lead on same jsf page and TestFormBean should be reinitialized accordingly.
Edit: I've researched facelets a bit, and while it won't help me now, I'll definitely keep that in mind for next project.
have you looked into using facelets? It lets you get rid of the whole JSF / JSP differences (it's an alternate and superior view controller).
It also supports great design-time semantics with the jsfc tag...
<input type="text" jsfc="#{SomeBean.property}" class="foo" />
gets translated internally to the correct JSF stuff, so you can work with your existing tools.
You can retrieve a managed bean inside of a tag library using something like this:
FacesContext context = FacesContext.getCurrentInstance();
Object myBean = context.getELContext().getELResolver().getValue(context.getELContext(), null, "myBeanName");
However, you'd need to use the tag library from one of your JSF pages. FacesContext.getCurrentInstance() returns null when it's called outside of the FacesServlet.
To solve this one I'd probably create a JSF fragment that only includes your form, then use a <c:import> tag to include it in my JSF page.
That solution is probably a little fragile depending on your environment though.
EDIT: See Chris Hall's answer, FacesContext is not available outside the FacesServlet.
Actually, I've resolved this by removing bean from session, so it has to be generated again when jsf page is called. Then I pick up get parameters from a request in constructor.
Create a custom JSP tag handler. You can then retrieve the bean from session scope and then initialize it on the fly. See this tutorial for more details.