Forgot password implementation spring security

I’m trying to implement “Forgot password” field using spring security. But there is an error that I tried to solve, but could not find the solution. I got to know that JpaRepository does some batch processing and CRUD operations. My user.java model class has all fields (….email,resetToken).

UserRepositoryDao:

@Repository("userRepository")
public interface UserRepositoryForgetPassword extends JpaRepository<User, Long>{

     Optional<User> findByEmail(String email);
     Optional<User> findByResetToken(String resetToken);

}

UserServiceForgotPassword:

public interface UserServiceForgetPassword {

    public Optional<User> findUserByEmail(String email);

    public Optional<User> findUserByResetToken(String resetToken);

    public void save(User user);
}

UserServiceForgotPasswordImpl:

@Service("userServiceForgetPassword")
public class UserServiceForgetPasswordImpl implements UserServiceForgetPassword {

    @Autowired
    UserRepositoryForgetPassword userRepositoryForgetPassword;

    @Override
    @Transactional
    public Optional<User> findUserByEmail(String email) {
        return userRepositoryForgetPassword.findByEmail(email);
    }

    @Override
    @Transactional
    public Optional<User> findUserByResetToken(String resetToken) {
        return userRepositoryForgetPassword.findByResetToken(resetToken);
    }

    @Override
    @Transactional
    public void save(User user) {
        userRepositoryForgetPassword.save(user);
    }
}

Error:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'fogetPasswordController': Unsatisfied dependency expressed through field 'userServiceForgetPassword'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userServiceForgetPassword': Unsatisfied dependency expressed through field 'userRepositoryForgetPassword'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.pulseBeatMaster.dao.UserRepositoryForgetPassword' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Controller:

    @RestController
    public class FogetPasswordController {

        @Autowired
        UserServiceForgetPassword userServiceForgetPassword;

        @Autowired
        EmailServiceForgetPassword emailServiceForgetPassword;

        @Autowired
        private BCryptPasswordEncoder bCryptPasswordEncoder;


        //Do the stuffs

}

I hope there is an error with extending JpaRepository.

EDITED

@Configuration
@PropertySource(value = { "classpath:application.properties" })
public class ApplicationContextConfig {

    // To get properties from application.properties
    // Import @PropertySource(value = { "classpath:application.properties" })
    // Have to use environment.getRequiredProperty();

    @Autowired
    private Environment environment;

    @Bean(name = "dataSource")
    public DataSource getDataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
        dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
        dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
        dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));

        // normally
        // dataSource.setDriverClassName("com.mysql.jdbc.Driver");

        return dataSource;
    }

    private Properties getHibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
        properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
        properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
        properties.put("hibernate.id.new_generator_mappings",
                environment.getRequiredProperty("hibernate.new_generator_mappings"));
        properties.put("current_session_context_class", "org.springframework.orm.hibernate5.SpringSessionContext");
        return properties;
    }

    @Autowired
    @Bean(name = "sessionFactory")
    public SessionFactory getSessionFactory(DataSource dataSource) {
        LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
        sessionBuilder.addProperties(getHibernateProperties());
        sessionBuilder.addAnnotatedClasses(Employee.class);
        sessionBuilder.addAnnotatedClasses(Department.class);
        sessionBuilder.addAnnotatedClasses(Company.class);
        sessionBuilder.addAnnotatedClasses(User.class);
        sessionBuilder.addAnnotatedClasses(UserProfile.class);
        sessionBuilder.addAnnotatedClasses(UserProfileType.class);
        sessionBuilder.addAnnotatedClasses(PersistentLogin.class);
        sessionBuilder.addAnnotatedClasses(GaugeCategory.class);
        sessionBuilder.addAnnotatedClasses(Survey.class);
        sessionBuilder.addAnnotatedClasses(PreferredUrl.class);
        sessionBuilder.addAnnotatedClasses(Gauge.class);
        sessionBuilder.addAnnotatedClasses(GaugeFeedback.class);
        sessionBuilder.addAnnotatedClasses(Customer.class);
        sessionBuilder.addAnnotatedClasses(Phone.class);
        return sessionBuilder.buildSessionFactory();
    }

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(getDataSource());
        sessionFactory.setPackagesToScan(new String[] { "com.pulseBeatMaster.model" });
        sessionFactory.setHibernateProperties(getHibernateProperties());
        return sessionFactory;
    }

    @Autowired
    @Bean(name = "transactionManager")
    public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);
        return transactionManager;
    }

    @Bean
    public JavaMailSender getMailSender() {
        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();

        // Using gmail
        mailSender.setHost(environment.getRequiredProperty("mailSender.host"));
        mailSender.setPort(587);
        mailSender.setUsername(environment.getRequiredProperty("mailSender.username"));
        mailSender.setPassword(environment.getRequiredProperty("mailSender.password"));

        Properties javaMailProperties = new Properties();
        javaMailProperties.put("mail.smtp.starttls.enable", "true");

        javaMailProperties.put("mail.smtp.auth", "true");
        javaMailProperties.put("mail.transport.protocol", "smtp");
        javaMailProperties.put("mail.debug", "true");// Prints out everything on
                                                        // screen

        mailSender.setJavaMailProperties(javaMailProperties);
        return mailSender;
    }

}

