"LinkageError -> загрузчик 'app' попытался определить дубликат класса" после маркировки классов как @Transactional - PullRequest
0 голосов
/ 27 февраля 2019

После маркировки класса как @Transactional (см. Ниже), я получаю LinkageErrors о «попытке определить дубликат класса», когда мое приложение перезагружается, когда пользователь все еще вошел в систему.

Ошибка:

org.springframework.security.authentication.InternalAuthenticationServiceException: java.lang.LinkageError-->loader 'app' (instance of jdk.internal.loader.ClassLoaders$AppClassLoader) attempted duplicate class definition for [redacted].AdminUserDao$$FastClassBySpringCGLIB$$2ffa020e.
        at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:126)

Где adminUserDao - это дао, которое мы используем в нашем пользовательском UserDetailsService для загрузки пользователей во время аутентификации.

Original AdminUserDao.java

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class AdminUserDao {
    private final SessionFactory sessionFactory;

    @Autowired
    public AdminUserDao(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public AdminUser getUserByEmailAddress(String emailAddress) {
        String hql = "from " + AdminUser.class.getName()
                + " admin_user where admin_user.emailAddress = :emailAddress";
        Session session = null;
        try {
          session = sessionFactory.openSession();
          return session
                .createQuery(hql, AdminUser.class)
                .setParameter("emailAddress", emailAddress)
                .uniqueResult();
       } finally {
          if (session != null && session.isOpen()) {
            session.close();
          }
    }
}

Транзакционный AdminUserDao.java

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Transactional
@Repository
public class AdminUserDao {
    private final SessionFactory sessionFactory;

    @Autowired
    public AdminUserDao(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public AdminUser getUserByEmailAddress(String emailAddress) {
        String hql = "from " + AdminUser.class.getName()
                + " admin_user where admin_user.emailAddress = :emailAddress";
        return sessionFactory.getCurrentSession()
                .createQuery(hql, AdminUser.class)
                .setParameter("emailAddress", emailAddress)
                .uniqueResult();
    }
}

Бин менеджера транзакций

@Bean
public HibernateTransactionManager transactionManager(@Qualifier("sessionFactory") SessionFactory sessionFactory) {
    return new HibernateTransactionManager(sessionFactory);
}

Шаги для воспроизведения:

  1. Войти в систему
  2. Перезапустить приложение (без выхода из системы)
  3. Перезагрузить страницу (пользователь все еще должен войти в систему)
  4. Выйти
  5. Попытаться снова войти в систему с тем же пользователем.Ошибка запускается, когда Spring пытается аутентифицировать пользователя.

Я видел, как другие пользователи переполнения стека сталкивались с этой проблемой, когда они неправильно определяют собственный ClassLoader ( здесь );однако я не использую пользовательский ClassLoader.

Потенциально релевантные версии зависимостей:

  • Java: 11
  • Spring Boot: 2.1.1.RELEASE
  • Пружина: 5.1.3.RELEASE
  • Пружина Безопасность: 5.1.4.RELEASE
...