views:

176

answers:

2

I'm working on some data access logic with Spring, my question has to do with transactions. The transaction documentation http://static.springsource.org/spring/docs/2.5.x/reference/transaction.html shows that you can implement declarative or programmatic transactions. I've chosen to use the programmatic approach so that I have finer control over what is transacted.

The basic pattern looks like this:

Product product = new Product();
// load properties 

// how do I pass my product object instance to my anonymous method?   
transactionTemplate.execute(
      new TransactionCallbackWithoutResult() 
      {
       protected void doInTransactionWithoutResult (TransactionStatus status)
       {
        // transaction update logic here
        return;
       }}); 

Perhaps i'm going about this the wrong way but, my question is how can I pass arguments into the inner anonymous method? The reason I want to do this is so I can build up my object graph before starting the transaction (because transactions should be as short time wise as possible right? ) I only want a fraction of the logic to run in the transaction (the update logic).

[edit]

So far it seems my only choice is to use a constant variable, or just put all logic inside the anonymous delegate. This seems like a very common problem...how have you handled situations like this in your own code?

+2  A: 

Declare it final. Anonymous inner classes have access to final local variables:

public void someMethod() {
    ...
    final Product product = new Product();
    ...
    transactionTemplate.execute( 
        new TransactionCallbackWithoutResult()  
        { 
            protected void doInTransactionWithoutResult (TransactionStatus status) 
            { 
                doSomething(product);
                return; 
            }}); 
    ...
}
axtavt
I can't, product is an instance type and it needs to be loaded in the containing method and I don't want to make this a class member variable either. The containing method will be called repeatedly so I don't think making it static would work unless i'm missing something.
James
@James: I mean a final local variable
axtavt
This method will be called by different threads it's being used in a web application. If I make the local variable final that would not be thread safe would it?
James
The `final` keyword on a variable marks that the variable is a constant. It's not like a `static` in C++
axtavt
James - think of it this way. someMethod executes in thread one and defines product product and freezes. someMethod executes in thread two and defines product product, but it has its own product - it didn't overwrite product in thread one because thread one's product exists only in the execution of thread one. When thread two gives up, and thread one resumes, the product of thread one is still there - it's instance variables you must be careful with when executing methods that could be used by two threads at the same time.
MetroidFan2002
@MetroidFan - Hence my concern with making the instance variable a constant. I'd prefer to use a method scope instance variable rather than a constant but that is the only suggestion thus far.
James
+1  A: 

For things like this I use the following ObjectHolder:

public class ObjectHolder<T> {
    private T m_object;

    public ObjectHolder( T object ) {
        m_object = object;
    }

    public T getValue() {
        return m_object;
    }

    public void setValue( T object ) {
        m_object = object;
    }
}

Then you can use

final ObjectHolder<Product> productHolder = 
    new ObjectHolder<Product>( new Product() );

...and inside your anonymous class you can access your Product with

productHolder.getValue();

...or change it's instance with

productHolder.setValue( new Product() );
tangens