Hi,
I've been trying to figure this out for 5 straight days and cannot understand why
org.jboss.seam.handledException is not being set in certain cases. Actually, it is set,
but I cannot retrieve it in my handler class.
First the setup:
-Seam 1.2.1
-Tomcat
-Richfaces 3.0.1
-Myfaces 1.1.5
Ok, so I have a "my account" page, where a user can update his details. I also
have an admin function, where an admin can update any user's details. The
StaleObjectStateException occurs if both the user and the admin update the details at the
same time. Nothing strange about this. What is strange is that if the admin is the
"winner" (i.e. his update was commited) then the exception handler for the
user's exception gets hold of org.jboss.seam.handledException value and proceeeds.
However, if the user is the winner, then the admin's handler (same class) does NOT get
the org.jboss.seam.handledException value. Why? Obviously something is happening in one
case but not the other, but I can't figure out what.
Here are some details:
The "handler" is defined as follows:
|
| pages.xml
|
| <page view-id="/errorConcurrentModif.xhtml"
action="#{concurrentModifHandler.handle}">
| <end-conversation before-redirect="true"/>
| </page>
|
|
| <exception class="org.hibernate.StaleObjectStateException">
| <end-conversation/>
| <redirect view-id="/errorConcurrentModif.xhtml"/>
| </exception>
|
|
So, when a StaleObjectStateException occurs, the user is redirected to
/errorConcurrentModif.xhtml, which has a page action handle().
| @Stateless
| @Name("concurrentModifHandler")
| public class ConcurrentModifHandler implements ConcurrentModifHandlerLocal {
|
| public void handle() {
| ...
| StaleObjectStateException sose = null;
| if (Contexts.isConversationContextActive()) {
| Object o =
Contexts.getConversationContext().get("org.jboss.seam.handledException");
| if (o != null && o instanceof StaleObjectStateException) {
| sose = (StaleObjectStateException) o;
| }
| }
|
| ...
| }
|
Here, sose is null in one case but not the other. In both cases, prior to reaching my
code, org.jboss.seam.core.Exceptions successfully sets
"org.jboss.seam.handledException" into an instance of
ServerConversationContext's "additions" map.
Another funny thing I noticed was that in the case where it works (as I expected), the
ServerConversationContext's flush() method is called before my handler, but in the
case where sose is null, the flush() method is called afterwards. flush() is where the
values in the additions map are moved to the Session's attributes.
Here's how the pages are set up. First the admin's (role is named BR). The admin
(BR) searches for users and gets presented with a data table in a page called
manageBidders. The actualt DataModel is created in a Session scoped component.
| @Stateful
| @Name("bidderSearch")
| @Scope(ScopeType.SESSION)
| @Restrict("#{s:hasRole('BR')}")
| public class BidderSearchingAction implements BidderSearchingLocal {
| ...
| @DataModel
| private List<Bidder> bidders;
| ...
| @Factory
| public List<Bidder> getBidders() {
| ...
| return bidders;
| }
| }
|
The admin then clicks on the edit link in the data table
| <rich:dataTable var="bidder" value="#{bidders}">
| ...
| <s:link action="#{bidderManager.showEdit(bidder)}"
value="#{messages.label_Edit}"/>
| ...
| </rich:dataTable>
|
BidderManager:
| @Stateful
| @Scope(ScopeType.CONVERSATION)
| @Name("bidderManager")
| public class BidderManager implements BidderManagerLocal {
| ...
| @Begin(join = true)
| public void showEdit(Bidder selectedBidder) {
| selBidder = database.merge(selectedBidder);
| userName = selBidder.getUserName();
| emailRepeat = selBidder.getEmailAddress();
| action = Constants.EDIT;
| }
| ...
| }
|
And the corresponding entry in pages.xml
| <page view-id="/restricted/manageBidders.xhtml">
| <restrict>#{s:hasRole('BR')}</restrict>
| <navigation from-action="#{bidderManager.showEdit(bidder)}">
| <redirect view-id="/restricted/editBidder.xhtml"/>
| </navigation>
| </page>
|
When the admin submits the changes, an action bidderManager.save() is called.
| <h:commandButton id="save" action="#{bidderManager.save}"
value="#{messages.button_Save}"/>
|
|
| In BidderManager:
|
| @End
| @Restrict("#{s:hasRole('Bidder') or s:hasRole('BR')}")
| public void save() {
| ...
| }
|
|
Navigation after save is handled by pages.xml:
| <page view-id="/restricted/editBidder.xhtml"
no-conversation-view-id="/restricted/manageBidders.xhtml">
| <restrict>#{s:hasRole('Bidder') or
s:hasRole('BR')}</restrict>
| <navigation from-action="#{bidderManager.save}">
| <rule if="#{bidderManager.action ==
constants.EDIT_MYACCOUNT}">
| <redirect view-id="/home.xhtml"/>
| </rule>
| <redirect view-id="/restricted/manageBidders.xhtml"/>
| </navigation>
| </page>
|
|
Now, for the user (the Bidder) the process is as follows:
His menubar has a link to "my account":
| <s:link id="accountBidder"
rendered="#{s:hasRole('Bidder')}" view="/home.xhtml"
action="#{bidderManager.showEditMyAccount}"
value="#{messages.label_MyAccount}" propagation="none"/>
|
As you see, it is the same action class BidderManager, but in this case the
showEditMyAccount method
| @Begin(join = true)
| @Restrict("#{s:hasRole('Bidder')}")
| public void showEditMyAccount() {
| selBidder = loggedInUser.getBidder();
| userName = selBidder.getUserName();
| action = Constants.EDIT_MYACCOUNT;
| }
|
This presents the user with the same page as the admin, but with some fields disabled. The
same bidderManager.save() as for the admin is called on submit. The loggedInUser object is
a Session scoped object created during login.
The only significant difference I can see is that the edited user object comes from a
Session scoped search component in one case, and a directly from the Session scoped
loggedInUser object in the other.
Any ideas on how I can get org.jboss.seam.handledException would be very helpfull
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4078018#...
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&a...