Syncope's REST API propagates some exceptions to client side.
Actual exception mapping and possible improvements for CXF REST API migration are represented on this page.
Mapping exception to/from HTTP response
Actually service (core) propagates exceptions in syncopeClientError.jsp directly using http servlet response, client uses Spring handler (SyncopeClientErrorHandler) to get exception from HTTP response.
Suggestion: by CXF migration use CXF REST exception mappers for both sides: client and service. It makes code more harmonic and understandable.
Mapping exceptions to HTTP codes
Exception |
Old Code |
New Code |
InvalidEntityException |
BAD_REQUEST |
BAD_REQUEST |
NotFoundException |
NOT_FOUND |
NOT_FOUND |
WorkflowException |
BAD_REQUEST |
BAD_REQUEST |
PropagationException |
BAD_REQUEST |
BAD_REQUEST |
SyncopeClientCompositeErrorException |
BAD_REQUEST |
BAD_REQUEST |
MissingConfKeyException |
NOT_FOUND |
NOT_FOUND |
InvalidSearchConditionException |
BAD_REQUEST |
BAD_REQUEST |
UnauthorizedRoleException |
BAD_REQUEST |
FORBIDDEN |
DataIntegrityViolationException (spring.dao) |
BAD_REQUEST |
CONFLICT |
PersistenceException (javax) |
BAD_REQUEST |
INTERNAL_SERVER_ERROR |
ConfigurationException (connid) |
BAD_REQUEST |
INTERNAL_SERVER_ERROR |
All others |
INTERNAL_SERVER_ERROR |
INTERNAL_SERVER_ ERROR |
Mapping from SyncopeClientCompositeErrorException on server side
Actually SyncopeClientCompositeErrorException is sent using:
- ExceptionType HTTP header containing exception type (enumeration SyncopeClientExceptionType)
- <ExceptionType>.element HTTP header as list of strings for error details (that are used to fill SyncopeClientException.elements)
For the CXF REST migration we will keep current propagation one to one and will add more verbose exception in HTTP body at the second step
Mapping to SyncopeClientCompositeException on client side
Actually almost all exceptions with status BAD_REQUEST and NOT_FOUND are mapped to SyncopeClientCompositeErrorException on the client side.
It is absolutely OK for composite exceptions containing number of sub-exceptions (like validation and propagation), however for some single exceptions it makes more sense to map not to SyncopeClientCompositeErrorException, but directly to corresponded exception type.
Candidates are:
- Deadlock
- ExistingResource
- DataIntegrityViolation
- GenericPersistence
- UnauthorizedRole
Proposed mapping makes exception processing more easy and effective.
Mapping low level exceptions in core
Actually service layer processes three relative low level exceptions from persistence:
- org.apache.ibatis.exceptions.PersistenceException;
- org.springframework.orm.jpa.JpaSystemException;
- javax.persistence.PersistenceException
Suggestion: abstract service implementation from persistence a little bit more and wrap these three exceptions in high level Syncope PersistenceException.
>From my perspective it helps for the cases when Syncope will support alternative persistence technologies like Hibernate JPA, EclipseLink JPA or even LDAP, JCR, non-SQL DBs.
Checked vs Runtime exceptions
Accordingly Java Best Practices checked exceptions should be used only for conditions from which the caller can reasonably be expected to recover.
Runtime exceptions should be used for preconditions violation and for programming errors.
Candidates for checked exceptions are:
- InvalidSearchConditionException
- IncompatiblePolicyException
Candidates for runtime exceptions:
- all Validation exceptions inherited from javax.validation.ValidationException
- NotFoundException
- MissingConfKeyException
- AccountPolicyException
- PasswordPolicyException
- PolicyEnforceException
- UnauthorizedRoleException
- PropagationException
- ReportException
- WorkflowException