List of Classes in play
SomeStrategyInterface - interface for strategy pattern
FooStrategy - implementation of SomeStrategyInterface
BarStrategy - implementation of SomeStrategyInterface
BazStrategy - implementation of SomeStrategyInterface
StrategyProvider - factory class to provide specific implementation of SomeStrategyInterface
MessageDispatcher - class that dispatches message to worker threads on type of message
ABTask - a type of worker class which handles specifics message type and needs StrategyProvider
The flow is
MessageDispatcher --> new ABTask() --> StrategyProvider.get()
public class ABTask implements Runnable{
public ABTask(StrategyProvider provider){
this.provider = provider
}
public void run(){
//need to use StrategyProvider here
}
}
public class MessageDispatcher{
private final StrategyProvider provider;
public void handleMsg(){
//I don't want to pass provider from here
new ABTask(provider)
}
}
Now to access StrategyProvider I will have to pass its instance from MessageDispatcher to ABTask since I am using Spring Dependency Injection. Though by doing this I am adding noise to MessageDispatcher class. So I was wondering is there any way to access this provider statically, or even expose the provider method as static so that I can use it from ABTask as follows:
public void run(){
StrategyProvider.get(args)
}
Please don't suggest to change MessageDispatcher class. Other ideas are welcome.
Assuming the StrategyProvider as a spring managed bean below approach should work
#Component
public class StrategyFactory {
private static StrategyProvider strategyProvider;
#Autowired
private StrategyProvider provider;
#PostConstruct
public void init() {
StrategyFactory.strategyProvider = provider;
}
public static StrategyProvider getStrategyProvider() {
return strategyProvider;
}
}
In another bean obtain the instance of StrategyProvider via autowiring and supply it to some static method. This static method than can be used in ABTask as below
public void run() {
StrategyFactory.getStrategyProvider().get(args)
}
However be aware of the gotcha here that if the static method StrategyFactory.getStrategyProvider() is invoked before Spring completes application contexts' initialization a nasty NullPointerException will be encountered.
Related
I have an Interface and multiple implementation. I'm auto wiring the interface in classes for usage. I need to choose different implementation at runtime.
public class Util {
public void getClient();
}
Implementations
public class UtilOne implements Util {
public void getClient() {...}
}
public class UtilTwo implements Util {
public void getClient() {...}
}
#Configuration
public class AppConfig {
#Autowired
#Bean
#Primary
public Util utilOne() {
return new UtilOne();
}
#Autowired
#Bean
public Util utilTwo() {
return new UtilTwo();
}
}
#Component
public class DemoService {
#Autowired
private Util util;
}
For some reason if we are unable to get client in UtilOne, I want to switch to UtilTwo without restarting the app. I want to change the Util object in DemoService to UtilTwo object.
Property active.util will come from DB and can we updated from UI.
It doesn't work this way - if you have a certain implementation of Util wired to, say, class SampleClass (which is a singleton) you can't really change the implementation of the Util to something different without restarting the application context.
So instead of going this way, I suggest an alternative. You say that under certain conditions that evaluate in runtime you want to switch implementations. What kind of condition it is? Is it possible to extract this condition decision logic?
If so, you can autowire a special DynamicUtil that will hold the reference to all the utils and will call the required util depending on the condition:
// represents all possible business 'runtime' outcomes
enum ConditionOutcome {
A, B, C
}
interface ConditionEvaluator {
ConditionOutcome evaluate(); // when called in runtime will evaluate a condition that currently exists in the system
}
interface Util {
void foo();
ConditionOutcome relevantOfOutcome();
}
class Utill1Impl implements Util {
public void foo() {...}
public ConditionOutcome relevantOfOutcome() {return ConditionOutcome.A;}
}
class Utill2Impl implements Util {
public void foo() {...}
public ConditionOutcome relevantOfOutcome() {return ConditionOutcome.B;}
}
class Utill3Impl implements Util {
public void foo() {...}
public ConditionOutcome relevantOfOutcome() {return ConditionOutcome.C;}
}
class DynamicUtil {
private final Map<ConditionOutcome, Util> possibleImpls;
private final ConditionEvaluator evaluator;
public class DynamicUtil(List<Util> allImplementations, ConditionEvaluator evaluator) {
// create a map by calling the 'relevantOfOutcome' per util impl in a loop
this.evaluator = evaluator;
}
public void foo() {
ConditionOutcome key = evaluator.evaluate();
// pick the relevant implementation based on evaluated key
possibleImpls.get(key).foo();
}
}
Now with such a design you can dynamically add new possible outcomes (along with utils that should implement them. You classes in the system will have to autowire DynamicUtil though, so effectively you'll introduce one additional level of indirection but will gain flexibility
class SampleClass { // a business class that will need to work with util capable of being changed during the runtime
#Autowired
private DynamicUtil util;
...
}
You can try approach with delegating proxy. Have a primary Util bean that is just wrapper around actual implementation and allow to change its internal delegate at runtime. In addition you can create something like manager/helper class that holds references to all actual implementation beans to simplify switching between them.
#Component
#Primary
public class DelegatingUtil implements Util {
private Util delegate;
public void setDelegate(Util delegate){ this.delegate = delegate; }
public Util getDelegate(){ return delegate; }
public void getClient() {
return delegate.getClient();
}
}
And where switching logic applies:
// Use #Named or #Qualifier or any other way to obtain references to actual implementations
private Util defaultImpl;
private Util fallbackImpl;
#Autowired
private DelegatingUtil switcher;
public void switchToFallback(){
this.switcher.setDelegate(this.fallbackImpl);
}
Note, this is only schematic example, you should take care about details like bean creation order, injection with qualifiers (maybe conditional), initialization and so on.
Here is a simple approach based on your situation. The main idea is that read active.util property from DB by PropertyService and wrap your Utils into RouteUtil:
#Component
public class RouteUtil {
#Autowired
private PropertyService propertyService;
#Qualifier("one")
#Autowired
private Util utilOne;
#Qualifier("two")
#Autowired
private Util utilTwo;
public void getClient() {
if ("one".equals(propertyService.read("active.util"))) {
utilOne.getClient();
} else {
utilTwo.getClient();
}
}
}
and in DemoService:
#Service
public class DemoService {
#Autowired
private RouteUtil util;
// RouteUtil.getClient() ...
}
You can change active.util to select which Util will be used at runtime without restarting the app.
Spring provides you a solution which I personally didn't like. What you can do is declare a
#MyInterface
List<MyIntercase> myimpls
Where MyInterface is your interface and list will contain all the implementations. However, I (since I didn't like this solution) wrote my own solution, where you can have a static factory that is self-populated by all implementations. So you don't have to inject all your implementations but choose them at run-time from a factory either by class name or by custom-defined name. An additional advantage is that the custom-defined name must be unique per factory. So lets say you have some staged process and for each stage you have your own interface and your own factory. So you can have the same custom defined names for your implementations of different interfaces. Say you working with text formats XML, JSON and CSV and have an interface (and related factory) for say stage-1 stage-2 stage-3. So for each stage-X inteface you can have implemetations named JSON, XML and CSV so all you have to do is have a variable called currentType that will hold one of the values - JSON, XML and CSV and for each stage you can use the factory to get the appropriate implementation:
Stage1Handler handler = stage-1-factory.getInstance(currentValue);
Stage2Handler handler = stage-2-factory.getInstance(currentValue);
Stage3Handler handler = stage-3-factory.getInstance(currentValue);
where Stage[X]Handler is your interface. But this is just an additional benifit. My solution is available in Open-source MgntUtils library. The article about this particular fiture could be found here: Non-intrusive access to "Orphaned" Beans in Spring framework Also, I describe this feature in my library javadoc here. The library could be found as Maven artifact and on Github including source code and Javadoc
I am new to spring framework. I have to use spring boot and have a rest controller as below :-
#RestController
public class StatisticsController {
private TransactionCache transactionCache;
public StatisticsController(TransactionCache transactionCache) {
this.transactionCache = transactionCache;
}
#PostMapping("/tick")
public ResponseEntity<Object> addInstrumentTransaction(#Valid #RequestBody InstrumentTransaction instrumentTransaction) {
transactionCache.addTransaction(instrumentTransaction);
return new ResponseEntity<>(HttpStatus.CREATED);
}
and I have a class which needs to be singleton :-
#Component
public class TransactionStatisticsCacheImpl implements TransactionCache {
private static TransactionStatisticsCacheImpl instance;
public static TransactionStatisticsCacheImpl getInstance(){
if(Objects.isNull(instance)){
synchronized (TransactionStatisticsCacheImpl.class) {
if(Objects.isNull(instance)){
instance = new TransactionStatisticsCacheImpl();
}
}
}
return instance;
}
private TransactionStatisticsCacheImpl() {}
I want to know the correct way to call this singleton class in my rest controller. I know that by default the scope of a bean in spring is singleton. Is this the correct way to call the singleton class in rest controller?
#RestController
public class StatisticsController {
private TransactionCache transactionCache;
public StatisticsController(TransactionCache transactionCache) {
this.transactionCache = transactionCache;
}
#PostMapping("/tick")
public ResponseEntity<Object> addInstrumentTransaction(#Valid #RequestBody InstrumentTransaction instrumentTransaction) {
transactionCache.addTransaction(instrumentTransaction);
return new ResponseEntity<>(HttpStatus.CREATED);
}
or
We need to call it using the getInstance() method? Also do we need to explicitly have the getInstance method in the TransactionStatisticsCacheImpl class?
One of the major advantages of container injection is that you can get the benefits of singleton semantics without all the serious problems of "hard" singletons (such as difficulty testing). Get rid of the getInstance manual business and let Spring take care of ensuring that a single instance is created and used for the context.
Just for clarification: By default, the spring IOC container will create only one instance per bean definition, unless if you specified otherwise using the #Scope stereotype. But if you create an instance using getInstance() the bean pre-processors and post-processors will not work correctly on that bean definition. And also you can use the #Autowired stereotype to inject a bean definition as needed and if you have different implementations for the same definition you can use the #Qualifier stereotype to specify the implementation that you need to inject, alternatively, you can use the constructor injection to inject your bean definition as needed without auto wiring as mentioned here Spring #Autowire on Properties vs Constructor
I would stick to the answers above. However, if you want to preserve further instantiation of the class in your code (or you want to keep your specific implementation of singleton), you can do it with getInstance().
Firstly, get rid of #Component annotation in your class:
// #Component
public class TransactionStatisticsCacheImpl implements TransactionCache {
private static TransactionStatisticsCacheImpl instance;
public static TransactionStatisticsCacheImpl getInstance(){
if(Objects.isNull(instance)){
synchronized (TransactionStatisticsCacheImpl.class) {
if(Objects.isNull(instance)){
instance = new TransactionStatisticsCacheImpl();
}
}
}
return instance;
}
private TransactionStatisticsCacheImpl() {}
}
Then, you may instantiate your singleton #Bean by defining #Configuration class - this way your bean would get managed by spring container.
#Configuration
public class SingletonConfiguration {
#Bean
public TransactionCache transactionCache() {
return TransactionCacheImpl.getInstance();
}
}
Eventually, you can have your singleton injected in your RestController using #Autowired.
#RestController
public class StatisticsController {
private TransactionCache transactionCache;
#Autowired
public StatisticsController(TransactionCache transactionCache) {
this.transactionCache = transactionCache;
}
#PostMapping("/tick")
public ResponseEntity<Object> addInstrumentTransaction(#Valid #RequestBody InstrumentTransaction instrumentTransaction) {
transactionCache.addTransaction(instrumentTransaction);
return new ResponseEntity<>(HttpStatus.CREATED);
}
}
It is a class which instance is connected to the external service and it is listening constantly of it.
#Component
public class Service extends PollingBot {
#Value("${token}")
private String token;
#Override
public void onUpdateReceived(Update update) {
if (update.hasMessage()) {
}
}
public void sendMessageToUser(String message) {
try {
execute(sendMessage);
} catch (ApiException e) {
}
}
}
You could see that there is a method called sendMessageToUser which send message. It could not be static because execute method not allow static context. This method could not be separeted to other class. /
So, I have to call this method from other class. However I don't want to create additional instance of Service class otherwise I have two instances which are listen for updates, but I want it is sole class instance doing so.
I have tried to run a Application Context and run method from it, but it was not worked.
So, my question is very simple. How could I run this class non-static(!) method from other class?
By default all spring managed beans are singleton. You need to use #Autowired to inject the bean into other and then you can call the methods of that bean.
#Autowired
private Service service;
public void sendMessage(String message){
service.sendMessageToUser(message);
}
You can use #Autowired annotation to call a method of a bean class(component) in Spring. Also, as mentioned by default beans are singleton in spring so you don't need to worry about creating a single instance explicitly every time.
Try to use the below code in the calling class:
#Autowired
private Service service;
public void sendText() {
service.sendMessage(message);
}
I am trying to use #Async annotation provided by spring. Going through some of the blogs I found there are the following constraints for using it:
It must be applied to public methods only
Self-invocation – calling the async method from within the same class – won’t work
I have a method which is getting called from the same class which I want to mark #Async. Is there any way of achieving it from the same class?
In Spring v4.3+ you can use self injection, and call the method on the self injected reference.
So for example:
#Component
public class SomeClass {
#Autowired
private SomeClass selfInjected;
public void someMethod() {
selfInjected.someOtherMethod();
}
#Async
public void someOtherMethod(){
...;
}
}
Updated as OP is using version before 4.3:
This will work for you.
#Component
public class SomeClass {
#Autowired
private ApplicationContext applicationContext;
private SomeClass selfInjected;
#PostConstruct
private void init() {
selfInjected = applicationContext.getBean(SomeClass.class);
}
}
Or
The other option is to extract the method to separate class and autowire it. I would personally explore this option before doing the above method.
public abstract class BaseLoaneeRepayment implements Repayment {
#Autowired
protected LoanRepository loanRepository;
#Transactional(propagation = Propagation.REQUIRES_NEW)
public final void repay(RepaymentInfo repaymentInfo) {
Loan loan = loanRepository.lockAndLoad(repaymentInfo.getLoan().id());
}
protected abstract void preCheck(final RepaymentInfo repaymentInfo);
protected abstract void updateLoanee(final RepaymentInfo repaymentInfo);
protected abstract void repayment(final RepaymentInfo repaymentInfo);
protected abstract void calcDifference(final RepaymentInfo repaymentInfo);
}
#Service("loaneeNormalRepayment")
public class NormalRepayment extends BaseLoaneeRepayment implements Repayment {
private static final CatLogger logger = CatLoggerFactory.getLogger(NormalRepayment.class);
#Override
public final void preCheck(RepaymentInfo repaymentInfo) {}
#Override
public final void updateLoanee(RepaymentInfo repaymentInfo) {}
#Override
public final void repayment(RepaymentInfo repaymentInfo) {}
#Override
public final void calcDifference(RepaymentInfo repaymentInfo) {}
}
in Junit,
#TransactionConfiguration(defaultRollback = true)
public class NormalRepaymentTest extends ServiceTest {
#Autowired
#Qualifier("normalRepayment2")
private NormalRepayment normalRepayment;
#Autowired
private LoanService loanService;
#Test
public void test() {
normalRepayment.repay(repaymentInfo);
}
}
This normalRepayment.repay(repaymentInfo); in NormalRepayment loanRepository is null. The autowire not work.
The behavior you see is related to proxies. In certain cases, for Spring managed beans, Spring will create a proxy for the target class. In this case, methods are marked as #Transactional, and Spring will create a proxy which implements transaction handling for your service. Depending on the proxy strategy, Spring may proxy by subclass, which means a subclass will override methods of the target class and implement various logic such as transaction handling in those methods. In this case, the dependencies will be injected in the proxy, not the target class.
Java, by design, does now allow overriding final methods, and because of this, the proxy subclass will not be able to override the final methods in your concrete class.
The calling code will, in this case, in fact call the non-proxied target methods, where dependencies are not injected and no transactional handling is present.
Solution: Remove the final modifier from the methods in your concrete class, which will allow Spring to properly proxy your service class.