1

my question is to change password for user that is logged in the system. It prints out new password changed successfully but when i check it, the password remains the same and has not been changed. Is it because i use set.Password? Is there other ways? This code tries to retrieve Employee using username.

UPDATED : This question has been resolved by Alex's brilliant answer along with the other suggestions! Thank you all.

This is the method to invoke the remote controller

 private void doChangePassword() throws UserNameNotFoundException, EmployeeNotFoundException {


    Scanner scanner = new Scanner(System.in);

    System.out.println("*** Administration Panel :: Change Password ***\n");
    System.out.print("Enter username> ");
    String username = scanner.nextLine().trim();
    System.out.print("Enter current password> ");
    String currentPassword = scanner.nextLine().trim();
    System.out.print("Enter new password> ");
    String newPassword = scanner.nextLine().trim();
    System.out.print("Enter new password again> ");
    String reenterNewPassword = scanner.nextLine().trim();

    currentEmployee = employeeControllerRemote.retrievePasswordByUsername(username);
    if (currentPassword.equals(currentEmployee.getPassword())) {
        if (newPassword.equals(reenterNewPassword)) {
            currentEmployee.setPassword(newPassword);  
            //Updated here
           employeeControllerRemote.updateNewPassword(currentEmployee);

            System.out.println("New Password changed successfully!\n");
        } else {
            System.out.println("New Password mismatched!\n");
        }
    }
    else {
        System.out.println("Wrong password, please try again later");
    }
    }

In another program, stateless session bean called employeeController. This method is implemented in employeeControllerRemote and local as well.

@Override
public Employee retrievePasswordByUsername(String username) throws UserNameNotFoundException {

    Query query = em.createQuery("SELECT e FROM Employee e WHERE e.username = :inUsername", Employee.class);
    query.setParameter("inUsername", username);
    return (Employee) query.getSingleResult();
    //Changed it according to suggestions
}

This is the new method that i created. I tried to use commit but it didn't work. I also tried to use persist and flush. But it says that it is a duplicate and there were illegal arguement errors. The flush did not work as well and the error code mentioned that there was nothing to flush. I created this new method did not put it under retrievePasswordByUsername method because i think that it should not be there since it just retrieves it? So i created a new method below. It still does not work though.

@Override
 public void updateNewPassword(Employee employee) {
    //em.getTransaction().begin();
    em.flush();
    //em.getTransaction().commit();
}

Thank you all for your time! :)

  • First you should check if user exists and current PW is correct, before you enter a new one. – LenglBoy Oct 23 '17 at 07:37
  • After you set the password, you need to `flush` before it is updating the database. – Alex Oct 23 '17 at 07:40
  • do tell us what object lifecycle state (managed, detached, transient?) the object is in when you update a field on it? because that then determines what you need to do to get the changes in the database. As per the JPA spec ... –  Oct 23 '17 at 08:03
  • You may treat the `employee` passing to your client side and back to your server side is detached. So if you try to `persist` it again, it'll say it is duplicated as JPA will try to "Insert" instead of "Update" – Alex Oct 23 '17 at 08:56

3 Answers3

0

You need to persist the changed Entity/Data. entityManager.persist(employee); after you set the new PW.

Here are some other hints:

Casts shouldn´t be done. You can modify to this.

Query query = em.createQuery("SELECT e FROM Employee e WHERE e.username = :inUsername", Employee.class);
query.setParameter("inUsername", username);
return query.getSingleResult(); // now EMPLOYEE

Your workflow sould be:

  1. Enter userName
  2. Check if user exists (byName)
  3. Input currentPassword, newPassword, newPasswordConfirm
  4. Change the values
  5. Persist your User/Employee so the change will be in DB, too. Without saving it in DB you just changed the local used Object-Instance.
LenglBoy
  • 1,451
  • 1
  • 10
  • 24
  • Maybe you´ve not added the `commit()` after all interactions? So the changes are not realy done and there is a rollback? – LenglBoy Oct 23 '17 at 08:16
  • And you´re using method-variables so how can you to this after `doChangePassword()`? Add the merge/persist after `setPassword()` for a short thest and have a look in your DB - not only your code. – LenglBoy Oct 23 '17 at 08:21
  • I accidentally deleted the previous comment. But i'll check on the code right now. :) Thanks for the help. Will update again. –  Oct 23 '17 at 08:24
  • 1
    Hi! Thank you for your help! My problem has been resolved. I just needed to update my password in the session bean instead of changing it on the client side. –  Oct 23 '17 at 09:03
0

You should not do the password updating in your doChangePassword() method, as it is in client side. It cannot update anything to database directly. It needs to do it via your stateless session bean.

So you should modify your method in stateless session bean to do the update job.

@Override
public void updatePasswordByUsername(String username, String password) throws UserNameNotFoundException
{
    Query query = em.createQuery("SELECT e FROM Employee e WHERE e.username = :inUsername");
    query.setParameter("inUsername", username);
    //query.getSingleResult();

    Employee employee = (Employee) query.getSingleResult();
    employee.setPassword(password);
    em.persist(employee);    
}

Then you call this method in your client side through stateless session bean.

You may need to check the old password again in your stateless session bean in order to avoid attacks that bypass your client-side checking.

Alex
  • 803
  • 4
  • 9
  • Hi! Thanks for the suggestion. I'll try it now :) –  Oct 23 '17 at 08:48
  • Hi! Thank you so much for this solution. It resolved my problem. It was like what you said, it is in client side so it didn't update the database directly. After doing it via your method (stateless session bean) it worked. Thank you! –  Oct 23 '17 at 09:01
-3

you should use one of these "save, persist, update, merge, saveOrUpdate"

Try using the EntityManager.merge method - this is very similar.

employee.setPassword(newPassword);   
em.merge(employee);
emreucar
  • 21
  • 5