This week's book giveaway is in the Jython/Python forum.
We're giving away four copies of Hands On Software Engineering with Python and have Brian Allbey on-line!
See this thread for details.
Win a copy of Hands On Software Engineering with Python this week in the Jython/Python forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Bear Bibeault
  • Knute Snortum
  • Liutauras Vilda
Sheriffs:
  • Tim Cooke
  • Devaka Cooray
  • Paul Clapham
Saloon Keepers:
  • Tim Moores
  • Frits Walraven
  • Ron McLeod
  • Ganesh Patekar
  • salvin francis
Bartenders:
  • Tim Holloway
  • Carey Brown
  • Stephan van Hulst

About request scope and removing a row from datatable  RSS feed

 
Ranch Hand
Posts: 1709
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, I am reading Core JSF 3rd edition chapter 6 datatable, about deleting a name from a data table.




There is a statement in the book :


If the value of a data table has request scope, be sure that the data does not change between the rendering of the table and the decoding of the
response. If the new data set is different, then the wrong row will be processed. If the new data set is empty, then no action takes place at all
because no matching link is encountered.



I don't understand this statement. I think the data , eg Anna Keeney, is rendered and decoded in the same request when Anna Keeney is removed
during the command button is clicked.
Why does it matter to define the Name in session scope or request scope?
For example,  Anna Keeney name object,  is going from lifecycle phrases from restore view through invoke application when the delete button is clicked. Then, it is removed (decoded) from the view when it is in the render phrase. It happens in one single request. Why it should be in a session scope ?
 
Bartender
Posts: 20107
101
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Let's make it simple. Forget Request Scope when you are using JSF. It will bite hard and often. And dataTables are especially prone to problems, because there is cursor information in the DataModel that maps the dataTable (even if you don't use a DataModel, JSF will).

JSF operates via postbacks. Among other things, this means that the same page may be displayed over and over again with error messages displayed until the user gets all the data entered validly. So that's one problem point.

The other is the way the table is displayed itself. If you navigate to a view that contains a dataTable mapped into a Request Scope bean, the navigation process constructs the request, constructs the DataModel (either implicitly or explicitly), pushes the data into a Component tree, which is then rendered and posted back to the client. If the client clicks on a commandButton or commandLink on a row in the dataTable, the form request is then sent back to the server, which constructs a new Request object. Which will not contain any state information from the previous request, since it wasn't saved and restored, it was constructed. And that state information that gets lost will include the context of the row in the dataTable.

As a general rule I recommend always constructing an explicit DataModel to back a dataTable, although if the dataTable is display-only it's not essential. A DataModel is going to be built anyway, so if your table contributes data input, having an explicit DataModel means that you have something to call getRowId or getRowData() on.

You could probably safely make a display-only dataTable be request scope, but there's always the possibility that someday you might get a "one small change please" assignment that alters it to a data-entry dataTable and if you marked the backing bean as Request Scope you'd probably waste several hours wondering why it didn't work any more. After all, you only made one small change, right?  

So for a happier life, wrap your table data in a DataModel and make the bean View or Session Scoped.
 
Himai Minh
Ranch Hand
Posts: 1709
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, Tim. Thanks for the explanation.
To make sure I understand the explanation.
You mean if we edit a row in a data table and click on the row's submit button, there is a new request object created behind the scene ?
In the case, the request object with the original data is lost?
 
Tim Holloway
Bartender
Posts: 20107
101
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Himai Minh wrote:Hi, Tim. Thanks for the explanation.
To make sure I understand the explanation.
You mean if we edit a row in a data table and click on the row's submit button, there is a new request object created behind the scene ?
In the case, the request object with the original data is lost?



Essentially. You also lose the JSF cursor information, so it's not possible to ask the DataModel which row you clicked on. The instant that a web page is sent to the client, the previous request object is destroyed.
 
Himai Minh
Ranch Hand
Posts: 1709
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,
I tried out an example from Chapter 6 of Core JSF.
The managed bean is a request scope bean, instead of session scope.


This is the index xhtml.


I found out this example works fine. I changed the last name of Anna Keeney to Anna Keeneyi in one request. When I reload the index page again, the change is in effect.
I assume after one request of name change, the name change will be gone after subsequent reload of the page.
Any comments?
beforeNameChange.JPG
[Thumbnail for beforeNameChange.JPG]
Before Anna Keeney's last name change
afterNameChange.JPG
[Thumbnail for afterNameChange.JPG]
After Anna Keeney's last name change into keeneyi
 
Tim Holloway
Bartender
Posts: 20107
101
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Try this:

Add the attribute "required="true"" to the control referencing names.last (incidentally, I strongly recommend putting an "id" on all your controls as well as dataTables and other container elements. Error messages are easier to decode that way.)

Now that you've made required=true, try doing your edit, but blank out the last name. I think you'll find that when it posts back the error that interesting things will happen.
 
Himai Minh
Ranch Hand
Posts: 1709
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, Tim.
This is what I modified. I added id for the table, last name, first name and save button. The last name is required.




