-
1. Re: Refresh issue with conversation scoped page
nbhatia.bhatian.comcast.net Sep 28, 2009 9:20 PM (in response to nbhatia.bhatian.comcast.net)Any thoughts on this issue? Could it be that the entity manager is not fetching fresh instances of Order entities because they are already sitting in the session? In that case, is conversation scope a bad idea for this use case?
Thanks.
Naresh
-
2. Re: Refresh issue with conversation scoped page
asookazian Sep 29, 2009 5:30 PM (in response to nbhatia.bhatian.comcast.net)The factory method will only be executed if orders is null. If you are posting back to the same JSF page, it will not be null b/c you are using PAGE scope.
Try using:
@DataModel(scope=ScopeType.EVENT)
Another option is to not use @Factory and call the method directly as follows:
<h:dataTable id="orderTable" value="#{orderListController.findOrders}" var="order">
but make sure to check for null in the findOrders() method to avoid unnecessary db hits. Add a debug brkpt in the method to see when it's actually being called...
-
3. Re: Refresh issue with conversation scoped page
nbhatia.bhatian.comcast.net Sep 30, 2009 7:38 AM (in response to nbhatia.bhatian.comcast.net)Arbi, I tried with
@DataModel(scope=ScopeType.EVENT)
but that gives me the following runtime error:java.lang.IllegalArgumentException: @DataModel scope must be ScopeType.UNSPECIFIED or ScopeType.PAGE: orderListController
You also mentioned that
Another option is to not use @Factory and call the method directly as follows:<h:dataTable id="orderTable" value="#{orderListController.findOrders}" var="order">
That's pretty much I am doing in when the update button is clicked:
<h:commandButton value="Update" action="#{orderListController.findOrders}" />
It is calling findOrders() directly, which should update the orders context variable and the DataTable should display that. As noted above, all that is happening - the trouble is that findOrders() is not returning the right results. Although the underlying database has been changed by some other transaction, findOrders() is not picking up the change.
If I change the scope of OrderListController itself to Event, then it is picking up the changes by another transaction (obviously - because it is not keeping a hibernate session open). But the down side is that selection of table rows now stops working, i.e DataModelSelection does not work. So it seems that I can get one thing or the other, but not both.
Any further ideas?
Thanks.
Naresh
-
4. Re: Refresh issue with conversation scoped page
nbhatia.bhatian.comcast.net Sep 30, 2009 2:01 PM (in response to nbhatia.bhatian.comcast.net)I just confirmed that the problem is because orders are being cached in Hibernate's session cache. In the hibernate query above, if I simply clear the session before querying, I do get fresh instances of orders from the database. Unfortunately that can't be my solution because clearing the session clears out many other objects that my front end relies on and thus other things break.
Has anyone come across this problem? How did you solve it?
Thanks.
Naresh
-
5. Re: Refresh issue with conversation scoped page
javacoryd Sep 30, 2009 11:23 PM (in response to nbhatia.bhatian.comcast.net)If you can't do a clear() on the entityManager you can loop over the list of orders calling entityManager.refresh( order ).
Cory.
-
6. Re: Refresh issue with conversation scoped page
nbhatia.bhatian.comcast.net Oct 1, 2009 12:55 AM (in response to nbhatia.bhatian.comcast.net)Thanks Cory. That works! The only drawback is that it is doing a select for every order. Hey, but at least it works!
I may play around with another approach where I don't use @DataModelSelection. This would allow me to get rid of the conversation and use plain old event scope.
-
7. Re: Refresh issue with conversation scoped page
javacoryd Oct 1, 2009 3:20 PM (in response to nbhatia.bhatian.comcast.net)An alternative to this approach which doesn't do a single query for each order is to drill down to the Hibernate Session ( em.getDelegate() ) and explicitly evict() each order. You can then re-run your query and it will reload the orders from the DB.
Cory.
-
8. Re: Refresh issue with conversation scoped page
nbhatia.bhatian.comcast.net Oct 1, 2009 4:13 PM (in response to nbhatia.bhatian.comcast.net)Good suggestion! I tried it, but running into another problem with this strategy. The evict is happening fine, but the following findOrders() call is trying to do a flush, which is forcing the detached orders to persist via some cascade relationship and Hibernate does not like that:
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: org.archfirst.bullsfirst.domain.order.Order at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:102) at org.hibernate.impl.SessionImpl.firePersistOnFlush(SessionImpl.java:671) at org.hibernate.impl.SessionImpl.persistOnFlush(SessionImpl.java:663) at org.hibernate.engine.CascadingAction$9.cascade(CascadingAction.java:346) at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:291) at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:239) at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:192) at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:319) at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:265) at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:242) at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:192) at org.hibernate.engine.Cascade.cascade(Cascade.java:153) at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:154) at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:145) at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88) at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:58) at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:996) at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1589) at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:306) at JpaAccountRepository.findOrders(JpaAccountRepository.java:102)
-
9. Re: Refresh issue with conversation scoped page
javacoryd Oct 1, 2009 7:44 PM (in response to nbhatia.bhatian.comcast.net)Yea, the reason this is happening is because you probably have a relationship from Order to something as a OneToMany, OneToOne etc, and the evict() is not cascading to those relationships. EJB3 doesn't support the evict, but if you are using JBoss it works by adding an additional
Cascade
annotation from Hibernate to your relationship with a cascade type of EVICT.Like:
@Cascade(org.hibernate.annotations.CascadeType.EVICT)Cory.
-
10. Re: Refresh issue with conversation scoped page
nbhatia.bhatian.comcast.net Oct 2, 2009 4:32 AM (in response to nbhatia.bhatian.comcast.net)Thanks Cory. That's good to know.
-
11. Re: Refresh issue with conversation scoped page
nagendra_singh_krishnawat Oct 2, 2009 10:48 PM (in response to nbhatia.bhatian.comcast.net)ok, I see that you have declared both @DataModel and @Factory which are outjecting same context variable
order
, Since Data model itself is outjectingorder
in scope of conversation you dont need to say another @Factory.You can also define the scope of @datamodel (See datamodel attributes)
-
12. Re: Refresh issue with conversation scoped page
nbhatia.bhatian.comcast.net Oct 2, 2009 11:28 PM (in response to nbhatia.bhatian.comcast.net)Good observation - hadn't thought about that. However, this is what I have seen in all Seam examples (see this example). I understand that the factory is used to initialize the variable when none exists, whereas @DataModel outjects to support clickable links.
-
13. Re: Refresh issue with conversation scoped page
nagendra_singh_krishnawat Dec 2, 2009 1:05 AM (in response to nbhatia.bhatian.comcast.net)@Factory @Factory("processInstance") Specifies that the method of the component is used to initialize the value of the named context variable, when the context variable has no value. This style is used with methods that return void. @Factory("processInstance", scope=CONVERSATION) Specifies that the method returns a value that Seam should use to initialize the value of the named context variable, when the context variable has no value. This style is used with methods that return a value. If no scope is explicitly specified, the scope of the component with the @Factory method is used (unless the component is stateless, in which case the EVENT context is used). value — specifies the name of the context variable. If the method is a getter method, default to the JavaBeans property name. scope — specifies the scope that Seam should bind the returned value to. Only meaningful for factory methods which return a value.
Read the
value
description.