long conversation - rich client applications RCP - spring and hibernate

After much thought it appears that easily grafting long conversation support into standard spring is challenging. It forces code into the DAOs that should be made more transparent--perhaps through AOP etc--but is a twisting of how some of the core classes in spring work around hibernate (which is based more or less on session-per-request).

The way I see it, the two key classes are SessionFactoryUtils and SynchronizationTransactionManager. The STM class is merely a way to stash global variables on the thread. They can be keyed (because the data is stored in a hashmap inside of the STM class) so it is a general purpose mechanism. STM also has TransactionSynchronization support which are really just listener objects listening to transaction events such as begin, commit, etc--its a transaction specific listener/observer pattern.

The real crux is probably in the SessionFactoryUtils class. This class supports getting the current session from the STM based on the session factory. In the case of conversations, we would have multiple sessions open at once and these managed sessions need to have a different way of being activated or deactivated. I think this is much the way the Seam framework does it with their contextual sessions. The word managed sessions is probably better because "contextual" sounds like spring contexts and could be confusing. Managed sessions suggest that while the session is managed, you can plug in different management strategies. What we really need is a session manager that is more global and keyed by some type of key such as a "session id" so that it can be accessed and used by any other object such as DAOs. The session manager would need to be able to know when to switch in that session into the thread and when that session id is asked for and is already active, when to not switch it in. That way, only the switching of the session is needed and the rest of the spring framework dealing with transactions can work without changes.

In a previous blog I had created a LongSessionManager-type object but stands alone and must be programatically used versus other ways. I will think through using it in an interceptor as well as through annotations (like Seam) to help facilitate related objects (such as a DAO tree) using the right session in a coordinated fashion. We need to think of a SessionFactoryUtils that is more in the spirit of Hibernate's ManagedSessionContext object or seam's context management. Note that in Java Persistence with Hibernate, they show the ability to bind and unbind a session using an interceptor. Using spring, we could program this interceptor using AOP. This is not hard in spring.

Some of the requirements include:

  • Works transparently with spring and works well with dependency injection.

  • Allows DAOs to be used hierarchically (nested calls) or sequentially, as in a transaction script design pattern.

  • Allows the session to be used across transactions in a JTA environment.

  • Allows a central management of the session objects themselves e.g. the session object does not have to be managed within user created objects.

  • Allows multiple long-conversations to exist simultaneously on the same thread using detached objects or an extended persistence context (using hibernate language).

  • Allows one conversation to be active/selected at a time per thread.

  • Allow objects to select which conversation should be used for its operations either through annotations, programatically or of course AOP interceptors.

  • Switching to a conversation within a conversation should not disrupt the transaction synchronizations that exist.

  • Allows nested conversations.

  • Allows the user to define long conversations as well as being automatically created.



One design decision is to ensure that we can identify the entry and exit point of the session used in the conversation. The session would need to be instated into the frameworks at the start then removed at the end of the conversation. How we demarcate this "start" and "stop" points will determine the ease by which we can use the machinery. In some cases, especially to replicate certain framework behaviors, the same method would be the start and stop points for using a session. Here are a couple of use cases to describe this.

@Repository
@Transactional(readOnly = true)
public class PersonDao {

public Person find(int id) { ... }

public List findAll() { ... }

@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void changeName(Person p, String newName) { ... }

}


  • @Repository indicates the use of spring support to translate exceptions. It requires a coordinating bean object in the context from which PersonDao is managed.

  • @Transactional indicates that the methods should be transactional, the default is read-only. However, changeName should needs to be write.



But what if we want to have a long conversation around Person? Perhaps keep all the people in an extended persistent context? And we don't want to have to add any code to the DAO (lining up with spring's design approach) and instead configure it where possible? Also, what if we want to get all the people inside an already active session in order to retrieve some information needed for that separate conversation (in other words, entity data from different sessions may need to interact).

What if we want to use the HibernateTemplate inside a DAO to do this work but not change anything around the DAO implementation? HibernateTemplate uses SessionFactoryUtils to access the current session for a session factory from the STM. If so, the session must be installed as the current session in the STM when the HibernateTemplate code is called and also ensure that the session is not closed when the template is finished.



Just a thought. More later.

Popular posts from this blog

React, Redux, Recompose and some simple steps to remove "some" boilerplate and improve reuse

cats/cats-effect and webservices function composition

typescript ambient declarations, global.d.ts, lib and typeRoot.md