Depending on your environment and used JPA-implementation you might experience the problem
that there are database connections which have not been passed back to the connection pool.
This can happen if you use entities with e.g. OneToMany mappings and lazy init AND accessing the OneToMany collection from your JSF view the first time.
The EntityManager has to re-establish a connection to your database, but now that this happens outside of your conversation scoped bean, no one ends the transaction and so no one puts the connection back to the pool.
The problem is that with a growing number of users and a growing number of conversations (especially not ended conversations - waiting for their timeout) your pool might exhaust.
As said before, this might not be the case with all JPA-implementations. But we had at least one environment where this happened, so here the work-around.
To activate the workaround simply put the following code in your spring config and adjust the names as required.
<bean id="managedDataSource" class="org.apache.myfaces.orchestra.connectionManager.ConnectionManagerDataSource"> <property name="dataSource" ref="dataSource"/> </bean>
You have to configure
the property dataSource to point to the original datasource and
the JPA configuration to use our managedDataSource (adjust the name if required)
PropertyPlaceholderConfigurer STOPS working after the introduction of orchestra into my configuration
Use the <aop:scoped-proxy> configuratino with in the persistentContextConversationInterceptor definition. You'll end up with something like:
<bean id="persistentContextConversationInterceptor" class="org.apache.myfaces.orchestra.conversation.spring.PersistenceContextConversationInterceptor"> <aop:scoped-proxy/> <property name="persistenceContextFactory" ref="persistentContextFactory"/> </bean>
The reason is, that, during startup of the spring system when the custom scope will
be initialized, the system might already require a datasource, but at this time
the PropertyPlaceholderConfigurer didn't run already.
Using the <aop:scoped-proxy> configuration allows the initialization process to end cleanly.
If your ViewController event methods are called twice you probably configured the
ViewControllerPhaseListener in your faces-config.xml which is not required.
Orchestra already does this for you.
Each conversation has its own persistence context, but an entity can only be managed
by the context it was loaded by.
Reading an entity may trigger lazy loads. This will always be performed using the persistence context that loaded the entity, ie this works regardless of who calls the method on the entity.
However performing operations like merge, delete, etc. require the object to be passed to a persistence context; if it is passed to the wrong one then unexpected behaviour will occur. Things like using the object in a query being executed in a persistence context that is not the one associated with that entity may also fail.
Rather than passing entity references between conversations, just pass the key of the object and reload it if access is required from a different conversation.
This is not an Orchestra limitation, but more a technical limitation of how ORMs work today.