In my first run, I define TableData as request scope. In my second run, I define it as session scope.
In the first run using request scope, I first blank out the last name. It gives a validation error. I assume the TableData bean is destroyed. I open another browser to start a new request with a new TableData bean. The last name appears in the second browser because it is a new request.

In the second run using session scope, I first blank out the last name. It also gives me an error. Then, I open a second browser. I assume the same TableData bean is still alive.
The last name appears in the second browser.
But I expect that the last name should disappear in the second browser as the TableData bean is still the same.
TwoBrowsers.JPG
[Thumbnail for TwoBrowsers.JPG]
When table data bean is in request or session scope, the last name appears in both second browsers.
 
Himai Minh
Ranch Hand
Posts: 1709
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, Tim.
I did another experiment.
I tried to use both session and request scope TableData bean. I first blank out the second row of last name. Then,  I got an error.
After the error is printed on the browser, I click on the third row of last name. But this row is not editable.
It seems to me that under both scenarios with session/request scope, after the error happens, it forgets which row was selected in the previous request and it cannot select a new row.
forgetSelectedRow.JPG
[Thumbnail for forgetSelectedRow.JPG]
It forgets which row was previously selected.
 
Tim Holloway
Bartender
Posts: 20107
101
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It's important to note that regardless of scope, a backing bean is not updated if any field on the form is invalid. A missing required field is invalid, which is why even in session scope, the change wasn't reflected in the second browser window.

JSF isn't really designed for multiple-window usage anyway, and that's fine with me. Want me to avoid your website? Pop open a window. Or start an auto-playing video/audio.

You can get rid of that funny ID segment in your validation error message by putting an id on the h:form element.

As far as losing track of what row you're working on, that was the original point. The cursor information used to do such things is lost when you run in request scope.

And finally, you're actually seeing a best-case scenario in your example, since the underlying table data is static. If it had been a dynamic object created or injected into the bean, you would have seen more problems.
 
Himai Minh
Ranch Hand
Posts: 1709
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, Tim

As far as losing track of what row you're working on, that was the original point. The cursor information used to do such things is lost when you run in request scope.


Base on my experiments, I think the cursor information is lost when I run in request and session scope.
When the second last name is empty, it cannot be validated.
Then, I click on the third last name and try to edit it. But the last name field is not editable. It looks like the cursor is lost until I fix the second last name.
 
Tim Holloway
Bartender
Posts: 20107
101
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
When you mark a control as "required", that is a validation option. If the control has no value set (for example, no text in an inputText), then the form data is invalid. In which case the bean will not be updated and the action method will not be invoked. Nor will value change listeners and other functions that are only allowed for a valid form.
 
Himai Minh
Ranch Hand
Posts: 1709
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So, having a validation error cannot demo the lost of cursor information.
Let me try to dynamically set the names for example in the setNames method, append a number to a last name. Then, increase the number after each request:



What I expect is :
With request scope, the increment value is always 1. The name display is always Dupont1
With session scope, the increment value is always increasing. The name display is Dupont1, Dupont2, Dupont3 after each time the faces servlet is called.
 
Himai Minh
Ranch Hand
Posts: 1709
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Tim for the suggestion.
Let me answer my own question based on your advice.
I modified the TableData , so that it uses ArrayDataModel to store the names.




I first edit a last name. When I hit save, the TableData object is not alive after the save is clicked.
The last name change is not in effect. See the following attachment.
Req_Scope_before_Save.JPG
[Thumbnail for Req_Scope_before_Save.JPG]
Before save button is clicked, make a change to the last name
Req_Scope_after_Save.JPG
[Thumbnail for Req_Scope_after_Save.JPG]
After the save button is clicked, the TableData is destroyed after the request/response life cycle. So, the original names are loaded.
 
Himai Minh
Ranch Hand
Posts: 1709
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Another experiment is to make the TableData as a session scoped bean:


After I edited a last name, I hit save button. The request/response life cycle is done. But the TableData bean is still alive. So, the change is stored.
Session_scope_before_save.JPG
[Thumbnail for Session_scope_before_save.JPG]
Before save, I changed a last name
Session_scope_after_save.JPG
[Thumbnail for Session_scope_after_save.JPG]
after save, the reqest/response is done. But the bean is still alive. Change is effective.
 
Himai Minh
Ranch Hand
Posts: 1709
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, another experiment is to keep track of how many time the save button is click.



The result is that the name is not changed and the increment is changing from 0 to 1 and so on for subsequent run.

If the TableData is session scoped, the increment will change from 0 to 1, 2, 3 and so on.
before_Save.JPG
[Thumbnail for before_Save.JPG]
Before save, increment =0
after_Save.JPG
[Thumbnail for after_Save.JPG]
after save, increment = 1
second_edit.JPG
[Thumbnail for second_edit.JPG]
Edit the name for a second time. Since the previous request object is destroyed, increment is reinitialized to be 0
 
It will give me the powers of the gods. Not bad for a tiny ad:
RavenDB is an Open Source NoSQL Database that’s fully transactional (ACID) across your database
https://coderanch.com/t/704633/RavenDB-Open-Source-NoSQL-Database
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!