new validation logic

This commit is contained in:
Efstratios Giannopoulos 2023-12-18 18:23:37 +02:00
parent ab68a0bd4d
commit bd64566e8c
14 changed files with 409 additions and 160 deletions

View File

@ -0,0 +1,47 @@
package eu.eudat.commons.validation;
import eu.eudat.errorcode.ErrorThesaurusProperties;
import gr.cite.tools.exception.MyValidationException;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public abstract class BaseValidator implements ModelValidator {
private BeanPropertyBindingResult result;
protected final ErrorThesaurusProperties errors;
protected BaseValidator(ErrorThesaurusProperties errors) {
this.errors = errors;
}
@Override
public void validate(Object target){
this.result = new org.springframework.validation.BeanPropertyBindingResult(target, target.getClass().getName());
this.validate(target, this.result);
}
@Override
public void validateForce(Object target) {
this.validate(target);
if (this.result != null && result.hasErrors()){
List<Map.Entry<String, List<String>>> errorsMap = new ArrayList<>();
for (FieldError fieldError : result.getFieldErrors()){
errorsMap.add(new AbstractMap.SimpleEntry<>(fieldError.getField(), List.of(fieldError.getDefaultMessage())));
}
throw new MyValidationException(this.errors.getModelValidation().getCode(), errorsMap);
}
}
@Override
public Errors result() {
return this.result;
}
}

View File

@ -0,0 +1,10 @@
package eu.eudat.commons.validation;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
public interface ModelValidator extends Validator {
void validate(Object target);
void validateForce(Object target);
Errors result();
}

View File

@ -0,0 +1,12 @@
package eu.eudat.commons.validation;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface ValidationFilterAnnotation {
public String validator();
public String argumentName();
}

View File

@ -12,6 +12,9 @@ import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import java.util.List;
import java.util.UUID;

View File

