0

Hello every body i'm developping an authentication service using spring security & mysql database and ia have this error when running my springboot app

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]

Here is my pom.xml

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.0.7.Final</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

and this is my SecurityConfig.java

    @EnableGlobalMethodSecurity(prePostEnabled = true)
    @EnableWebSecurity
    @EnableJpaRepositories(basePackageClasses = UsersRepository.class)
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private MyUserDetailsService myUserDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(myUserDetailsService)
                    .passwordEncoder(getPasswordEncoder());

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable();
        http.authorizeRequests()
                .antMatchers("**/admin/**").authenticated()
                .anyRequest().permitAll()
                .and()
                .formLogin().permitAll();
    }

    private PasswordEncoder getPasswordEncoder() {
        return new PasswordEncoder() {
            @Override
            public String encode(CharSequence charSequence) {
                return charSequence.toString();
            }

            @Override
            public boolean matches(CharSequence charSequence, String s) {
                return true;
            }
        };
    }
}

this is my Users.java

@Entity
@Table(name = "user")
public class Users {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "user_id")
    private int id;

    @Column(name = "login")
    private String login;

    @Column(name = "password")
    private String password;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Set<Role> roles;

    public Users() {
    }

    public Users(Users users){

        this.id=users.getId();
        this.login=users.getLogin();
        this.password=users.getPassword();
        this.roles=users.getRoles();
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Set<Role> getRoles() {
        return roles;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }
}

this is the roles.java

@Entity
@Table(name = "role")
public class Role {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "role_id")
    private int roleId;

    @Column(name = "role")
    private String role;

    public Role() {
    }

    public int getRoleId() {
        return roleId;
    }

    public void setRoleId(int roleId) {
        this.roleId = roleId;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }
}

this is my UsersRepository.java

@Repository
public interface UsersRepository extends JpaRepository<Users, Integer> {
    Optional<Users> findByName(String username);
}

this is MyUserDetailsService.java

@Service
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private UsersRepository usersRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Optional<Users> optionalUsers = usersRepository.findByName(username);

        optionalUsers
                .orElseThrow(() -> new UsernameNotFoundException("Utilisateur Introuvable!"));
        return optionalUsers
                .map(MyUserDetails::new).get();
    }
}

this is MyUserDetails.java

public class MyUserDetails extends Users implements UserDetails {


    public MyUserDetails(final Users users) {
        super(users);
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {

        return getRoles()
                .stream()
                .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getRole()))
                .collect(Collectors.toList());
    }

    @Override
    public String getPassword() {
        return super.getPassword();
    }

    @Override
    public String getUsername() {
        return super.getLogin();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

and finally my controller of ressources AuthenticationCOntroller.java

@RequestMapping("/api")
@RestController
public class AuthentificationController {


    @GetMapping(value = "/login")
    public String hello() {

        return "Hello World";
    }

    @PreAuthorize("hasAnyRole('ADMIN')")
    @GetMapping("/admin/login")
    public String helloAdmin() {
        return "Hello ADMIN";
    }

    @GetMapping("/login/alternate")
    public String alternate() {
        return "alternate";
    }

}

this is application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password =
spring.datasource.testWhileIdle=true
spring.datasource.validationQuery=SELECT 1
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

I'm using and MYSQL database it is well connected and the tables are created with some values.

Thank you and waiting for you answers.

Anil Nivargi
  • 1,473
  • 3
  • 27
  • 34
Fraxn
  • 23
  • 8
  • `spring-boot-starter-data-jpa` dependency already has hibernate-core included. Try to remove `hibernate-core` dependency first? – Chaffy Mar 31 '20 at 17:23

3 Answers3

0

There is a conflict in pom.xml dependencies:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

spring-boot-starter-jpa has hibernate-core dependency included.

It is possible to view the dependency graph of a project like so:

mvn dependency:tree
mvn dependency:list

These commands will show what version of Hibernate included in the compilation.

To fix the UnsatisfiedDependencyException of entityManagerFactory bean, simply delete hibernate-core dependency from the pom.xml

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>5.0.7.Final</version>
</dependency>
Chaffy
  • 182
  • 12
  • Unfortunately, i did that but didnt work, now i have a second error and it says, the jdbc time zone is not correct :/ – Fraxn Apr 01 '20 at 09:58
  • I am not entirely sure what is the new issue you are facing, however, it looks like removing the dependency of the Hibernate actually worked for the scenario above. As for the JDBC time zone, perhaps this answer might be of use to you? [MySQL JDBC Time Zone Unrecognized](https://stackoverflow.com/questions/26515700/mysql-jdbc-driver-5-1-33-time-zone-issue) – Chaffy Apr 02 '20 at 20:29
  • i have deleted the hibernate dependency and i have this problem right now : org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityConfig': Unsatisfied dependency expressed through field 'myUserDetailsService'; – Fraxn Apr 02 '20 at 20:39
  • Now you face an exception that happens because of the logic inside the project. You should check `securityConfig` bean as stated in the error you mentioned. – Chaffy Apr 02 '20 at 21:03
  • it tells me that there is a problem here UsersRepository.findByName(java.lang.String)! No property name found for type Users! – Fraxn Apr 02 '20 at 21:11
  • There is no field that named 'name' in `Users` entity. I assume you want to find the user by 'login' instead. Change the name of the method in `UserRepository` to `findByLogin(String login);` – Chaffy Apr 04 '20 at 06:18
0

if you are using java version 9+, add following too and remove hibernate core dependency as its already included in spring boot jpa starter.

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>
01000001
  • 833
  • 3
  • 8
  • 21
  • it changed the error look what it says now: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityConfig': Unsatisfied dependency expressed through field 'myUserDetailsService'; – Fraxn Apr 02 '20 at 20:40
0

Remove the Hibernate dependency because spring-boot-starter-data-jpa already has it.

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.0.7.Final</version>
</dependency>

Hope this works :)

Chamith Madusanka
  • 471
  • 2
  • 4
  • 11
  • thank you, it changed the error look what it says now: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityConfig': Unsatisfied dependency expressed through field 'myUserDetailsService'; – Fraxn Apr 02 '20 at 20:40
  • You have to put @Bean annotation on top of getPasswordEncoder method in security config class. `@Bean private PasswordEncoder getPasswordEncoder() { return new PasswordEncoder() { @Override public String encode(CharSequence charSequence) { return charSequence.toString(); } @Override public boolean matches(CharSequence charSequence, String s) { return true; } }; }` – Chamith Madusanka Apr 03 '20 at 03:55