4

I have the following scenario:

  • There's a user repository which can save/update a user
  • I want to validate the user's firstname/lastname (perform some string operations) before saving/updating
  • If the user's firstname/lastname is < 2 character after having performed the operations, a checked custom UnacceptableStringValueException should be thrown

Note that many services access the user repository, so it's cumbersome to implement new logic directly before saving.

What I tried to do in order to perform the validation just before saving/updating without having to implement this for every save/update call explicitly, is to use a JPA listener. Using @PrePersist and @PreUpdate I achieved the goal of performing the validation before each save/update. However there are two problems with this solution:

  • The checked exception is not enforced on the methods which save/update a user and the exception gets automatically wrapped as a RuntimeException via the listener
  • When trying to use AOP to catch said RuntimeException and unpack the original checked exception, I keep getting org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only

Note that a simple service layer performing the check before saving/updating the user won't solve my use case because there's a user role repository which could also save/update a user (@ManyToOne(optional = false, cascade = CascadeType.PERSIST))

What's a good way to solve the constraints described in the scenario on top?

emazzotta
  • 1,879
  • 3
  • 20
  • 31
  • 1
    You can check/validate fields values by using java feature and if else condition in controller/service layer. And throw specific message by using custom exception class. refer (https://stackoverflow.com/questions/56832667/how-to-pass-api-exception-output-to-through-own-rest-service) – Null Pointer Jul 24 '19 at 12:43
  • Why not simply use Bean Validation on your entity fields, though? It integrates with JPA nicely and will work whenever you save/update the entity, whatever the method – crizzis Jul 24 '19 at 14:50
  • @crizzis the validation should take place after the string operations were performed (such as trimming) – emazzotta Jul 24 '19 at 16:46
  • Bean validation is invoked about the same time as the pre persist callback – crizzis Jul 24 '19 at 19:22
  • @crizzis thanks for the hint, unfortunately I need to dynamically load the allowed size from a config file, I'm not aware if that's compatible with bean validation – emazzotta Jul 25 '19 at 08:39
  • You can do that by implementing a custom validator. With Hibernate Validator, you can even register a custom validator for existing annotations, as described [here](https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#_constraint_definitions_via_code_serviceloader_code) – crizzis Jul 25 '19 at 09:04

1 Answers1

1

I found a somewhat viable solution by fixing the org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only error.

The problem was, that the checked exception caused an unexpected rollback, in order to fix this, I added my custom checked exception to the exceptions which can be rolled back like this: @Transactional(rollbackFor = {UnacceptableStringValueException.class})

emazzotta
  • 1,879
  • 3
  • 20
  • 31