-
1. Re: Starting new conversation resets flush mode to auto
pmurphy.pjmurphy.paddypower.com Nov 17, 2009 3:25 PM (in response to pmurphy.pjmurphy.paddypower.com)Actually, even my resetFlushModes() method does not seem to work. If you set one entity manager then the other entity manager is also set. I've even created a new persistence-unit, so that I could have one for the entity manager that I want to keep from auto-flushing and one that auto-flushes. However, whenever I change the flush mode of one entity manager the other entity manager's flush mode is also set. It appears that it is impossible to have two separate entity managers in Seam/Hibernate with different flush modes at the same time. Does anyone have an opinion on this?
-
2. Re: Starting new conversation resets flush mode to auto
pmurphy.pjmurphy.paddypower.com Nov 17, 2009 5:29 PM (in response to pmurphy.pjmurphy.paddypower.com)Looking at the org.jboss.seam.persistence.PersistenceContexts (a singleton class per conversation - PersistenceContexts.instance()) code when the entity manager is being initialized via the ManagedPersistenceContext
org.jboss.seam.persistence.ManagedPersistenceContext.initEntityManager() private void initEntityManager() { entityManager = getEntityManagerFactoryFromJndiOrValueBinding().createEntityManager(); PersistenceProvider persistenceProvider = PersistenceProvider.instance(); entityManager = persistenceProvider.proxyEntityManager(entityManager); setEntityManagerFlushMode( PersistenceContexts.instance().getFlushMode() ); ... }
it would appear that only one persistent context per conversation is supported in Seam.
-
3. Re: Starting new conversation resets flush mode to auto
pmurphy.pjmurphy.paddypower.com Nov 17, 2009 7:03 PM (in response to pmurphy.pjmurphy.paddypower.com)If someone else has the same problem, a possible work around is to look up second entity manager and not let Seam inject it.
private EntityManager manualEntityManager; @Create @Override public void create() { manualEntityManager = (EntityManager)Component.getInstance("manualEntityManager"); ((Session)manualEntityManager.getDelegate()).setFlushMode(FlushMode.MANUAL); }
-
4. Re: Starting new conversation resets flush mode to auto
asookazian Nov 18, 2009 12:37 AM (in response to pmurphy.pjmurphy.paddypower.com)your scenario is interesting but why do you need one AUTO and one MANUAL?
-
5. Re: Starting new conversation resets flush mode to auto
pmurphy.pjmurphy.paddypower.com Nov 19, 2009 10:11 AM (in response to pmurphy.pjmurphy.paddypower.com)I have a complex screen using different modules (included xhtml files) where part of it uses fast update (i.e. when the user enters data it is automatically pushed to the server using ajax on validation), and another part of the screen where values need to be validated (via ajax request) but not saved to the database until the user presses a save button. To handle the latter case, I do a look up using the standard entity manager, whose flush mode is auto, and set the individual changes from the entity that was looked up using the manual entity manager and push them to the standard one. At this point the individual changes are saved to the database as the flush mode is auto for the standard entity manager.
So, in short, I have a requirement for some changes to be auto-saved and some changes that mustn't be saved until a save button is pressed.
BTW, for the previous snippet of code to work you would also need to define the following in your components.xml file.
<persistence:managed-persistence-context name="manualEntityManager" auto-create="true" persistence-unit-jndi-name="java:/manualEntityManagerFactory" /> <persistence:managed-persistence-context name="entityManager" auto-create="true" persistence-unit-jndi-name="java:/standardEntityManagerFactory" />
-
6. Re: Starting new conversation resets flush mode to auto
pmurphy.pjmurphy.paddypower.com Nov 19, 2009 10:17 AM (in response to pmurphy.pjmurphy.paddypower.com)Slight correction to components.xml as you can shared the same persistent unit.
<persistence:managed-persistence-context name="manualEntityManager" auto-create="true" persistence-unit-jndi-name="java:/myEntityManagerFactory" /> <persistence:managed-persistence-context name="entityManager" auto-create="true" persistence-unit-jndi-name="java:/myEntityManagerFactory" />
Of course, the JNDI name 'java:/myEntityManagerFactory' needs to correspond to the 'jboss.entity.manager.factory.jndi.name' property defined in your persistence-dev.xml and persistence-prod.xml files.
-
7. Re: Starting new conversation resets flush mode to auto
asookazian Nov 19, 2009 6:06 PM (in response to pmurphy.pjmurphy.paddypower.com)
To handle the latter case, I do a look up using the standard entity manager, whose flush mode is auto, and set the individual changes from the entity that was looked up using the manual entity manager and push them to the standard one. At this point the individual changes are saved to the database as the flush mode is auto for the standard entity manager.I don't see why you can't use either one EntityManager with manual flush or two EntityManagers with manual flush. The latter case is typically required when you need to do CRUD on more than one DB (which is likely not the case here).
With Seam apps it is typically recommended to use SMPC with Hibernate manual flush (if Hibernate is your persistence provider). The advantage is that you can keep the persistence context open for the duration of the conversation and thus the entities don't get detached until after the em.flush() to the SMPC (which typically occurs at the end of the conversation).
So the main point here is that irrespective of the fast AJAX save and regular HTTP POST of form save, you should be able to flush() the SMPC twice per conversation (or n times prior to the end of the conversation).
Here's an example using SFSB:
@Name("foo") @Stateful public class Foo { @In //use SMPC, not container-managed PC private EntityManager entityManager; @Begin(join=true, flushMode=FlushModeType.MANUAL) public void someStartMethod() { //do some stuff or start LRC from pages.xml } public void fastUpdate() { //do some stuff; remember merge() is a crude operation and is not required //b/c JPA does write-behind and dirty-tracking of changes in the PC //via the 1st level cache entityManager.flush(); } @End public void save() { //do some stuff like entityManager.persist(foo) or update, etc. entityManager.flush(); } }
The SMPC is conversation-scoped, so it remains open until the end of the LRC (thus avoiding LIEs). In Seam apps, if you are using Hibernate, you should typically never need to use AUTO or COMMIT modes for flushing the PC.
-
8. Re: Starting new conversation resets flush mode to auto
pmurphy.pjmurphy.paddypower.com Nov 19, 2009 6:37 PM (in response to pmurphy.pjmurphy.paddypower.com)Hi Arbi,
Thanks for the response. The reason I can't use just one entity manager is because of the screen layout and business requirement. Let me explain. I have a screen (web page) where the data that is represented on the screen is from multiple entities. The screen is spit up into different parts where the user needs the ability to update different entities independently of each other. When they change some parts of the screen the changes need to be auto saved while others parts need to be delayed-saved until the user presses a save button. There are multiple save buttons on the screen to update different parts of it where one save affects some set of entities but not other entities on separate parts of the same screen.
I am trying to achieve very fine-grained control of what is saved and when it is saved on a very complex control screen.
If I used your approach when I called entityManager.flush() it would flush all changes on the screen and not just the particular ones that the user was working with. That is, the user has modified two or more parts of data on the screen, but only wants to save one part as he still hasn't made up his mind if he wants to commit the other changes that they have made.
Thanks again for your input.
Philip
-
9. Re: Starting new conversation resets flush mode to auto
asookazian Nov 19, 2009 7:47 PM (in response to pmurphy.pjmurphy.paddypower.com)http://seamframework.org/Documentation/HowDoIUseMultipleDynamicEntityManagersInSeam
use two EntityManagers with Hibernate manual flush for both. I had a similar use case (see 2nd link above)
-
10. Re: Starting new conversation resets flush mode to auto
pmurphy.pjmurphy.paddypower.com Nov 20, 2009 9:52 AM (in response to pmurphy.pjmurphy.paddypower.com)Hi Arbi,
Thanks for the links - interesting reading.
The posts cover using two manual entity managers which have both their flush modes set to manual. In my specific case, I need to use one entity manager with flush mode auto and one manual to control different parts of a complex screen(s). The auto one is required as certain parts of the screen (which are very complex) have been developed separately by other developers which have used auto flush mode (actually most screens in the application use auto flushing). My particular part of the main control screen, which again is a very complex component needs deferred-save functionality, so in this case I use an entity manager with flush mode set to manual. As the project has been in development for 6 months I can't get or have the time to change all entity managers to manual flushing and use flush-on-demand. I guess we are where we are, but at least I have a solution that meets the business requirements, but without the need to change how different components work currently.
All the same, thanks for the ideas.
Cheers,
Philip
-
11. Re: Starting new conversation resets flush mode to auto
asookazian Nov 20, 2009 8:56 PM (in response to pmurphy.pjmurphy.paddypower.com)Ok, so the problem is you must use one AUTO flush and one MANUAL flush...
this is your solution, correct?:
private EntityManager manualEntityManager; @Create @Override public void create() { manualEntityManager = (EntityManager)Component.getInstance("manualEntityManager"); ((Session)manualEntityManager.getDelegate()).setFlushMode(FlushMode.MANUAL); }
Why don't you use @Unwrap like is done in this example:
@Name("entityManager") @Scope(ScopeType.CONVERSATION) public class DynamicEntityManager { @Unwrap public EntityManager getEntityManager() { EntityManager entityManager = (EntityManager)Component.getInstance("entityManager"); return entityManager; } }
That way you can simply reference entityManager and you'll get the instance you want. No need for @Create method in every class that needs the EM...
In any event, this sounds like a possible JIRA issue. not sure what the official recommendation is for this scenario...