Search code examples
javaresttransactionsjax-rs

Achieving transactional integrity using two service operations in a rest controller


I have a question regarding the transactional boundaries in REST-Controllers using Java/Jakarta EE and JAX-RS. Given the following controller, when a user is created in the @POST method, first the user is created using a dedicated service. Afterwards, the user´s permissions are stored using a different service. Both services wrap incoming calls in a container managed transaction.

@Path("/users")
public class UserController {

    @Inject
    private UserService userService;

    @Inject
    private PermissionService permissionService;

    @POST
    public UserDto createUser(UserDto userDto) {
        User user = mapToUser(userDto);
        User createdUser = userService.create(user);

        Permissions perms = mapToPermissions(userDto);
        permissionService.createPermissions(createdUser.getId());

        return mapToUserDto(createdUser);
    }
}

From my point of view, there exists a transactional boundary around userService.create() and a second one around permissionService.createPermissions(). Can you confirm that this is true?

Secondly, if the previous statement is true, and the applications shuts down mid processing, the users permissions might not be persisted. Is this appraoch considered bad practise and should both operations be performed in a single transaction (or in the REST-paradigm under different ressources / endpoints)?


Solution

  • You are correct, there are two transactions, so the first could succeed while the second fails.

    A common practice is using a Service Façade pattern. A coarse grained service that sets the transactions boundaries, and call the services to achieve the result.