Catch DataIntegrityViolationException in @Transactional service method
<p>I have a REST Spring boot app with Hibernate. For simplicity let's assume this workflow:</p>

<ol>
<li>Controller handles incoming requests, calls Service methods</li>
<li>Service methods are <code>@Transactional</code>, do some business logic and call Persistence methods</li>
<li>Persistence methods are handled by DAO objects, saving stuff into database.</li>
</ol>

<p>The database has a <code>unique</code> constraint on <code>username</code> of a User. The way I have it working now is this:</p>

<ol>
<li>Client sends request to Controller</li>
<li>Controller calls Service</li>
<li>Service attempts to save an object through DAO. If <code>DataViolationException</code> occurs, Service returns a custom Exception</li>
<li>Controller catches the custom Exception and sends back appropriate response</li>
</ol>

<hr>

<p>The pseudocode is this:</p>

<pre><code>public class UserController {
    @RequestMapping("/user")
    public User createUser(...){
        try{
            return userService.createUser(...);
        } catch (UserAlreadyExistsException e){
            // Do some processing and return error message to client
        }
    }
}

public class UserService {
    @Transactional
    public User createUser(...){
        (...)
        try{
            userDAO.save(newUserObject);
        } catch(DataIntegrityViolationException e){
            throw new UserAlreadyExistsException(username);
        }
    }
}
</code></pre>

<p>However, this way I am getting an error when a duplicate user is attempted to be created.</p>

<pre><code>javax.persistence.RollbackException: Transaction marked as rollbackOnly
</code></pre>

<p><strong>One way to fix this</strong> seems to be to let the <code>DataIntegrityViolationException</code> "bubble" up from the transaction (and not catch it in Service). But that means that the Controller has to handle persistence exceptions and I don't like that.</p>

<p>I prefer if the service threw "understandable" exceptions for the Controller to handle. The service knows what persistence exceptions to expect and when and is able to "translate" the broad <code>DataIntegrityViolationException</code> into a meaningful one.</p>

<p>Is there a way to handle the exceptions this way? I don't particularly like the idea of having a "2-layered service layer" to achieve this. </p>

<hr>

<p>EDIT: Another reason I want to throw my custom Exception is that it is required by the compiler to be caught. I want to enforce the controller to handle all possible exceptions that may occur.</p>