@ -2,14 +2,26 @@ package eu.eudat.model.persist;
import eu.eudat.commons.enums.DescriptionTemplateTypeStatus;
import eu.eudat.commons.validation.BaseValidator;
import eu.eudat.commons.validation.FieldNotNullIfOtherSet;
import eu.eudat.commons.validation.ValidEnum;
import eu.eudat.commons.validation.ValidId;
import eu.eudat.data.DescriptionTemplateTypeEntity;
import eu.eudat.errorcode.ErrorThesaurusProperties;
import eu.eudat.model.Description;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import java.util.List;
import java.util.UUID;
@FieldNotNullIfOtherSet(message = "{validation.hashempty}")
@ -27,6 +39,10 @@ public class DescriptionTemplateTypePersist {
@ValidEnum(message = "{validation.empty}")
private DescriptionTemplateTypeStatus status;
private List<DescriptionTemplateTypePersist> nested;
private DescriptionTemplateTypePersist obj;
public UUID getId() {
return id;
@ -59,5 +75,82 @@ public class DescriptionTemplateTypePersist {
public void setStatus(DescriptionTemplateTypeStatus status) {
this.status = status;
}
public List<DescriptionTemplateTypePersist> getNested() {
return nested;
}
public void setNested(List<DescriptionTemplateTypePersist> nested) {
this.nested = nested;
}
public DescriptionTemplateTypePersist getObj() {
return obj;
}
public void setObj(DescriptionTemplateTypePersist obj) {
this.obj = obj;
}
@Component(DescriptionTemplateTypePersistValidator.ValidatorName)
public static class DescriptionTemplateTypePersistValidator extends BaseValidator {
@Autowired
private DescriptionTemplateTypePersistValidator1 descriptionTemplateTypePersistValidator;
public static final String ValidatorName = "DescriptionTemplateTypePersistValidator";
private final MessageSource messageSource;
public DescriptionTemplateTypePersistValidator(MessageSource messageSource, ErrorThesaurusProperties errors) {
super(errors);
this.messageSource = messageSource;
}
public boolean supports(Class clazz) {
return DescriptionTemplateTypePersist.class.equals(clazz);
}
public void validate(Object obj, Errors e) {
e.rejectValue("name", "negativevalue", messageSource.getMessage("General_ItemNotFound", new Object[]{"aaa", Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
DescriptionTemplateTypePersist p = (DescriptionTemplateTypePersist) obj;
try {
e.pushNestedPath("obj");
ValidationUtils.invokeValidator(descriptionTemplateTypePersistValidator, p.getObj(), e);
} finally {
e.popNestedPath();
}
for (int i = 0; i < p.getNested().size(); i++) {
try {
e.pushNestedPath("nested["+i+"]");
ValidationUtils.invokeValidator(descriptionTemplateTypePersistValidator, p.getObj(), e);
} finally {
e.popNestedPath();
}
}
}
}
@Component(DescriptionTemplateTypePersistValidator1.ValidatorName)
public static class DescriptionTemplateTypePersistValidator1 extends BaseValidator {
public static final String ValidatorName = "DescriptionTemplateTypePersistValidator1";
private final MessageSource messageSource;
public DescriptionTemplateTypePersistValidator1(MessageSource messageSource, ErrorThesaurusProperties errors) {
super(errors);
this.messageSource = messageSource;
}
public boolean supports(Class clazz) {
return DescriptionTemplateTypePersist.class.equals(clazz);
}
public void validate(Object obj, Errors e) {
e.rejectValue("name", "negativevalue", messageSource.getMessage("General_ItemNotFound", new Object[]{"aaa", Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
}
}
}

View File

@ -28,7 +28,8 @@ import java.util.List;
"eu.eudat.depositinterface",
"gr.cite",
"gr.cite.tools",
"gr.cite.commons"
"gr.cite.commons",
"eu.eudat.controllers.controllerhandler"
})
@EntityScan({
"eu.eudat.data"})

View File

@ -1,17 +1,11 @@
package eu.eudat.configurations;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import eu.eudat.interceptors.UserInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

View File

@ -1,31 +1,31 @@
package eu.eudat.controllers.controllerhandler;
import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.types.ApiMessageCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import jakarta.annotation.Priority;
/**
* Created by ikalyvas on 6/12/2018.
*/
@ControllerAdvice
@Priority(5)
public class ControllerErrorHandler {
private static final Logger logger = LoggerFactory.getLogger(ControllerErrorHandler.class);
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ResponseItem<Exception> processValidationError( Exception ex) throws Exception {
logger.error(ex.getMessage(), ex);
return new ResponseItem<Exception>().message(ex.getMessage()).status(ApiMessageCode.DEFAULT_ERROR_MESSAGE);
}
}
//package eu.eudat.controllers.controllerhandler;
//
//
//import eu.eudat.models.data.helpers.responses.ResponseItem;
//import eu.eudat.types.ApiMessageCode;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.http.HttpStatus;
//import org.springframework.web.bind.annotation.ControllerAdvice;
//import org.springframework.web.bind.annotation.ExceptionHandler;
//import org.springframework.web.bind.annotation.ResponseBody;
//import org.springframework.web.bind.annotation.ResponseStatus;
//
//import jakarta.annotation.Priority;
//
///**
// * Created by ikalyvas on 6/12/2018.
// */
//@ControllerAdvice
//@Priority(5)
//public class ControllerErrorHandler {
// private static final Logger logger = LoggerFactory.getLogger(ControllerErrorHandler.class);
//
// @ExceptionHandler(Exception.class)
// @ResponseStatus(HttpStatus.BAD_REQUEST)
// @ResponseBody
// public ResponseItem<Exception> processValidationError( Exception ex) throws Exception {
// logger.error(ex.getMessage(), ex);
// return new ResponseItem<Exception>().message(ex.getMessage()).status(ApiMessageCode.DEFAULT_ERROR_MESSAGE);
// }
//}

View File

@ -1,34 +1,34 @@
package eu.eudat.controllers.controllerhandler;
import eu.eudat.exceptions.security.UnauthorisedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import jakarta.annotation.Priority;
/**
* Created by ikalyvas on 6/12/2018.
*/
@ControllerAdvice
@Priority(4)
public class ControllerUnauthorisedHandler {
private static final Logger logger = LoggerFactory.getLogger(ControllerUnauthorisedHandler.class);
@Autowired
public ControllerUnauthorisedHandler() {
}
@ExceptionHandler(UnauthorisedException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ResponseBody
public void processValidationError(UnauthorisedException ex) {
logger.error(ex.getMessage(), ex);
return;
}
}
//package eu.eudat.controllers.controllerhandler;
//
//import eu.eudat.exceptions.security.UnauthorisedException;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.http.HttpStatus;
//import org.springframework.web.bind.annotation.ControllerAdvice;
//import org.springframework.web.bind.annotation.ExceptionHandler;
//import org.springframework.web.bind.annotation.ResponseBody;
//import org.springframework.web.bind.annotation.ResponseStatus;
//
//import jakarta.annotation.Priority;
//
///**
// * Created by ikalyvas on 6/12/2018.
// */
//@ControllerAdvice
//@Priority(4)
//public class ControllerUnauthorisedHandler {
// private static final Logger logger = LoggerFactory.getLogger(ControllerUnauthorisedHandler.class);
//
// @Autowired
// public ControllerUnauthorisedHandler() {
// }
//
// @ExceptionHandler(UnauthorisedException.class)
// @ResponseStatus(HttpStatus.UNAUTHORIZED)
// @ResponseBody
// public void processValidationError(UnauthorisedException ex) {
// logger.error(ex.getMessage(), ex);
// return;
// }
//}

View File

@ -1,19 +1,19 @@
package eu.eudat.controllers.controllerhandler;
import eu.eudat.exceptions.security.NullEmailException;
import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.types.ApiMessageCode;
import org.springframework.core.annotation.Order;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
@Order(2)
public class ControllerUserNullEmailHandler {
@ExceptionHandler(NullEmailException.class)
public ResponseEntity nullEmailException(Exception ex) throws Exception {
return ResponseEntity.status(ApiMessageCode.NULL_EMAIL.getValue()).body("");
}
}
//package eu.eudat.controllers.controllerhandler;
//
//import eu.eudat.exceptions.security.NullEmailException;
//import eu.eudat.models.data.helpers.responses.ResponseItem;
//import eu.eudat.types.ApiMessageCode;
//import org.springframework.core.annotation.Order;
//import org.springframework.http.ResponseEntity;
//import org.springframework.web.bind.annotation.ControllerAdvice;
//import org.springframework.web.bind.annotation.ExceptionHandler;
//
//@ControllerAdvice
//@Order(2)
//public class ControllerUserNullEmailHandler {
//
// @ExceptionHandler(NullEmailException.class)
// public ResponseEntity nullEmailException(Exception ex) throws Exception {
// return ResponseEntity.status(ApiMessageCode.NULL_EMAIL.getValue()).body("");
// }
//}

View File

@ -1,66 +1,66 @@
package eu.eudat.controllers.controllerhandler;
import eu.eudat.models.data.errormodels.ValidationErrorContext;
import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.types.ApiMessageCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import java.util.List;
import java.util.Locale;
@ControllerAdvice
@Order(3)
public class ControllerValidatorErrorHandler {
private MessageSource messageSource;
@Autowired
public ControllerValidatorErrorHandler(MessageSource messageSource) {
this.messageSource = messageSource;
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ResponseItem<ValidationErrorContext> processValidationError(MethodArgumentNotValidException ex) {
BindingResult result = ex.getBindingResult();
List<FieldError> fieldErrors = result.getFieldErrors();
return processFieldErrors(fieldErrors);
}
private ResponseItem<ValidationErrorContext> processFieldErrors(List<FieldError> fieldErrors) {
ValidationErrorContext dto = new ValidationErrorContext();
for (FieldError fieldError : fieldErrors) {
String localizedErrorMessage = resolveLocalizedErrorMessage(fieldError);
dto.addFieldError(fieldError.getField(), localizedErrorMessage);
}
return new ResponseItem<ValidationErrorContext>().status(ApiMessageCode.VALIDATION_MESSAGE).payload(dto);
}
private String resolveLocalizedErrorMessage(FieldError fieldError) {
Locale currentLocale = LocaleContextHolder.getLocale();
String localizedErrorMessage = messageSource.getMessage(fieldError, currentLocale);
if (localizedErrorMessage.equals(fieldError.getDefaultMessage())) {
String[] fieldErrorCodes = fieldError.getCodes();
localizedErrorMessage = fieldErrorCodes[0];
}
return localizedErrorMessage;
}
}
//package eu.eudat.controllers.controllerhandler;
//
//import eu.eudat.models.data.errormodels.ValidationErrorContext;
//import eu.eudat.models.data.helpers.responses.ResponseItem;
//import eu.eudat.types.ApiMessageCode;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.context.MessageSource;
//import org.springframework.context.i18n.LocaleContextHolder;
//import org.springframework.core.annotation.Order;
//import org.springframework.http.HttpStatus;
//import org.springframework.validation.BindingResult;
//import org.springframework.validation.FieldError;
//import org.springframework.web.bind.MethodArgumentNotValidException;
//import org.springframework.web.bind.annotation.ControllerAdvice;
//import org.springframework.web.bind.annotation.ExceptionHandler;
//import org.springframework.web.bind.annotation.ResponseBody;
//import org.springframework.web.bind.annotation.ResponseStatus;
//
//import java.util.List;
//import java.util.Locale;
//
//
//@ControllerAdvice
//@Order(3)
//public class ControllerValidatorErrorHandler {
//
// private MessageSource messageSource;
//
// @Autowired
// public ControllerValidatorErrorHandler(MessageSource messageSource) {
// this.messageSource = messageSource;
// }
//
// @ExceptionHandler(MethodArgumentNotValidException.class)
// @ResponseStatus(HttpStatus.BAD_REQUEST)
// @ResponseBody
// public ResponseItem<ValidationErrorContext> processValidationError(MethodArgumentNotValidException ex) {
// BindingResult result = ex.getBindingResult();
// List<FieldError> fieldErrors = result.getFieldErrors();
//
// return processFieldErrors(fieldErrors);
// }
//
// private ResponseItem<ValidationErrorContext> processFieldErrors(List<FieldError> fieldErrors) {
// ValidationErrorContext dto = new ValidationErrorContext();
//
// for (FieldError fieldError : fieldErrors) {
// String localizedErrorMessage = resolveLocalizedErrorMessage(fieldError);
// dto.addFieldError(fieldError.getField(), localizedErrorMessage);
// }
//
// return new ResponseItem<ValidationErrorContext>().status(ApiMessageCode.VALIDATION_MESSAGE).payload(dto);
// }
//
// private String resolveLocalizedErrorMessage(FieldError fieldError) {
// Locale currentLocale = LocaleContextHolder.getLocale();
// String localizedErrorMessage = messageSource.getMessage(fieldError, currentLocale);
//
// if (localizedErrorMessage.equals(fieldError.getDefaultMessage())) {
// String[] fieldErrorCodes = fieldError.getCodes();
// localizedErrorMessage = fieldErrorCodes[0];
// }
//
// return localizedErrorMessage;
// }
//}

View File

@ -0,0 +1,30 @@
package eu.eudat.controllers.controllerhandler;
import eu.eudat.errorcode.ErrorThesaurusProperties;
import gr.cite.tools.exception.MyValidationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.WebRequest;
@RestControllerAdvice
@ControllerAdvice
public class GlobalExceptionHandler {
private final ErrorThesaurusProperties errors;
public GlobalExceptionHandler(ErrorThesaurusProperties errors) {
this.errors = errors;
}
@ExceptionHandler(Exception.class)
public ResponseEntity<?> handleUnexpectedErrors(Exception e, WebRequest request) throws Exception {
if (e instanceof MyValidationException argumentNotValidException) {
return new ResponseEntity<>(argumentNotValidException.getErrors(), HttpStatus.BAD_REQUEST);
}
else {
throw e;
}
}
}

View File

@ -0,0 +1,55 @@
package eu.eudat.controllers.controllerhandler;
import eu.eudat.commons.validation.BaseValidator;
import eu.eudat.commons.validation.ValidationFilterAnnotation;
import eu.eudat.logic.services.ApiContext;
import gr.cite.tools.exception.MyApplicationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Objects;
@ControllerAdvice
@RestControllerAdvice
public class ValidatorRequestBodyAdvice implements RequestBodyAdvice {
@Autowired
private ApiContext apiContext;
@Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
Class<? extends HttpMessageConverter<?>> converterType) {
if (parameter.getMethod() != null) {
ValidationFilterAnnotation annotation = parameter.getMethod().getAnnotation((ValidationFilterAnnotation.class));
if (annotation == null || !Objects.equals(parameter.getParameterName(), annotation.argumentName())) return body;
BaseValidator validator = this.apiContext.getOperationsContext().getApplicationContext().getBean(annotation.validator(), BaseValidator.class);
if (validator == null) throw new MyApplicationException("validator not provided");
validator.validateForce(body);
}
return body;
}
@Override
public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return body;
}
@Override
public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
return inputMessage;
}
}

View File

@ -3,6 +3,8 @@ package eu.eudat.controllers.v2;
import eu.eudat.audit.AuditableAction;
import eu.eudat.authorization.AuthorizationFlags;
import eu.eudat.data.DescriptionTemplateTypeEntity;
import eu.eudat.commons.validation.ValidationFilterAnnotation;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.model.DescriptionTemplateType;
import eu.eudat.model.builder.DescriptionTemplateTypeBuilder;
import eu.eudat.model.censorship.DescriptionTemplateTypeCensor;
@ -21,8 +23,8 @@ import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import gr.cite.tools.validation.MyValidate;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.transaction.annotation.Transactional;
@ -36,9 +38,10 @@ import java.util.*;
public class DescriptionTemplateTypeController {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTemplateTypeController.class));
@Autowired
private ApiContext apiContext;
private final BuilderFactory builderFactory;
private final AuditService auditService;
private final DescriptionTemplateTypeService descriptionTemplateTypeService;
@ -104,7 +107,8 @@ public class DescriptionTemplateTypeController {
@PostMapping("persist")
@Transactional
public DescriptionTemplateType Persist(@MyValidate @RequestBody DescriptionTemplateTypePersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException {
@ValidationFilterAnnotation(validator = DescriptionTemplateTypePersist.DescriptionTemplateTypePersistValidator.ValidatorName, argumentName ="model")
public DescriptionTemplateType Persist(@RequestBody DescriptionTemplateTypePersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException {
logger.debug(new MapLogEntry("persisting" + DescriptionTemplateType.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet));
DescriptionTemplateType persisted = this.descriptionTemplateTypeService.persist(model, fieldSet);