I have a task to rewrite some old logic stored in the database procedures in java, using JavaEE 7. The application is deployed on JBoss EAP 7.
There is a critical functionality, therefore we need to have some sort of a switcher, in order to be able to switch between old and new implementation of some services in production quickly.
Unfortunatelly we are not able to deliver and deploy new versions immediately, even in case of critical problems. So we need to introduce such switcher in form of a database table.
In order to provide good maintainability, I would like to use CDI to inject old/new implementations based on the switcher.
The simpliest way I see, is to utilize CDI Producers. Would it be the good solution to make a DB-Request in a Producer Method?
My Example:
@ApplicationScoped
public class NewServiceProducer {
@Inject
private ImplementationSwitcherDAO implementationSwitcherDAO;
@Produces
@RequestScoped
public NewService produceNewService(){
//a DB-Call is done here
boolean useOldVersion = implementationSwitcherDAO.isUseOldVersionForService("NewService");
if(useOldVersion){
return CDI.current().select(NewServiceOldImpl.class).get();
}
return CDI.current().select(NewServiceImpl.class).get();
}
}
I can't really comment on the "good practice" question, but you have a question in here that deserves an answer.
To do what you want, you need to do one, but not both, of the following:
NewServiceOldImpl.class
and NewServiceImpl.class
do not have NewService
in their set of bean typesNewServiceOldImpl.class
and NewServiceImpl.class
entirelyOtherwise, if you try to @Inject
a NewService
, there will be two possibilities, and, all else being equal, CDI will fail with some kind of AmbiguousResolutionException
.
I would implement your solution like this:
// Let's assume that NewServiceImpl is a regular managed bean
@RequestScoped
@Typed({ NewServiceImpl.class, Object.class }) // ...or whatever, but not NewService.class
public class NewServiceImpl { /*...*/ }
// Let's assume that NewServiceOldImpl is a regular managed bean
@RequestScoped
@Typed({ NewServiceOldImpl.class, Object.class }) // ...or whatever, but not NewService.class
public class NewServiceOldImpl { /*...*/ }
// Then somewhere else:
@Produces
@RequestScoped
private static NewService produceNewService(final NewServiceOldImpl oldImpl,
final NewServiceImpl newImpl) {
if (implementationSwitcherDAO.isUseOldVersionForService("NewService")) {
return oldImpl;
}
return newImpl;
}