You need to use a @Repository on your UserRepositoryForgetPassword interface. and add @EnableJpaRepositories(basePackages = {“com.demo.test.repository”}) in your ApplicationContaxt.xml file configuration to scan repository classes and also use <context:component-scan annotation-config=”true” base-package=”com.demo.test” /> in your ApplicationContaxt.xml file to scan base package and classes annotations.

You need

  • Enable Spring Data JPA by annotating the ApplicationContextConfig class with the @EnableJpaRepositories annotation.
  • Configure the base packages that are scanned when Spring Data JPA creates implementations for our repository interfaces.

So add please in your configuration file (ApplicationContextConfig):

@EnableJpaRepositories(basePackages = {"com.pulseBeatMaster.dao"})

Please check below configuration class. As suggested by M. Denium you dont have to directly work with SessionFactory. JPA works on notion of EntityManager. I have made necessary changes to make it work through java configuration. You can do most of this config using application.properties if you are using spring-boot.

    @Configuration
    @PropertySource(value = { "classpath:application.properties" })
    @EnableJpaRepositories(basePackages = "com.pulseBeatMaster.dao", entityManagerFactoryRef = "myEntityManagerFactory", transactionManagerRef = "myTransactionManager")
    public class ApplicationContextConfig {

        // To get properties from application.properties
        // Import @PropertySource(value = { "classpath:application.properties" })
        // Have to use environment.getRequiredProperty();

        @Autowired
        private Environment environment;

        @Bean(name = "dataSource")
        public DataSource getDataSource() {
            BasicDataSource dataSource = new BasicDataSource();
            dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
            dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
            dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
            dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));

            // normally
            // dataSource.setDriverClassName("com.mysql.jdbc.Driver");

            return dataSource;
        }

        private Properties getHibernateProperties() {
            Properties properties = new Properties();
            properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
            properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
            properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
            properties.put("hibernate.id.new_generator_mappings",
                    environment.getRequiredProperty("hibernate.new_generator_mappings"));
            properties.put("current_session_context_class", "org.springframework.orm.hibernate5.SpringSessionContext");
            return properties;
        }

        @Autowired
        @Bean(name = "transactionManager")
        public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {
            HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);
            return transactionManager;
        }

        @Primary
        @Bean(name="myEntityManagerFactory")
        public LocalContainerEntityManagerFactoryBean myEntityManagerFactory() throws ClassNotFoundException {
            final LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();

            entityManagerFactoryBean.setDataSource(getDataSource());
            // mention packae scan your classes annotated as @Entity
            entityManagerFactoryBean.setPackagesToScan(new String[] { "com.pulseBeatMaster.model" });
            entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);

            final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
            vendorAdapter.setShowSql(true);
            entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
            entityManagerFactoryBean.setJpaProperties(getHibernateProperties());

            entityManagerFactoryBean.afterPropertiesSet();
            entityManagerFactoryBean.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());

            return entityManagerFactoryBean;
        }

        @Primary
        @Bean(name = "myTransactionManager")
        public PlatformTransactionManager myTransactionManager() {
            final JpaTransactionManager transactionManager = new JpaTransactionManager();
            try {
                transactionManager.setEntityManagerFactory(myEntityManagerFactory().getObject());
                transactionManager.setDataSource(getDataSource());
                transactionManager.setJpaDialect(new HibernateJpaDialect());
                transactionManager.setJpaProperties(getHibernateProperties());
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return transactionManager;
        }

        @Bean
        public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
            return new PersistenceExceptionTranslationPostProcessor();
        }

        @Bean
        public HibernateExceptionTranslator hibernateExceptionTranslator() {
            return new HibernateExceptionTranslator();
        }

        @Bean
        public JavaMailSender getMailSender() {
            JavaMailSenderImpl mailSender = new JavaMailSenderImpl();

            // Using gmail
            mailSender.setHost(environment.getRequiredProperty("mailSender.host"));
            mailSender.setPort(587);
            mailSender.setUsername(environment.getRequiredProperty("mailSender.username"));
            mailSender.setPassword(environment.getRequiredProperty("mailSender.password"));

            Properties javaMailProperties = new Properties();
            javaMailProperties.put("mail.smtp.starttls.enable", "true");

            javaMailProperties.put("mail.smtp.auth", "true");
            javaMailProperties.put("mail.transport.protocol", "smtp");
            javaMailProperties.put("mail.debug", "true");// Prints out everything on
                                                            // screen

            mailSender.setJavaMailProperties(javaMailProperties);
            return mailSender;
        }

    }

for minimal config via spring-boot properties just check this spring-boot-jpa
tutorial.