0

I was wondering how to solve the following problem using Spring dependency injection:

Given that I have a list of Transactions of different types, I'd need to process them based on their TransactionType. So I’d have a TransactionController with a TransactionService as such:

public class TransactionController {
    private TransactionService transactionService;
    public void doStuff(List<Transaction> transactions) {
        for (Transaction transaction : transactions) {
            // use the correct implementation of transactionService based on the type
            transactionService.process(transaction);
        }
    }
}

public interface TransactionService {
    void process(transaction);
}

Without using Spring IoC, I would use a Simple Factory pattern to return the implementation based on the Type enum:

public class TransactionServiceFactory {
    public TransactionService(TransactionType transactionType) {
        // switch case to return correct implementation.
    }
}

How can I achieve the same injecting the TransactionService? I can't use the @Qualifier annotation, as implementation depends on the TransactionType. I've stumbled upon an article in the spring docs showing Instantiation using a factory method, but I cannot figure how to pass arguments to it.

I believe I probably have to use a different design with Spring IoC. I guess since I've always used the Simple Factory, Factory and Abstract Factory patterns, I can’t see a different way of solving this…

Can someone also please format this for me? The android app doesn't seem to do this, sorry!

2 Answers 2

2

In this case, factory pattern or similar is the correct solution, IMHO. Just implement a factory/registry/locator object and inject that using Spring. The rest is as usual. Injection happens when your object is created, but you need different implementations of the service during runtime. In this case, only service locator, factory or similar patterns make sense.

Sign up to request clarification or add additional context in comments.

4 Comments

But how would the injection framework switch the implementation in the middle of doStuff method? Even with the darkest of AoP magic, you wouldn't be able to swap objects in the middle of the loop. And even if you could, it would be a solution to stay away from.
Right... What if Spring had some sort of AbstractFactory that'd be called when using the uninstanciated service, then it'd check for a parameter meta-attribute and use it in the application configuration? Or have I gone completely insane? I think I need a break...
Well... as far as I know, there is no such thing OOB and it sounds too situational for a generic solution. You can, of course, make your own wrapper around the TransactionService that does whatever, but then you'd effectively be implementing one of the patterns from my original response. Heck, you could even make it somewhat generic, to e.g. find beans with Qualifiers with type names.
yep, I'll make a PoC injecting the factory and in the factory class injecting each service to be returned...
1

You can use Map property injection in this case:

**private Map<TransactionServiceMap>  transactionServiceMap;**


<!-- results in a transactionServiceMap(java.util.Map) call -->
**<property name="transactionServiceMap">
    <map>
        <entry key="TRANSACTION_TYPE_1" value-ref="transactionService1"/>
        <entry key ="TRANSACTION_TYPE_2" value-ref="transactionService2"/>
    </map>
</property>**

and in modify the for loop as stated below:

public void doStuff(List transactions) {

        for (Transaction transaction : transactions) {

            // use the correct implementation of transactionService based on the type

            TransactionService transactionService = transactionServiceMap
                                          .get(transaction.getType());

            transactionService.process(transaction);



        }

    }

2 Comments

That's interesting too... Well it seems there's no way to directly get the implementation...
You will always have different service instance for specific transaction type. So you can provide those instances through injection directly. Even if mutiple transaction type belongs to same service instance you can provide the same reference for both trasaction type.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.