Является ли хорошей практикой в ​​Java EE и CDI выбор реализации для внедрения на основе значения конфигурации, хранящегося в базе данных? - PullRequest
0 голосов
/ 01 апреля 2020

У меня есть задача переписать некоторые старые логи c, хранящиеся в процедурах базы данных в java, с использованием JavaEE 7. Приложение развернуто на JBoss EAP 7.

Существует критическая функциональность, поэтому нам нужен какой-то переключатель, чтобы быстро переключаться между старой и новой реализацией некоторых служб в работе.

К сожалению, мы не можем сразу же доставлять и развертывать новые версии, даже в случае критических проблем. Поэтому нам нужно ввести такой переключатель в виде таблицы базы данных.

Чтобы обеспечить удобство сопровождения, я хотел бы использовать CDI для внедрения старых / новых реализаций на основе переключателя.

Самый простой способ, который я вижу, - использовать CDI Producers. Было бы хорошим решением сделать запрос DB в методе источника?

Мой пример:

@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();
    }
}

1 Ответ

0 голосов
/ 01 апреля 2020

Я не могу комментировать вопрос «хорошей практики», но у вас есть вопрос, который заслуживает ответа.

Чтобы сделать то, что вы хотите, вам нужно сделать один, но не оба из следующего:

  1. Убедитесь, что NewServiceOldImpl.class и NewServiceImpl.class делают не имеют NewService в своем наборе типов бинов
  2. Вето NewServiceOldImpl.class и NewServiceImpl.class полностью

В противном случае, если вы попытаетесь @Inject a NewService, будет две возможности и, при прочих равных условиях, CDI потерпит неудачу с каким-то AmbiguousResolutionException.

Я бы реализовал ваше решение так:

// 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;
}
...