JSF: poll server, render button/link, so user can refresh view - jsf

The most popular page in my JSF/PrimeFaces web app is a page with p:dataTable with data spanning date ranges (and yes, FROM and TO p:calendar are used for filtering the data along with p:inputText and p:autoComplete components, when/as necessary).
I would like to poll for changes in the data listed in the dataTable for selected dates (date range). I would like to render an Update or Refresh commandButton/Link ONLY IF data has changed for the current view for any/every user.
When a given user makes an update to data, I would like to inform other users in any/all other sessions that this data was changed, and if user(s) is/are viewing that data on a page/view via dataTable (or detailed view), then user can click Refresh button to see the update, but the Refresh button/link is only rendered via AJAX via polling. Of course, I want this 'action' to be initiated or some flag (or POJO may be more appropriate) to be stored on server ('List dataThatWasUpdated'), and polling would check this 'per' user (like the polling-Notifications implementation that I already have in place, which is working perfectly). During polling, this list will be scanned, and if user is viewing any of the data that is in the List, then Boolean will be set on another managedBean to render the commandButton/Link. This List would be set to null after each polling.
In the near or distant future, after I migrate to CDI, I will do this via CDI and server-sent-events (SSE) via HTML (and Java EE CDI, of course), but for now I am considering using or adding p:poll to give user the opportunity/option to refresh the view (since data has been updated by another user).
Please confirm my thoughts/design and/or advise. Thanks.

