title: how do you handle and parse JPA persistence exceptions to provide meaningfull message to user
body: <p>I am fairly new to JPA and want to find best practices when handling persistence exceptions from JPA for things like say, unique constraint violations which <em>can</em> be addressed by the user. There are tons of examples on how to write JPA apps, but almost nothing on how to hand exceptions kicked out by them. :/  </p>
  
  <p>For example registering a user, the person enters an email address that is already in active use by the system and gets a constraint violation:</p>
  
  <pre><code>try {
       em.persist(credentials);
  } catch (javax.persistence.PersistenceException ex) {
  </code></pre>
  
  <p>which produces this error when a duplicate email is added:</p>
  
  <pre><code>WARNING: SQL Error: 0, SQLState: 23505
  SEVERE: ERROR: duplicate key value violates unique constraint "EMAIL_UQ_IDX"
    Detail: Key (email)=(testuser@xyz.com) already exists.
  </code></pre>
  
  <p>How can I get a meaningful answer back to the user? For example something like: Oops looks like someone is using that email address already, are you sure you haven't registered before? Is there a facility built in to parse this or will I need to run regexes against the exception message in a (possibly a series of) if statement(s)?</p>
  
  <p>And what about if it is caught on the business tier... what are best practices for kicking it up to the presentation tier... like I said before, so that a 'nice' message can be provided for the user.</p>
  
  <hr>
  
  <p>Added for clarity:
  Just so people know, I had, have, and am still looking at all the different types of persistence exceptions, and here is some of the research I've been doing I didn't include with the "try statement" example I included above:</p>
  
  <pre><code>try {
       em.persist(credentials);
       } catch (javax.persistence.PersistenceException ex) {
           System.out.println("EXCEPTION CLASS NAME: " + ex.getClass().getName().toString());
           System.out.println("THROWABLE CLASS NAME: " + ex.getCause().getClass().getName().toString());
                  Throwable th = ex.getCause();
           System.out.println("THROWABLE INFO: " + th.getCause().toString());
           Logger.getLogger(CredentialsControllerImpl.class
                .getName()).log(Level.INFO, "Credentials Controller "
                    + "persistence exception "
                        + "EXCEPTION STRING: {0}", ex.toString());
           Logger.getLogger(CredentialsControllerImpl.class
                .getName()).log(Level.INFO, "Credentials Controller "
                    + "persistence exception "
                        + "THROWABLE MESSAGE: {0}", th.getMessage());
           Logger.getLogger(CredentialsControllerImpl.class
                .getName()).log(Level.INFO, "Credentials Controller "
                    + "persistence exceptions "
                        + "THROWABLE STRING: {0}", th.toString());
       }
  </code></pre>
  
  <p>:)</p>