Примечание: это не дублированный вопрос.Прочитайте весь пост;)
Чтобы предотвратить проблему XY, вот полная история:
Мне нужно написать слушатель ревизии Envers, чтобы вычислить и сохранить различие последнего изменения сущности в приложении Spring:
public class MyRevisionListener implements EntityTrackingRevisionListener {
@Override
public void newRevision(Object revision) {
...
}
@Override
public void entityChanged(Class entityClass,
String entityName,
Serializable entityId,
RevisionType revisionType,
Object revisionEntity) {
EntityManager em = EntityManagerBeanLookup.getInstance().get();
int id = ((DefaultRevisionEntity) revisionEntity).getId();
List<?> revisions = AuditReaderFactory.get(em)
.createQuery()
.forRevisionsOfEntity(entityClass, false, true)
.add(AuditEntity.id().eq(entityId))
.add(AuditEntity.revisionNumber().le(id + 1))
.addOrder(AuditEntity.revisionNumber().desc())
.setMaxResults(2)
.getResultList();
checkArgument(revisions.size() > 0, "Need at least one revision: %s", revisions);
// continue with calculating and persisting the diff;
}
}
и для получения EntityManager
бина у меня есть утилита / бин EntityManagerBeanLookup
:
@Component
public class EntityManagerBeanLookup implements Supplier<EntityManager> {
@Getter
private static EntityManagerBeanLookup instance;
@Getter
private EntityManager entityManager;
@PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
@Autowired
public void setInstance(EntityManagerBeanLookup instance) {
EntityManagerBeanLookup.instance = instance;
}
@Override
public EntityManager get() {
return ofNullable(getInstance())
.map(EntityManagerBeanLookup::getEntityManager)
.orElseThrow(() -> new IllegalStateException("Not initialized yet"));
}
}
Все работает просто отлично.Проблема в том, что у нас есть интеграционные тесты с использованием среды Spring Test.В зависимости от того, как Spring создает тестовые контексты и кэширует bean-компоненты, возможно, что класс поиска bean-компонентов возвращает менеджер сущностей из другого контекста, а не из текущего контекста.Это происходит в нашем случае, когда проходной тест не пройден, если вы запускаете его среди других тестов (подробнее здесь ).
Теперь вопросы:
1. Есть ли способ определить MyRevisionListener
как bean-компонент Spring, чтобы я мог аккуратно внедрить контекст постоянства?
2. Если вышеприведенное является НЕТ, то как мне правильно получить контекст постоянства в статическом контексте / методе?
Спасибо.