This is the definition for the databases in the application.properties file: First Database:
spring.datasource.jdbc-url=jdbc:mysql://localhost:3306/police_db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=Admin
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
Second database configuration:
enroll.datasource.jdbc-url=jdbc:mysql://localhost:3306/enrollment_db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
enroll.datasource.username=root
enroll.datasource.password=Admin
enroll.datasource.driverClassName=com.mysql.cj.jdbc.Driver
I created two configuration classes for the two databases, this is the configuration class for the first or primary database:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactory",
basePackages = {"com.cpm.repository"})
public class PoliceDbConfig {
@Primary
@Bean(name = "dataSource")
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder builder, @Qualifier("dataSource") DataSource dataSource) {
return builder.dataSource(dataSource).packages("com.cpm.model").persistenceUnit("model")
.build();
}
@Primary
@Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("entityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
This is the configuration class for the second database:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "barEntityManagerFactory",
transactionManagerRef = "barTransactionManager", basePackages = {"com.enrollment.repository"})
public class EnrollmentDbConfig {
@Bean(name = "enrollmentDatasource")
@ConfigurationProperties(prefix = "enroll.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "barEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean barEntityManagerFactory(
EntityManagerFactoryBuilder builder, @Qualifier("enrollmentDatasource") DataSource dataSource) {
return builder.dataSource(dataSource).
packages("com.enrollment.model").
persistenceUnit("model")
.build();
}
@Bean(name = "barTransactionManager")
public PlatformTransactionManager barTransactionManager(
@Qualifier("barEntityManagerFactory") EntityManagerFactory barEntityManagerFactory) {
return new JpaTransactionManager(barEntityManagerFactory);
}
}
The major problem i am having is the tables for the entities are not automatically generated, i did a web search for the problem and i was told to add this annotations:
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create
The first annotation creates the tables but if i remove it and leave just the second annotation which is what i need, the tables do not get created.
Another issue is I have an sql script in the resources folder which is supposed to run and populate the tables when the application is started, but it does not do so.
The final issue is, I have basic authentication set up using spring security, but I still get unauthorized when I test any of my endpoints, so I guess that's because the users table is not populated when the application is started, so I then added the users via MYSQL workbench manually and tried the endpoint, but it still results in unauthorized error.
Any help on these issues would be very much appreciated. UPDATE: This is the security configuration class:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final SystemUserDetailService userDetailsService;
@Autowired
public SecurityConfig(SystemUserDetailService userDetailsService) {
this.userDetailsService = userDetailsService;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
//.antMatchers("/verification/**","/admin/**", "/login/**","/logout/**").authenticated()
.antMatchers("/verification/**","/admin/**", "/login/**","/logout/**").authenticated()
.and()
.httpBasic()
.realmName("Bio Connect")
.and()
.csrf()
.disable();
}
}
Also, this is my UserDetailService Class:
@Component
public class SystemUserDetailService implements UserDetailsService {
private final SystemUserRepository repository;
@Autowired
public SystemUserDetailService(SystemUserRepository repository) {
this.repository = repository;
}
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
SystemUser user = repository.findByUsername(s);
if(user == null) {
throw new UsernameNotFoundException(String.format("User with the username %s doesn't exist", s));
}
// Create a granted authority based on user's role.
// Can't pass null authorities to user. Hence initialize with an empty arraylist
List<GrantedAuthority> authorities = new ArrayList<>();
if(user.isAdmin()) {
authorities = AuthorityUtils.createAuthorityList("ROLE_ADMIN");
}
// Create a UserDetails object from the data
UserDetails userDetails = new User(user.getUsername(), user.getPassword(), authorities);
return userDetails;
}
}