This forum is now a read-only archive. All commenting, posting, registration services have been turned off. Those needing community support and/or wanting to ask questions should refer to the Tag/Forum map, and to http://spring.io/questions for a curated list of stackoverflow tags that Pivotal engineers, and the community, monitor.

Transactions spanning database and server upload etc.

I am pretty much a beginner with Spring, and I am trying to set up a new architecture with Spring and Hibernate.

We have one database, but also a server that our clients talk to. For example, they can upload a form to the server and access it later (it's details also get added to the database).

I would like to combine these two actions - uploading the form to the server, and updating the database - into a single "transaction", but, I am having a particular problem figuring out how to configure Spring in such a case.

For example, if the form is uploaded ok, but updating the database fails for some reason, how does Spring know how to roll back the uploading of the form to the server ie to call a method that removes it from the server? Do I need to define some kind of transaction manager for the server? If so, any pointers would be appreciated!

Comment

The file system isn't transactional. So you would need to write code to delete the file if the DB transaction fails. Alternatively, you could consider writing the data to a BLOB in the DB in the same transaction, so that a single Spring tx can span both storing the information about the data and the data itself.

Comment

Actually our server is seperate, so uploading a form to the server is more than writing to the filesystem - we have to connect to the server, call it's API to upload it etc..

What I'm trying to get my head around is whether I can write some code to allow Spring to "know what to do" if I need to rollback both the transaction that spans both the db transaction (Hibernate) and my own transaction with the server. eg is there any way to tell Spring to "include this when you rollback a transaction" in a declarative mode?

Can I set up some kind of transaction manager for the server that Spring can recognize and use? If not, and I have to write it each method to handle a transaction rollback programmatically (soemthing I really want to avoid if possible), do I have to change how I handle Hibernate transactions to combine the two?

Comment

Yes, you can attach to the transaction synchronization that Spring is already using. This is how thread bound resources such as Hibernate Session Factories get handled, for example.

There's no real documentation on doing this, since this is normally used internally, however all the classes in question have pretty extensive JavaDocs, and there is lots of sample code in terms of the various pieces of code that use this mechanism (Hibernate integration, iBatis, JDO, etc.).

Comment

TransactionSynchronizationManager is the basic for synchronization with the current transaction, via thread bound holders for resources.

Take a look at how it is used for example via SessionFactoryUtils and HibernateInterceptor. SessionFactoryUtils.getSession ultimately ends up registering a new synchronization, where the Hibernate Session is kept in a SessionHolder class, which is registered (indirectly as a an SpringSessionSynchronization class) as a transaction synchronization. This basically gets callbacks to synchronize with events on the transaction. Looking at HibernateInterceptor, you can see how an interceptor can get in on the action. If you look at the invoke method, the call to getSession will cause the binding and synchronization to happen if there is none. The 'else' case handles the situation where the HibernateInterceptor is applied (accidentally) before the transaction interceptor itself, ensuring that the newly created session is at least still bound to the current thread, althoughin this case it will not be also synchronized to the transaction, since there is no synchronization registered in this case, as the tx doesn't even exist yet. However, that will happen later when a session is requested, as SessionFactoryUtils getSession() will notice that the session needs to be registered.

Comment

Another question emerges - for just the database stuff, I have a TransactionProxyFactoryBean set up for my Service Object (Manager), linked to a HibernateTransactionManager.

Now, to handle the database transactions and the server transactions, can I create a ServerTransactionManager and link the 2 together somehow? Or do I need to create a single HibernateAndServerTransactionManager and apply it to my Service object?

Just transactionally wrap (using TransactionProxyFactoryBean or BeanNameAutoProxyCreator) all the service objects which need to be transactional. There is no issue if they call into each other, either.

Regards,

Comment

But that's the thing - I have a Service object called FormManager, which makes calls to the database using my FormDAO which uses HibernateTemplate, and in the same method (addForm()) also calls the server API using my FormsetDAO (on the Server it's called a FormSet) which will be managed by my Server transaction stuff.

So, what do I set as the Transaction manager for the FormManger service object when I wrap it as TransactionProxyFactoryBean? At the moment it's the HibernateTransactionManager, but that's without the server stuff...

Many thanks,

David

Comment

Presumably you are going to add your own code to synchronize to the existing database transactions (as per the previous entries), but that can still all be handled through the one transaction manager, HibernateTransactionManager in this case. The fact that this transaction manager is Hibernate aware and creates a session to bind to the current thread/tx on entry does not impede synchronizing other aspect to it as well...

Everything that needs to be transactional needs to be wrapped with a proxy which is hooked up to this transaction manager. When it comes to your server stuff which needs to synched in, you have to do it in a fashion similar to the way the existing classes which do this kind of thing (like SessionFactoryUtils) do it.

Regards,

Regards,

Comment

thanks! That was one of the missing pieces!! Things are progressing much better now...

Just a quick qu:

Is there any reason that SpringSessionSynchronization (inner class in SessionFactoryUtils) receives both the SessionHolder and the SessionFactory - can't it just get the SessionHolder using the SessionFactory via TransactionSynchronizationManager?

cheers,

David

Comment

I too have a similar need. In our current system, we "simulate" XA txns via a composite TransactionManager (of our own design), in which Oracle, JMS, and other instances get registered. Since our TransactionManager is not really XA (it just does its best using single phase commit) the registered sub-managers are assigned a priority. For example, JMS is always the lowest priority so that messages are only sent to clients if all else succeeds. While this leaves some holes, it is very fast compared to XA.

So, my question: From your posts and my browsing, I gather that there is no concept of a composite TransactionManager in spring. And that TransactionSynchronizationManager is used to register resources that will be called back by AbstractPlatoformTransactionManager.

But we would like to use the predefined spring Hibernate and JMS txn managers (and get rid of our own). So I'm a bit confused as to how to proceed in recreating our "poor-mans" XA using spring.

Comment

Is there any reason that SpringSessionSynchronization (inner class in SessionFactoryUtils) receives both the SessionHolder and the SessionFactory - can't it just get the SessionHolder using the SessionFactory via TransactionSynchronizationManager?
David

Consider the resume method for example, where it needs to rebind the session holder with the session factory as the key. That's at least one place it needs both. Once it has it for that, it may as well use it in a number of other places directly (it's cleaner), even if it could theoretically get it from the synchronization manager.