0
votes

I'm triyng to use @Transational in a method but i'm facing the following problem. First this is the scenario:

1- I update his password

2- I insert his id in a tracking table(simple insert query)

To test my transaction, I give an existing id (primary key) in the insert query.

The transaction works but I get this error Transaction silently rolled back because it has been marked as rollback-only knowing that the two functions are inside try-catch block and normally it should return Internal error.

When I use the breakpoint on the response it shows the internal error but in Postman I get Transaction silently rolled back because it has been marked as rollback-only.

This is my code:

import javax.transaction.Transactional;

@Transactional
    public UpdateUserPasswordResponse updateUserPassword(String login, String pwd, String newPwd)
            throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException,
            InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchPaddingException,
            UnsupportedEncodingException {

        GetUserByUsernameAndPasswordResponse responseLogin = new GetUserByUsernameAndPasswordResponse();

        UpdateUserPasswordResponse response = new UpdateUserPasswordResponse();

        // some code

        if (responseLogin.getUser() != null) {

//some code

            try {
                // call the update query from DAO
                int lineUpdated = dao.updateUserPassword(login, Cryptedpwd);


                int lineInserted = dao.insertUtilisateurTracking(responseLogin.getUser().getId(), new Date());

                response.setMessage(Constants.SUCCESS);
                response.setStatus(Constants.OK);

            } catch (Exception e) {

                response.setMessage(Constants.ERREUR_INTERNE);
                response.setStatus(Constants.KO);

            }
        } else {
            if (responseLogin.getMessage().equals(Constants.LOGIN_PASSWORD_INCORRECT)) {
                response.setStatus(Constants.KO);
                response.setMessage(Constants.LOGIN_PASSWORD_INCORRECT);
            } else {
                response.setMessage(Constants.ERREUR_INTERNE);
                response.setStatus(Constants.KO);
            }
        }

        return response;

    }
1
Of course the transaction will rollback. You got two write queries, one that update a password and the other one that insert an user. The first one is being rollback after the second one fails, since the user's id already exists. Unless, you want another behavior, that's what the @Transactional annotation will do for you. - Alain Cruz
@AlainCruz So there is no way to show Internal error instead of the transaction exception ?? - taha manar
Hmmm try adding the following @Transactional(rollbackFor = Exception.class). This force to rollback only if an Exception is thrown, might work, but not sure. - Alain Cruz

1 Answers

0
votes

This is the normal behavior and the reason is that your insertUtilisateurTracking method needs a TX when being executed. But when it is called inside updateUserPassword method, there is a TX available, the container doesn't create a new one and uses existing TX. So if any exception occurs in insertUtilisateurTracking method, it causes TX to be set to rollBackOnly (even if you catch the exception in the caller and ignore it).