p:poll is fine but a WebSocket/Comet Framework could be nicer (and not really complicated to add). And as you are using Primefaces, you could use Atmosphere (http://atmosphere.java.net). They had a p:push to achieve such a goal.

Related

best practice for communicating between two beans that back the same page

We are making the transition to bootstrap pages. As part of this, we are making most of our dialogs into simple include files that get rendered on demand. The include files have their own backing bean to minimize code duplication.
The typical use case is when a user enters a page a datatable shows a list of things. The user selects one or more rows in the table and then clicks a button to perform an action. The page is re-rendered using ajax. The datatable is not displayed but the former dialog is. The user then does whatever bulk operation the former dialog does and clicks execute (or cancel). The page is then re-rendered with the datatable showing and the former dialog box not.
The problem here is simple; how do you set the render flags on the datatable and former dialog box? Each of the beans needs to set the render flag of the other bean. I blithely tried injecting each bean into the other and promptly got a circular injection error at runtime. I've gone to having a callback interface that the datatable beans implement. When the former dialog bean gets injected, the datatable bean sets itself up to be called back. This works but I am not sure it's the best way to do it. Being an old swing programmer, I considered using property change listeners, which are much more robust than the simple interface, but I'm not sure what the implications of using them in a managed bean environment are. I did check out the messaging API but it clearly doesn't apply to this case.
So, what's the best way for two view beans that are backing the same page to talk to each other?

JSF-Calling BackingBean method twice maintaining value of inputFileUpload

I am very new to JSF. I have the following requirement:
On click of a commandButton, call a backing bean method to check if there is some data present satisfying the condition.
If yes, confirm from user for overwrite.
If user says OK, call the same method of backing bean with some parameters set to tell the program to overwrite the data.
What I am doing is:
having action of the commandButton as the method name.
in the backing bean method, check if we have come with certain condition, check if the data is already present.
If yes, go back to page and ask for confirmation.
If confirmed, call the click method of the button.
The problem is, when I come back to the page, the inputFileUpload component on the page loses its value.
What can I do to achieve this? Please help.
This is fully by HTML specification and completely outside control of JSF. It's by HTML specification for security reasons not possible to (re)display the value of a HTML input file field with a value coming from the server side. Otherwise a hazard scenario as shown in this answer would be possible.
You need to redesign the form in such way that the input file field is not been updated during confirmation. You can use among others JavaScript/ajax for this: just submit the form by ajax and make sure that the input file field is not been updated on ajax response.

how to distinguish a jsf action or direct url link invoked the page

I have a situation, I have a session bean with list, this list I show in html data table. When the user hits the url from browser or normal href, I have to show all records. There is provision to search for the data also, where I have to show the filtered list. Now after a user has made the search, the list contains filtered records and after doing this he leaves the page to some other, and now if the user hits the url or uses the menu to come back to this page, since I have this list in session bean, I still have the filtered list.
Since there is no default action in JSF 1.1 or 2.0 preRenderView concept, its difficult to clear the list and get non filtered data(all results) again. Even tricks in getList() method fail to accomplish the task.
I have planned to use phase listener, as when a user reaches a page via href or url hit in browser, invoke application phase does not happen. I can toggle boolean variable in my session bean and in getList() I can perform some trick to check it was url,href hit or by command button.
Hope I have made myself clear. In short I have to identify in my bean whether the request came directly from href,browser or an action. If search action filter records for data table if not keep list cache and keep showing it as long as search is not made.
Just guide me whether I am doing things in right way or thinking too much or can it be done in much more efficient way.
Thanks in advance.
Well platform is jsf 1.1 in weblogic portal 10.3 .....
JSF 1.x actions use by default POST method. Direct links/bookmarks/etc are by nature GET method. Since there's no ResponseStateManager#isPostback() or FacesContext#isPostback() in JSF 1.1, you have to determine the request method yourself:
HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
boolean postback = "POST".equalsIgnoreCase(request.getMethod());
Or check for a certain parameter in the request parameter map, but I can't tell from top of head which one you'd like to check. You've to determine it yourself.
boolean postback = facesContext.getExternalContext().getRequestParameterMap().containsKey(SOME_KEY);
If postback is true, then a JSF action is been invoked.

Populating a page from Data table in modal panel

I'm trying to get some data from a datatable in rich:modal panel
The whole flow is as follows
When clicking on search button on main page, a modal panel pops up with appropriate data & check box
Till this point the application is working fine
After clicking on ok button, selected data should be populated into main page. This is where the code fails
I tried stuff like getRowData, getValues, etc. but in vain. This could be done by keeping the bean in session scope but I have to keep this bean in request scope using Apache MyFaces JSF 1.2
Two ways comes to mind:
Pass an extra request parameter (the search string and the page number?) so that the bean knows which data to preload.
Make use of MyFaces Orchestra to create a conversation scope which lies in between request and session scope and is exactly the scope you're looking for this particular functional requirement.

Whats the best way of sending parameters between pages?

We are using JSF in our project (im pretty new to it) were every page have a back bean Java file.
In order to move (redirect) from one page to another, i need to put all the parameters (search criteria) in the request scope before redirecting and then retrieve it back in the next page constructor. When you have few pages deep and you want to come back to the top, it becomes really annoying to maintain.
For example, if i have page 1 with advanced search filters, which redirects to page 2, depending on the chosen item, and from page 2, you get another list were you can go to page 3 for details. Now each time i need to put all the params in the request scope/read them again, store them in hidden fields and get them back.
Whats exactly wrong with this method and whats a better way to do it in JSF?
EDIT: the environment is IBM Rational Application Developer (RAD), which have its own JSF implementation. Not sure if that makes a difference.
Putting request scoped data in session scope will bite you (very) hard if you're going to open the same page in multiple windows/tabs. Only use the session scope if the data itself is also really session scoped (excellent examples are the "logged-in user" and the "shopping cart", you want it to be exactly the same throughout the entire session). Again, don't put request scoped data in the session scope. It hurts both you and the enduser.
Just design your beans smart (it makes no sense to have different beans containing the same data) and make use of h:inputHidden where needed, if necessary in combination with managed property injection. It's indeed a bit a pain to code and maintain. You can on the other hand also just grab Tomahawk <t:saveState> if the to-be-passed data is actually as big as a "whole" managed bean. It costs only a single line in the JSF page and has always been of great assistance.
*For example, if i have page 1 with advanced search filters, which redirects to page 2, depending on the chosen item, and from page 2, you get another list were you can go to page 3 for details. Now each time i need to put all the params in the request scope/read them again, store them in hidden fields and get them back.
Whats exactly wrong with this method and whats a better way to do it in JSF?*
There's nothing wrong with this method. Maybe you coded it the wrong way which caused that it looks unnecessarily overcomplicated. I can't tell much as long as you don't post details about the code used.
As per your edit:
EDIT: the environment is IBM Rational Application Developer (RAD), which have its own JSF implementation. Not sure if that makes a difference.
This is not true. IBM doesn't have any JSF implementation. It has just a component library (the poorly maintained hx prefixed components, also known as "Faces Client Framework"). WSAD/RAD ships with Sun JSF RI (Mojarra) as standard JSF implementation, although it's usually a heavily outdated version. Ensure that you keep it updated.
I'm only starting out with JSF too to be honest, but I thought you can save managed beans in the session scope, thus being able to access the bean on each request? You can also save the state client-side avoiding nastiness about session stickyness and stuff.
So you could save the data you are currently passing as request parameters in a session-scoped managed bean, and it will be available to any requests in that user's session, destroyed when the session times out or is deliberately invalidated (say on user logout).
I don't think JSF currently supports conversation state which I think might be the exact solution to your problem, maybe a session scoped managed bean would be the pragmatic solution?
Make your managed-bean session scoped.
If you are using MyFaces you can use PageFlowScope. If using Seam then use Conversation scope.
If pageflowscope or conversation scope is not available, then use session scoped beans. In addition you can use PhaseListener to initialize or execute specific methods before the page gets called. In you case if the flow is page1 -> page2 -> page3, then initialize the session scoped bean in PhaseListener if page1 gets called.
I'll update with more info if you need.

Resources