Is it possible to implement strategy pattern with enum in Spring - java

I am trying to implement a strategy pattern with Enum, but I need Service to handle each of my task. I tried to #Autowired a service into Enum but it doesn't work.
I have searched a bit for "How to inject bean into enum" and there comes an answer(but it looks not elegant for me ).
I am now hesitate to continue because I don't know if this is a good way to go. Do we have batter design for this kind of requirement?
public enum TaskType {
CREATE_MATERIAL{
#Override
public void handleTask(ScheduledEvent scheduledEvent) {
service.createMaterial(scheduledEvent);
}
};
#Autowired
private static AService service;
public abstract void handleTask(ScheduledEvent scheduledEvent);
}

You can't autowire an enum, since enums are constants created by the Java runtime, and cannot as such be Spring-managed beans.
You need to pass in any required values as parameters to the method.
public enum TaskType {
CREATE_MATERIAL{
#Override
public void handleTask(AService service, ScheduledEvent scheduledEvent) {
service.createMaterial(scheduledEvent);
}
};
public abstract void handleTask(AService service, ScheduledEvent scheduledEvent);
}
If the different strategies need to call different services, stop using enum.
public interface TaskType {
public abstract void handleTask(AService service, ScheduledEvent scheduledEvent);
}
#Component
public class CreateMaterial implements TaskType {
#Autowired
private static AService service;
#Override
public void handleTask(ScheduledEvent scheduledEvent) {
service.createMaterial(scheduledEvent);
}
};

Related

Changing the Spring beans implementation at runtime

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

Java: using inheritance if only constructor differs

I need to implement the same sequence of commands in a service, but operating on several different database objects, depending on a case. I'm wondering whether it is a good practice to use an inheritance in such case - which would consist in passing a different dao in a specifc class's constructor only. Something like this:
public abstract class Service{
private Dao dao;
public Service(Dao dao){
this.dao = dao;
}
public void mainMethod(){
dao.step1();
subMethod();
dao.step2();
}
public void subMethod(){
//...
}
}
public class ServiceImpl1 extends Service{
public ServiceImpl1(DaoImpl1 daoImpl1){
super(daoImpl1);
}
}
Inheritance is useful for delegating messages (method calls) to the superclass with few changes. You're not delegating messages to the parent class though, you're changing the parameter of the constructor. So there is no need to inherit anything.
This is fine:
public class Service{
private Dao dao;
public Service(Dao dao){
this.dao = dao;
}
public void mainMethod(){
dao.step1();
subMethod();
dao.step2();
}
public void subMethod(){
//...
}
}
You can then make instances like
Service posgresService = new Service(new PosgresDao());
Service redisService = new Service(new RedisDao());
See depenency injection for more details
I think that if -sequence of commands- refers to the exact same commands, I think you should create overloaded methods such as: if not, inheritance would be a good choice in order to keep orden in the code.
Since you are talking about inheritance and from the sample code provide, it seems like there will be one ServiceImpl class for each DaoImpl class. It will work, however you could also settle with a single ServiceImpl class for all Dao classes:
public class ServiceImpl implements Service {
public void mainMethod(Dao dao) {
dao.step1();
subMethod();
dao.step2();
}
public void subMethod() {
// ...
}
}
elsewhere
Service service = new ServiceImpl();
// ...
Dao dao1 = new DaoImpl1();
Dao dao2 = new DaoImpl2();
// ...
service.mainMethod(dao1);
service.mainMethod(dao2);

How to use a dynamic implementation of an interface in Spring?

