Domain service to (attempt) to recognize certain exceptions, and return user-friendly messages instead.

Rather than redirecting to a general-purpose error page, the message (corresponding to the recognized exception) is rendered as a regular validation message.

For example, a set of recognizers are provided for the JPA and JDO persistence mechanisms in order to recognize and handle SQL constraint exceptions such as uniqueness violations. These can then be rendered back to the user as expected errors, rather than fatal stacktraces.

More than one implementation of ExceptionRecognizer can be registered; they will all be consulted (in the order as specified by Spring’s org.springframework.core.annotation.Order annotation) to determine if they recognize the exception. The message returned by the first service recognizing the exception is used.

The framework also provides a default implementation of this service that recognizes any org.apache.isis.applib.exceptions.RecoverableException , simply returning the exception’s org.apache.isis.applib.exceptions.RecoverableException#getMessage() message . This allows any component or domain object to throw this exception with the knowledge that it will be handled appropriately.

Initially introduced for the Wicket viewer; check the documentation of other viewers to determine whether they also support this service.


interface ExceptionRecognizer {
  Optional<Recognition> recognize(Throwable ex)     (1)
1 recognize(Throwable)

(Attempt to) recognize the exception and return a user-friendly message to render instead.



(Attempt to) recognize the exception and return a user-friendly message to render instead.


The framework provides a number of default implementations for JPA and JDO, to recognise:

  • data already exists (uniqueness constraints)

  • object not found

  • related data exists (foreign key constraints preventing change)

  • unable to save data (foreign key constraints not met)

  • other data access problem.


If you want to recognize and handle additional exceptions (for example to capture error messages specific to the JDBC driver you might be using), then create an implementation of this SPI for the particular error message, and annotate your implementation as a DomainService.

There are some convenience implementations of the interface to subclass from if required.

See also