The power of the ContextResolver Part I
How to use a ContextResolver? What can you do with this?
Let´s say you have something like the following:
The implementation DemoLogicB is a normal JavaClass, KotlinDemoLogic is writen in Kotlin. Both implementations are paired with a qualifier and a producer like the following in the picture.
At this point you have n implementations with n qualiefiers and maybe n producer. Or it must be possible to extend the running system with a few more different customer dependent implementations. To write this inside your code with an big if else tree it is not a good style. From the busineslogic point of view the right definition is:
For this you can use the producer methods from cdi. The way is quite easy:
Now we have to implement the first class, called DemoContextResolver. The DemoContextResolver will be injected into every producer that must be able to decide something.
Let´s say you have something like the following:
@Inject @DemoLogicContext DemoLogic demologic;But it depends on the transient context of the application to decide what is the right implementation of the interface DemoLogic.
The implementation DemoLogicB is a normal JavaClass, KotlinDemoLogic is writen in Kotlin. Both implementations are paired with a qualifier and a producer like the following in the picture.
At this point you have n implementations with n qualiefiers and maybe n producer. Or it must be possible to extend the running system with a few more different customer dependent implementations. To write this inside your code with an big if else tree it is not a good style. From the busineslogic point of view the right definition is:
@Inject @DemoLogicContext DemoLogic demologic;
For this you can use the producer methods from cdi. The way is quite easy:
@Produces @DemoLogicContext
public DemoLogic create(){...}
With this you have the entry-point for the final injection point. You can extend the signature of the create method with more attributes. Mostly used is the BeanManager and/or InjectioPoint, but you can use your own classes. For example the ContextResolver.
@Produces @DemoLogicContext
public DemoLogic create(ContextResolver contextResolver){...}
The ContextResolver itself is an interface.. this means you have to use an qualifier to define the producer or implementing class for this interface.
@Produces @DemoLogicContext
public DemoLogic create(@DemoLogicContext ContextResolver contextResolver){...}
Now we have to implement the first class, called DemoContextResolver. The DemoContextResolver will be injected into every producer that must be able to decide something.
public class DemoLogicProducer {
private @Inject ManagedInstanceCreator creator;
@Produces @DemoLogicContext
public DemoLogic create(@New DemoContextResolver contextResolver){
final Class beanType = DemoLogic.class;
final AnnotationLiteral annotationLiteral = contextResolver.resolveContext(beanType);
final DemoLogic demoLogic = creator.getManagedInstance(beanType, annotationLiteral);
return demoLogic;
}
}
From this point you are able to decide what will be the implementation to use. For this example I wrote a very simple
version, but you can extend this to a tree of deciding ContextResolvers.
public class DemoContextResolver implements ContextResolver {
@Inject DemoContext demoContext;
@Override public AnnotationLiteral resolveContext(Class targetClass) {
if(demoContext.getContextInfo()){
return new AnnotationLiteral() {};
} else{
return new AnnotationLiteral() {};
}
}
}
The good thing is, that every module will be usable for itself. You can write jUnit-Tests per implementation. At runtime you can add more implementations.
Think about the possibility to change the controller for a GUI in this way ;-)
I will show this more in detail in my next blog entry (Part II)



Kommentare
Kommentar veröffentlichen