This question is intended to make an answer for a useful issue.
Suppose we have a Spring application with a #Controller, an interface and different implementations of that interface.
We want that the #Controller use the interface with the proper implementation, based on the request that we receive.
Here is the #Controller:
#Controller
public class SampleController {
#RequestMapping(path = "/path/{service}", method = RequestMethod.GET)
public void method(#PathVariable("service") String service){
// here we have to use the right implementation of the interface
}
}
Here is the interface:
public interface SampleInterface {
public void sampleMethod(); // a sample method
}
Here is one of the possibile implementation:
public class SampleInterfaceImpl implements SampleInterface {
public void sampleMethod() {
// ...
}
}
And here is another one:
Here is one of the possibile implementation:
public class SampleInterfaceOtherImpl implements SampleInterface {
public void sampleMethod() {
// ...
}
}
Below I'll show the solution that I've found to use one of the implementations dynamically based on the request.
The solution I've found is this one.
First, we have to autowire the ApplicationContext in the #Controller.
#Autowired
private ApplicationContext appContext;
Second, we have to use the #Service annotation in the implementations of the interface.
In the example, I give them the names "Basic" and "Other".
#Service("Basic")
public class SampleInterfaceImpl implements SampleInterface {
public void sampleMethod() {
// ...
}
}
#Service("Other")
public class SampleInterfaceOtherImpl implements SampleInterface {
public void sampleMethod() {
// ...
}
}
Next, we have to obtain the implementation in the #Controller.
Here's one possible way:
#Controller
public class SampleController {
#Autowired
private ApplicationContext appContext;
#RequestMapping(path = "/path/{service}", method = RequestMethod.GET)
public void method(#PathVariable("service") String service){
SampleInterface sample = appContext.getBean(service, SampleInterface.class);
sample.sampleMethod();
}
}
In this way, Spring injects the right bean in a dynamic context, so the interface is resolved with the properly inmplementation.
I solved that problem like this:
Let the interface implement a method supports(...) and inject a List<SampleInterface> into your controller.
create a method getCurrentImpl(...) in the controller to resolve it with the help of supports
since Spring 4 the autowired list will be ordered if you implement the Ordered interface or use the annotation #Order.
This way you have no need for using the ApplicationContext explicitly.
Honestly I don't think the idea of exposing internal implementation details in the URL just to avoid writing some lines of code is good.
The solution proposed by #kriger at least adds one indirection step using a key / value approach.
I would prefer to create a Factory Bean (to be even more enterprise oriented even an Abstract Factory Pattern) that will choose which concrete implementation to use.
In this way you will be able to choose the interface in a separate place (the factory method) using any custom logic you wish.
And you will be able to decouple the service URL from the concrete implementation (which is not very safe).
If you are creating a very simple service your solution will work, but in an enterprise environment the use of patterns is vital to ensure maintenability and scalability.
I'm not convinced with your solution because there's an implicit link between an HTTP parameter value and a bean qualifier. Innocent change of the bean name would result in a disaster that could be tricky to debug. I would encapsulate all the necessary information in one place to ensure any changes only need to be done in a single bean:
#Controller
public class SampleController {
#Autowired
private SampleInterfaceImpl basic;
#Autowired
private SampleInterfaceOtherImpl other;
Map<String, SampleInterface> services;
#PostConstruct
void init() {
services = new HashMap()<>;
services.put("Basic", basic);
services.put("Other", other);
}
#RequestMapping(path = "/path/{service}", method = RequestMethod.GET)
public void method(#PathVariable("service") String service){
SampleInterface sample = services.get(service);
// remember to handle the case where there's no corresponding service
sample.sampleMethod();
}
}
Also, dependency on the ApplicationContext object will make it more complicated to test.
NB. to make it more robust I'd use enums instead of the "Basic" and "Other" strings.
However, if you know you'll only have two types of the service to choose from, this would be the "keep it simple stupid" way:
#Controller
public class SampleController {
#Autowired
private SampleInterfaceImpl basic;
#Autowired
private SampleInterfaceOtherImpl other;
#RequestMapping(path = "/path/Basic", method = RequestMethod.GET)
public void basic() {
basic.sampleMethod();
}
#RequestMapping(path = "/path/Other", method = RequestMethod.GET)
public void other() {
other.sampleMethod();
}
}

Spring can't Autowired abstract class with final 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.

Injecting dependent bean

I have a class
EntiyFacadeImpl.java
#Stateless
public class EntityFacadeImpl implements EntityFacade {
#EJB
ICustomerBean customerBean;
public void printCustomer(Customer c) {
customerBean.printCustomer(c);
customerBean.additionalFieldsHandler(c.getAdditionalFields().toString());
}
}
Where ICustomerBean is #Local interface and have two implementation classes CustomerBean.java and CustomerBeanExt.java where later one extends CustomerBean.java
#Stateless(name = "CustomerBean")
public class CustomerBean implements ICustomerBean {
public void printCustomer(Customer customer) {
System.out.println(customer);
}
public void additionalFieldsHandler(String additionalFields) {
// an empty implemetation here
}
}
#Stateless(name = "CustomerExtBean")
public class CustomerExtBean extends CustomerBean implements ICustomerBean {
#Override
public void additionalFieldsHandler(String additionalFields) {
// some custom implemetation
System.out.println("Additional Fields: "+additionalFields);
}
}
ICustomer interface looks like this
#Local
public interface ICustomerBean {
public void printCustomer(Customer c);
public void additionalFieldsHandler(String additionalFields);
}
My aim is that whenever I inject my EntityFacade (interface for EntityFacadeImpl) in SimpleRESTPojo.java only, I want CustomerExtBean to be inject in it, while when any other class injects it I want CustomerBean to be injected
#Path("/pojo")
public class SimpleRESTPojo {
#EJB
private EntityFacade entityFacade;
}
My app's entry point is EntityFacade only. Is there a way to achieve this?
Actually, after reading your question, it looks like you're trying to introduce tight coupling. CDI doesn't make EntityFacade aware of where it was injected in to. I don't see a way to do this.
What you could do is create an extended version of EntityFacade that used this injection point:
#Inject
#Extended //or whatever qualifier you come up with
private ICustomerBean customerBean;
and then use that same qualifier on the extended EntityFacade.

Categories