-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
Hi team,
I have some issue when using AbstractRoutingDataSource
for custom datasource
:
This is my error: Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jwtAuthenticationFilter' defined in file [JwtAuthenticationFilter.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'authenticationService' defined in file [AuthenticationService.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'userRepositoryInterface' defined in com.tkg.MasterSystem.repositories.UserRepositoryInterface defined in @EnableJpaRepositories declared on DatasourceRoutingConfiguration: Cannot resolve reference to bean 'jpaSharedEM_entityManager' while setting bean property 'entityManager'
This is my config:
@Service
@RequiredArgsConstructor
public class AuthenticationService implements AuthenticationServiceInterface {
@Autowired
Environment environment;
@Value("${JWT_SECRET_KEY}")
private String jwtSecret;
private final UserRepositoryInterface userRepository;
public class ClientDataSourceRouter extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return ClientDatabaseContextHolder.getClientDatabase();
}
public void initDataSource(DataSource companyA, DataSource companyB){
Map<Object, Object> datasourceMap = new HashMap<>();
datasourceMap.put(ClientDatabase.COMPANY_A, companyA);
datasourceMap.put(ClientDatabase.COMPANY_B, companyB);
this.setTargetDataSources(datasourceMap);
this.setDefaultTargetDataSource(companyA);
}
}
public class ClientDatabaseContextHolder {
private static ThreadLocal<ClientDatabase> threadLocal = new ThreadLocal<>();
public static void set(ClientDatabase clientDatabase){
threadLocal.set(clientDatabase);
}
public static ClientDatabase getClientDatabase(){
return threadLocal.get();
}
public static void clear(){
threadLocal.remove();
}
}
@Component
public class DataSourceInterceptor extends WebRequestHandlerInterceptorAdapter{
public DataSourceInterceptor(WebRequestInterceptor requestInterceptor) {
super(requestInterceptor);
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String company = request.getHeader("company");
if (ClientDatabase.COMPANY_A.toString().equals(company)){
ClientDatabaseContextHolder.set(ClientDatabase.COMPANY_A);
} else if(ClientDatabase.COMPANY_B.toString().equals(company)){
ClientDatabaseContextHolder.set(ClientDatabase.COMPANY_B);
} else {
ClientDatabaseContextHolder.set(ClientDatabase.COMPANY_A);
}
return super.preHandle(request, response, handler);
}
}
Configuration
@EnableJpaRepositories(basePackages = "com.tkg.MasterSystem.repositories", transactionManagerRef = "transcationManager", entityManagerFactoryRef = "entityManager")
@EnableTransactionManagement
public class DatasourceRoutingConfiguration {
@Bean
@Primary
@Autowired
public DataSource dataSource() {
ClientDataSourceRouter clientDataSourceRouter = new ClientDataSourceRouter();
clientDataSourceRouter.initDataSource(companyADatasource(), companyBDatasource());
return clientDataSourceRouter;
}
@Bean
@ConfigurationProperties(prefix = "twt.datasource")
public DataSource companyADatasource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "tkg.datasource")
public DataSource companyBDatasource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "entityManager")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(EntityManagerFactoryBuilder builder) {
return builder.dataSource(dataSource()).packages(User.class).build();
}
@Bean(name = "transcationManager")
public JpaTransactionManager transactionManager(
@Autowired @Qualifier("entityManager") LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
return new JpaTransactionManager(Objects.requireNonNull(entityManagerFactoryBean.getObject()));
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
DataSourceInterceptor dataSourceInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(dataSourceInterceptor).addPathPatterns("/**");
WebMvcConfigurer.super.addInterceptors(registry);
}
}
@Entity(name = "users")
@Table(name = "users")
@Data
public class User implements UserDetails {
public User() {}
public User(String title, String firstName, String lastName, String middleName, String email, String password, LocalDate dob, String avatarUrl, Boolean status, String countryCode, String phoneNumber, String authenticationCode, LocalDateTime sendAuthenticationCodeAt, Long createdBy) {
this.title = title;
this.firstName = firstName;
this.lastName = lastName;
this.middleName = middleName;
this.email = email;
this.password = password;
this.dob = dob;
this.avatarUrl = avatarUrl;
this.status = status;
this.countryCode = countryCode;
this.phoneNumber = phoneNumber;
this.authenticationCode = authenticationCode;
this.sendAuthenticationCodeAt = sendAuthenticationCodeAt;
this.createdBy = createdBy;
}
public User(StoreUserRequest request){
this.title = request.getTitle();
this.firstName = request.getFirstName();
this.lastName = request.getLastName();
this.middleName = request.getMiddleName();
this.dob = request.getDob();
this.position = request.getPosition();
this.department = request.getDepartment();
this.email = request.getEmail();
this.countryCode = request.getCountryCode();
this.phoneNumber = request.getPhoneNumber();
this.avatarUrl = request.getAvatarUrl();
this.createdAt = LocalDateTime.now();
this.updatedAt = LocalDateTime.now();
this.createdBy = Helper.getAuthUser().getId();
}
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String title;
private String firstName;
private String lastName;
private String middleName;
private String email;
private String password;
private LocalDate dob;
private String position;
private String department;
private String avatarUrl;
private Boolean status;
private String countryCode;
private String phoneNumber;
private String authenticationCode;
private LocalDateTime sendAuthenticationCodeAt;
private int numberLoginFailed;
private String forgotPasswordToken;
private Long createdBy;
private LocalDateTime createdAt = LocalDateTime.now();
private LocalDateTime updatedAt;
private Long deletedBy;
private LocalDateTime deletedAt;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return email;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return status;
}
@Getter(AccessLevel.NONE)
@OneToMany(mappedBy = "userCreate")
private List<Permission> permissions;
@Getter(AccessLevel.NONE)
@OneToMany(mappedBy = "userCreate")
private List<Role> roles;
}
@Repository
public interface UserRepositoryInterface extends JpaRepository<User, Long> {
boolean existsByEmail(String email);
Optional<User> findByEmail(String email);
Optional<User> findByForgotPasswordToken(String token);
}