У меня есть проект Maven, который представляет уровень данных сервера единого входа (SSO).Другие клиентские приложения должны использовать его для аутентификации и авторизации пользователя.
Это .jar
архив, который должен использоваться другим REST
проектом, также проектом Maven.
ОбаПроекты на основе Spring Boot 2.
Этот проект должен иметь некоторые интеграционные тесты с базами данных H2 и MySQL.
Поскольку это библиотека, она не запускается сама по себе.Но у него есть некоторые интеграционные тесты, которые должны быть выполнены.Поэтому класс main
отсутствует.
Команда, используемая для построения и выполнения тестов, mvn clean install -Denv="test"
Мое дерево исходного кода выглядит следующим образом:
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── com
│ │ └── thalasoft
│ │ └── userdata
│ │ ├── config
│ │ │ ├── DatabaseConfiguration.java
│ │ │ ├── JpaService.java
│ │ │ └── properties
│ │ │ ├── AbstractDatabaseProperties.java
│ │ │ ├── DatabaseH2TestProperties.java
│ │ │ ├── DatabaseMySQLAcceptanceProperties.java
│ │ │ ├── DatabaseMySQLPreProdProperties.java
│ │ │ ├── DatabaseMySQLProdProperties.java
│ │ │ ├── DatabaseMySQLTestProperties.java
│ │ │ ├── DatabaseOraclePreProdProperties.java
│ │ │ ├── DatabaseOracleProdProperties.java
│ │ │ ├── DatabaseOracleTestProperties.java
│ │ │ ├── DatabaseProperties.java
│ │ │ └── PropertyNames.java
│ │ ├── dialect
│ │ │ ├── CustomMySQL5InnoDBDialect.java
│ │ │ └── CustomOracle10gDialect.java
│ │ ├── exception
│ │ │ ├── CannotDeleteEntityException.java
│ │ │ ├── EnrichableException.java
│ │ │ ├── EntityAlreadyExistsException.java
│ │ │ ├── EntityNotFoundException.java
│ │ │ └── NoEntitiesFoundException.java
│ │ ├── jpa
│ │ │ ├── domain
│ │ │ │ ├── AbstractEntity.java
│ │ │ │ ├── EmailAddress.java
│ │ │ │ ├── User.java
│ │ │ │ └── UserRole.java
│ │ │ └── repository
│ │ │ ├── GenericRepositoryImpl.java
│ │ │ ├── GenericRepository.java
│ │ │ ├── UserRepositoryCustom.java
│ │ │ ├── UserRepositoryImpl.java
│ │ │ ├── UserRepository.java
│ │ │ ├── UserRoleRepositoryCustom.java
│ │ │ ├── UserRoleRepositoryImpl.java
│ │ │ └── UserRoleRepository.java
│ │ └── service
│ │ ├── UserRoleServiceImpl.java
│ │ ├── UserRoleService.java
│ │ ├── UserServiceImpl.java
│ │ └── UserService.java
│ └── resources
│ ├── application.properties
│ └── custom
│ └── typedef.hbm.xml
└── test
├── java
│ └── com
│ └── thalasoft
│ └── userdata
│ ├── assertion
│ │ └── UserAssert.java
│ ├── it
│ │ ├── jpa
│ │ │ ├── AbstractRepositoryTest.java
│ │ │ ├── UserRepositoryTest.java
│ │ │ └── UserRoleRepositoryTest.java
│ │ └── service
│ │ ├── AbstractServiceTest.java
│ │ └── UserServiceTest.java
│ └── ut
│ ├── AbstractRepositoryTest.java
│ └── UserRepositoryTest.java
└── resources
├── h2
│ └── data-source-test.properties
├── mysql
│ ├── clean-up-before-each-test.sql
│ └── data-source-test.properties
└── oracle
├── data-source-preprod.properties
└── data-source-test.properties
DatabaseH2TestProperties
загружается благодаря пользовательской аннотации, определенной в другом проекте панели инструментов Maven:
@EnvTest
@DbH2
@Configuration
@PropertySource({ "classpath:h2/data-source-test.properties" })
public class DatabaseH2TestProperties extends AbstractDatabaseProperties {
private static Logger logger = LoggerFactory.getLogger(DatabaseH2TestProperties.class);
public DatabaseH2TestProperties() {
logger.debug("===========>> Loading the classpath h2/data-source-test.properties file");
}
}
Файл data-source-test.properties
содержит:
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.datasource.driver-class-name=net.sf.log4jdbc.DriverSpy
spring.datasource.url=jdbc:log4jdbc:h2:file:./target/useraccounttest
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.show-sql=true
Все тесты основаныв классе:
@ContextConfiguration(classes = { DatabaseConfiguration.class })
@RunWith(SpringRunner.class)
@Sql(executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, scripts = { "classpath:mysql/clean-up-before-each-test.sql" })
public abstract class AbstractRepositoryTest {
}
В этом классе мне интересно, не стоит ли вместо этого использовать @SpringBootTest(classes = { DatabaseConfiguration.class })
.
И конфигурация выполняется с помощью:
@EnableAutoConfiguration
@ComponentScan(nameGenerator = PackageBeanNameGenerator.class, basePackages = { "com.thalasoft.userdata" })
public class DatabaseConfiguration {
}
Соединение с базой данных H2 установлено успешно:
02:23:56.299 [main] DEBUG jdbc.audit - 100. Connection.getMetaData() returned dbMeta74: conn99: url=jdbc:h2:file:./target/useraccounttest user=SA com.zaxxer.hikari.pool.ProxyConnection.getMetaData(ProxyConnection.java:361)
02:23:56.299 [main] DEBUG org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator - Database ->
name : H2
version : 1.4.197 (2018-03-18)
major : 1
minor : 4
02:23:56.299 [main] DEBUG org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator - Driver ->
name : H2 JDBC Driver
version : 1.4.197 (2018-03-18)
major : 1
minor : 4
02:23:56.299 [main] DEBUG org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator - JDBC version : 4.0
02:23:56.299 [main] INFO org.hibernate.dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
02:23:56.305 [main] DEBUG jdbc.audit - 100. Connection.clearWarnings() returned com.zaxxer.hikari.pool.ProxyConnection.close(ProxyConnection.java:250)
Но я получаю исключение.
Что говорит консольный журнал:
02:23:56.338 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
02:23:56.338 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Finished creating instance of bean 'com.thalasoft.userdata.config.JpaService'
02:23:56.338 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'com.thalasoft.userdata.config.properties.DatabaseH2TestProperties'
02:23:56.338 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'com.thalasoft.userdata.jpa.repository.GenericRepositoryImpl'
02:23:56.338 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating instance of bean 'com.thalasoft.userdata.jpa.repository.GenericRepositoryImpl'
02:23:56.338 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
02:23:56.340 [main] WARN org.springframework.context.support.GenericApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.thalasoft.userdata.jpa.repository.GenericRepositoryImpl' defined in file [/home/stephane/dev/java/projects/user-data/target/classes/com/thalasoft/userdata/jpa/repository/GenericRepositoryImpl.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.Class<?>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Действительно,У меня есть собственный универсальный репозиторий:
@Repository
@Transactional
public class GenericRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>
implements GenericRepository<T, ID> {
private EntityManager entityManager;
private final Class<T> domainClass;
public GenericRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
super(domainClass, entityManager);
this.entityManager = entityManager;
this.domainClass = domainClass;
}
public EntityManager getEntityManager() {
return entityManager;
}
}
@NoRepositoryBean
public interface GenericRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
public EntityManager getEntityManager();
}
И он используется как:
public interface UserRepository extends GenericRepository<User, Long>, UserRepositoryCustom {
}
public interface UserRepositoryCustom {
public User deleteByUserId(Long id) throws EntityNotFoundException;
}
public class UserRepositoryImpl implements UserRepositoryCustom {
@Autowired
private UserRepository userRepository;
}
Такое ощущение, что класс домена не может быть найден для универсального типа.