Synchronizing session scoped managed bean
I have 2 screens in my JSF 2.0 application. Screen 1 searches for students and lists students in a table. The student name in the results table is a link to the student details page (screen 2).
My managed bean:
@SessionScoped
public class TestController {
private Student studentOnUI; // Student being viewed on the UI
// synchronized public getters and setters
public String viewStudentAction(String studentId) {
this.studentOnUI = getStudentFromDB( studentId );
return "studentDetailedPage";
}
public synchronized String clearSearchAction() {
this.studentOnUI = null;
return "studentSearchPage";
}
screen 1 xhtml snippet
<!-- search fields -->
<h:commandButton
value="Clear Search"
action="#{testController.clearSearchAction()}"/>
<!-- Search button -->
<!-- search results table -->
Screen 2 xhtml snippet
<h:outputText value="#{testController.studentOnUI.name}" />
<h:dataTable
value="#{testController.studentOnUI.subjects}"
var="subject">
<h:outputText value="#{subject.score}"/>
</h:dataTable>
I face the following issue:
- After running search, user clicks on a student name (to move into screen 2)
- When the render response phase of
screen 2 is in progress (which has
EL references to
testController.studentOnUI), He
clicks on clear button (without waiting for the first request to complete). Now the
thread handling the clear request
sets testController.studentOnUI to null and
the first thread that is in render
response phase throws
NullPointerException when it
evaluates
{testController.studentOnUI.*}.
Although the managed bean handles synchronization (correctly?) it does not solve the concurrency issue here because, the following could happen
- Thread 1 (handling request to navigate to screen 2) - evaluates #{testController.studentOnUI.name} and happily renders the value. And then exits the testController.getStudentOnUI() synchronized method. So thread 1 no longer has the lock on the controller instance (in session scope). context switch happens.
- Thread 2 (handling request to clear search results) - does testController.studentOnUI = null in clearSearchAction(). context switch happens.
- Thread 1 - evaluates the next EL in the page (#{testController.stu开发者_JAVA技巧dentOnUI.subjects}) and throws a NullPointerException (as testController.studentOnUI is now null).
Appreciate any pointers on what I am doing wrong with this approach or if a different approach needs to be adopted here.
this is really strange behaviour but then i would rather disable the link on the first page with JavaScript to make it "unclickable". try with jQuery:
1 button: $('#button').attr("disabled", true);
2 link: $('a.something').click(function(e) { e.preventDefault(); });
I'm not sure about the synchronization in the backing bean since the JSF Controller has to put the lock on your Student object, not the clear method. Am I wrong?
精彩评论