我已在 AWS EC2 上部署了多租户 Spring 启动应用程序。该代码在本地系统中运行良好,但在 aws ec2 中运行 docker 后,应用程序失败并显示以下错误。
] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'orderReportListener' defined in URL [jar:file:/app-service.jar!/BOOT-INF/classes!/com/aic/autofluence/appservice/scheduler/kafkaReportListener/OrderReportListener.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'reportFactoryImplData' defined in URL [jar:file:/app-service.jar!/BOOT-INF/classes!/com/aic/autofluence/appservice/scheduler/service/Impl/ReportFactoryImplData.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'orderReportRepository' defined in com.aic.autofluence.appservice.scheduler.repository.OrderReportRepository defined in @EnableJpaRepositories declared on TenantDatabaseConfig: Cannot create inner bean '(inner bean)#4293e066' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#4293e066': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
2021-05-10 18:58:57.081 INFO 1 --- [ main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'masterdb-persistence-unit'
2021-05-10 18:58:57.082 INFO 1 --- [ main] com.zaxxer.hikari.HikariDataSource : masterdb-connection-pool - Shutdown initiated...
2021-05-10 18:58:57.099 INFO 1 --- [ main] com.zaxxer.hikari.HikariDataSource : masterdb-connection-pool - Shutdown completed.
2021-05-10 18:58:57.103 INFO 1 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2021-05-10 18:58:57.124 INFO 1 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-05-10 18:58:57.147 ERROR 1 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.aic.autofluence.appservice.scheduler.service.Impl.ReportFactoryImplData required a bean named 'entityManagerFactory' that could not be found.
我的示例代码如下:
tenantConfig:EntityManagerFactory bean 本身不被识别。它在本地系统中运行良好,在 vm 中失败
@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = { "x.x.x.x.scheduler.repository", "x.x.x.x.scheduler.model" })
@EnableJpaRepositories(basePackages = {"x.x.x.x..scheduler.repository", "x.x.x.x..scheduler.service"},
entityManagerFactoryRef = "tenantEntityManagerFactory",
transactionManagerRef = "tenantTransactionManager")
public class TenantDatabaseConfig {
@Bean(name = "tenantJpaVendorAdapter")
public JpaVendorAdapter jpaVendorAdapter() {
return new HibernateJpaVendorAdapter ();
}
@Bean(name = "tenantTransactionManager")
public JpaTransactionManager transactionManager(@Qualifier("tenantEntityManagerFactory") EntityManagerFactory tenantEntityManager) {
JpaTransactionManager transactionManager = new JpaTransactionManager ();
transactionManager.setEntityManagerFactory(tenantEntityManager);
return transactionManager;
}
@Bean(name = "datasourceBasedMultitenantConnectionProvider")
@ConditionalOnBean(name = "masterEntityManagerFactory")
public MultiTenantConnectionProvider multiTenantConnectionProvider() {
return new DataSourceBasedMultiTenantConnectionProviderImpl();
}
@Bean(name = "currentTenantIdentifierResolver")
public CurrentTenantIdentifierResolver currentTenantIdentifierResolver() {
return new CurrentTenantIdentifierResolverImpl();
}
@Bean(name = "tenantEntityManagerFactory")
@ConditionalOnBean(name = "datasourceBasedMultitenantConnectionProvider")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
@Qualifier("datasourceBasedMultitenantConnectionProvider")
MultiTenantConnectionProvider connectionProvider,
@Qualifier("currentTenantIdentifierResolver")
CurrentTenantIdentifierResolver tenantResolver) {
LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean ();
//All tenant related entities, repositories and service classes must be scanned
emfBean.setPackagesToScan("com.aic.autofluence.appservice");
emfBean.setJpaVendorAdapter(jpaVendorAdapter());
emfBean.setPersistenceUnitName("tenantdb-persistence-unit");
Map<String, Object> properties = new HashMap<>();
properties.put( Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE);
properties.put( Environment.MULTI_TENANT_CONNECTION_PROVIDER, connectionProvider);
properties.put( Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantResolver);
properties.put( Environment.DIALECT, "org.hibernate.dialect.MySQL5Dialect");
properties.put( Environment.SHOW_SQL, true);
properties.put( Environment.FORMAT_SQL, true);
properties.put( Environment.HBM2DDL_AUTO, "none");
emfBean.setJpaPropertyMap(properties);
return emfBean;
}
}
**MasterConfig: It is configured properly working fine**
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = {"x.x.x.x.mastertenant.model",
"x.x.x.x.mastertenant.repository"
},
entityManagerFactoryRef = "masterEntityManagerFactory",
transactionManagerRef = "masterTransactionManager")
public class MasterDatabaseConfig {
private static final Logger LOG = LoggerFactory.getLogger(MasterDatabaseConfig.class);
@Autowired
private MasterDatabaseConfigProperties masterDbProperties;
@Bean(name = "masterDataSource")
public DataSource masterDataSource() {
HikariDataSource hikariDataSource = new HikariDataSource ();
hikariDataSource.setUsername(masterDbProperties.getUsername());
hikariDataSource.setPassword(masterDbProperties.getPassword());
hikariDataSource.setJdbcUrl(masterDbProperties.getUrl());
hikariDataSource.setDriverClassName(masterDbProperties.getDriverClassName());
hikariDataSource.setPoolName(masterDbProperties.getPoolName());
// HikariCP settings
hikariDataSource.setMaximumPoolSize(masterDbProperties.getMaxPoolSize());
hikariDataSource.setMinimumIdle(masterDbProperties.getMinIdle());
hikariDataSource.setConnectionTimeout(masterDbProperties.getConnectionTimeout());
hikariDataSource.setIdleTimeout(masterDbProperties.getIdleTimeout());
LOG.info("Setup of masterDataSource succeeded.");
return hikariDataSource;
}
@Primary
@Bean(name = "masterEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean masterEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean ();
em.setDataSource(masterDataSource());
em.setPackagesToScan(new String[]{x,x,x,x...});
em.setPersistenceUnitName("masterdb-persistence-unit");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter ();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(hibernateProperties());
LOG.info("Setup of masterEntityManagerFactory succeeded.");
return em;
}
@Bean(name = "masterTransactionManager")
public JpaTransactionManager masterTransactionManager(@Qualifier("masterEntityManagerFactory") EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager ();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor ();
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put(org.hibernate.cfg.Environment.DIALECT, "org.hibernate.dialect.MySQL5Dialect");
properties.put(org.hibernate.cfg.Environment.SHOW_SQL, true);
properties.put(org.hibernate.cfg.Environment.FORMAT_SQL, true);
properties.put(org.hibernate.cfg.Environment.HBM2DDL_AUTO, "none");
return properties;
}
知道可能是什么问题吗?
谢谢
答案 0 :(得分:-1)
代码在本地系统中运行良好,但在 aws ec2 中运行 docker 后,应用程序失败并显示以下错误。
您能否确保已尝试 mvn clean package
并将最新的工件部署到 EC2?
从堆栈跟踪来看,缺少一个名称为:entityManagerFactory
的 bean。你需要用正确的名字来引用这个bean。
Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
Parameter 0 of constructor in com.aic.autofluence.appservice.scheduler.service.Impl.ReportFactoryImplData required a bean named 'entityManagerFactory' that could not be found.
在您的代码中,
@Primary
@Bean(name = "masterEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean masterEntityManagerFactory() {
// ...
@Bean(name = "tenantEntityManagerFactory")
@ConditionalOnBean(name = "datasourceBasedMultitenantConnectionProvider")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
// ...
多个 bean 具有相同的类型 LocalContainerEntityManagerFactoryBean
和不同的名称:masterEntityManagerFactory
和 tenantEntityManagerFactory
。
如果您希望通过类型而不是名称来引用bean,则不能这样做,因为您有多个类型的bean > LocalContainerEntityManagerFactoryBean
。要明确告诉 Spring 要注入哪个 bean,请根据您的定义指定 bean 名称。
根据您的堆栈跟踪,您在构造函数中通过名称 entityManagerFactory
引用了 bean。要解决此问题,您需要将参数名称从 entityManagerFactory
更改为 masterEntityManagerFactory
或 tenantEntityManagerFactory
。
另一种指定要注入的 bean 名称的方法是使用 @Qualifier("beanName")
。 Useful Guide
答案 1 :(得分:-1)
我已经通过删除 @ConditionalOnBean 注释解决了这个问题。感谢回复的人。