Results 1 to 7 of 7

Thread: propogating Hibernate session

  1. #1
    Join Date
    Oct 2006
    Posts
    156

    Default propogating Hibernate session

    Hi,

    I have a bunch of classes that implement a command interface:

    Code:
    interface Executable {
        public void Element execute();
    }
    Within the execute() method of these classes I call methods on a DAO (that implements HibernateDaoSupport) and also call methods on the objects returned by the DAO, for example:

    Code:
    Customer customer = dao.getCustomer(name);
    List<Order> orders = customer.getOrders();
    Because the orders collection is lazily loaded, the Hibernate session needs to be available within the execute() methods. Also, I want the boundaries of the transaction to be the start and end of each execute() method.

    Using Spring 1.2, how can I ensure the execute() methods propagate the session to the DAO and ensure that the transaction boundaries are defined as described above?

    Thanks in advance,
    DM
    Last edited by domurtag; Feb 3rd, 2008 at 12:43 PM.

  2. #2
    Join Date
    Jul 2007
    Posts
    101

    Default

    This is actually quite easy, I just don't understand what you are trying to accomplish. The standard Hibernate pattern is that once you commit a transaction, you are done with the session. Why would you want the same session to propagate? But, if that is what you want, then this is how you would do it.

    I will assume that you are using the TransactionTemplate, if not, hopefully you can apply the concept going forward. Since the sessions are thread local bound, you will get the same session as long as you don't close it. Using the transaction template, this means that the transaction hasn't been completed. here is the flow:

    Start the transaction at the entry point into your chain of command and only exit the transaction when the chain is completed. At each execute method, tell the transaction/template to start the transaction and at the end of the execute, tell it to commit the transaction. A simple template patterm/base command class will hide this nicely. Then in your execute, perform your dao calls.

    If you look at the transactional test support examples, you will see how to commit and restart transactions in the middle of an uber transaction.

    If you are managing transactions yourself, then the same concept applies. Everything will use the same session until the session is closed and removed from the thread local.

    Hope this makes sense.

  3. #3
    Join Date
    Oct 2006
    Posts
    156

    Question

    Thanks very much for the reply. I am managing transactions programatically with TransactionTemplate, and the boundaries of each transaction should be the start and end of each execute() method, because the relevant code looks like this:

    Code:
    public void process(final IExecutable cmd) {
    
        final PrintWriter output = getOutputWriter();
    
        // Execute the command within a transaction created by the transactional template
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
    
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    final Element result = cmd.execute();
        	        output.println(result.asXML());
    
                } catch (Exception e) {
    
                    // Instruct Spring to rollback the transaction
                    status.setRollbackOnly();
                    throw new ExecutionException(e);
                }
            }
        });
    }
    The implementation of cmd.execute() contains the following code:

    Code:
    Customer customer = dao.getCustomer(name);
    List<Order> orders = customer.getOrders();
    When customer.getOrders() is called a LazyInitializationException is thrown. The exception message indicates that the session has closed, or there is no session, so I can only assume that the session is being closed once the DAO method has completed.

    However, you said in your reply:

    Everything will use the same session until the session is closed and removed from the thread local
    So it seems that the session should only be closed when doInTransactionWithoutResult() has completed.
    Last edited by domurtag; Feb 3rd, 2008 at 09:17 PM.

  4. #4
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,624

    Default

    Why so complex? How are you creating instances of the Execute interface? Are they defined inside the ApplicationContext? If so simply put them in an TransactionProxyFactoryBean, configure the execute method to be transactional and presto. (You might even get away with a BeanNameAutoProxyCreator and a TransactionInterceptor).
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  5. #5
    Join Date
    Oct 2006
    Posts
    156

    Default

    Quote Originally Posted by mdeinum View Post
    How are you creating instances of the Execute interface? Are they defined inside the ApplicationContext? If so simply put them in an TransactionProxyFactoryBean, configure the execute method to be transactional and presto
    No, they're created by a factory class. I did try replacing the programmatic transaction management with a TransactionProxyFactoryBean that defines the process() method of the class shown above to be transactional, but I still had the same problem.

  6. #6
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,624

    Default

    Code:
    No, they're created by a factory class.
    A factory of yourself or a FactoryBean from Spring?

    If you 'new Executable()' something in your factory bean Spring is going to do nothing for you. What you could do is to define you Executable(s) in your application context (as prototype) , put a TransactionProxyFactoryBean around it and let your factory bean retrieve a new instance from the application context each time instead of creating a new one yourself. That way you will have transactional behavior configured instead of programming it each time (and injecting stuff manually).
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  7. #7
    Join Date
    Oct 2006
    Posts
    156

    Default

    Thanks very much for the reply. I like the sound of what you're suggesting, but am not entirely sure how to implement it. Currently, the factory that creates the IExecutable instances is a class I've written myself, rather than a bean configured in Spring. The factory method has the following signature:

    Code:
    public IExecutable getExecutable(Operation operation, Target target)
    This method will return one of 14 different implementations of the IExecutable interface. Regarding your suggestion, the first thing I'm unclear about is:

    define you Executable(s) in your application context (as prototype) , put a TransactionProxyFactoryBean around it
    Do you mean that I should configure a separate TransactionProxyFactoryBean bean for each implementation of IExecutable? This will greatly increase the size of my config file, and is not an appealing solution because the config will need to be changed each time an implementation of IExecutable is added/removed.

    Secondly, the factory method of FactoryBean does not take any parameters, so I'm not sure if I can use this to replace my existing Factory class which requires two parameters (see above) to figure out which implementation of IExecutable to return.

    Thanks Again!
    - DM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •