From 28af1211cb44f3cde494606c0ff63978a50a690b Mon Sep 17 00:00:00 2001 From: luk-kaminski Date: Wed, 27 Mar 2024 12:49:08 +0100 Subject: [PATCH 1/3] Config processing with lazy error handling --- .../github/joschi/jadconfig/JadConfig.java | 136 +++++++++++++----- .../jadconfig/response/ProcessingOutcome.java | 35 +++++ .../response/ProcessingResponse.java | 29 ++++ .../JadConfigLazyProcessingTest.java | 47 ++++++ 4 files changed, 213 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/github/joschi/jadconfig/response/ProcessingOutcome.java create mode 100644 src/main/java/com/github/joschi/jadconfig/response/ProcessingResponse.java create mode 100644 src/test/java/com/github/joschi/jadconfig/JadConfigLazyProcessingTest.java diff --git a/src/main/java/com/github/joschi/jadconfig/JadConfig.java b/src/main/java/com/github/joschi/jadconfig/JadConfig.java index 05e199d..1ae2c2d 100644 --- a/src/main/java/com/github/joschi/jadconfig/JadConfig.java +++ b/src/main/java/com/github/joschi/jadconfig/JadConfig.java @@ -2,6 +2,7 @@ import com.github.joschi.jadconfig.converters.NoConverter; import com.github.joschi.jadconfig.converters.StringConverter; +import com.github.joschi.jadconfig.response.ProcessingResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,9 +20,7 @@ import java.util.Objects; import java.util.Optional; -import static com.github.joschi.jadconfig.ReflectionUtils.getAllFields; -import static com.github.joschi.jadconfig.ReflectionUtils.getAllMethods; -import static com.github.joschi.jadconfig.ReflectionUtils.invokeMethodsWithAnnotation; +import static com.github.joschi.jadconfig.ReflectionUtils.*; /** * The main class for JadConfig. It's responsible for parsing the configuration bean(s) that contain(s) the annotated @@ -85,6 +84,8 @@ public JadConfig(Collection repositories, Object... configurationBea * Processes the configuration provided by the configured {@link Repository} and filling the provided configuration * beans. * + * Stops processing on first encountered exception. + * * @throws RepositoryException If an error occurred while reading from the configured {@link Repository} * @throws ValidationException If any parameter couldn't be successfully validated */ @@ -103,53 +104,99 @@ public void process() throws RepositoryException, ValidationException { } } + /** + * Processes the configuration provided by the configured {@link Repository} and filling the provided configuration + * beans. + * + * Instead of stopping processing on first encountered exception, tries to collect all validation problems and return them in single response, + * allowing identifying many problems at once. + * + * @return Response object, containing encountered problems if processing was not successful. + */ + public ProcessingResponse processFailingLazily() throws RepositoryException { + + ProcessingResponse response = new ProcessingResponse(); + + for (Repository repository : repositories) { + LOG.debug("Opening repository {}", repository); + repository.open(); + } + + for (Object configurationBean : configurationBeans) { + LOG.debug("Processing configuration bean {}", configurationBean); + + response.addOutcome( + configurationBean, + processClassFieldsFailingLazily(configurationBean, getAllFields(configurationBean.getClass())), + invokeValidatorMethodsFailingLazily(configurationBean, getAllMethods(configurationBean.getClass())) + ); + } + return response; + } + private void processClassFields(Object configurationBean, Field[] fields) throws ValidationException { for (Field field : fields) { - Parameter parameter = field.getAnnotation(Parameter.class); + processClassField(configurationBean, field); + } + } - if (parameter != null) { - LOG.debug("Processing field {}", parameter); + private Map processClassFieldsFailingLazily(Object configurationBean, Field[] fields) { + Map fieldProcessingProblems = new HashMap<>(); + for (Field field : fields) { + try { + processClassField(configurationBean, field); + } catch (Exception ex) { + fieldProcessingProblems.put(field.getAnnotation(Parameter.class).value(), ex); + } + } + return fieldProcessingProblems; + } - Object fieldValue = getFieldValue(field, configurationBean); + private void processClassField(Object configurationBean, Field field) throws ValidationException { + Parameter parameter = field.getAnnotation(Parameter.class); - String parameterName = parameter.value(); - String parameterValue = lookupParameter(parameterName) - .orElseGet(() -> lookupFallbackParameter(parameter)); + if (parameter != null) { + LOG.debug("Processing field {}", parameter); + Object fieldValue = getFieldValue(field, configurationBean); - if (parameterValue == null && fieldValue == null && parameter.required()) { - throw new ParameterException("Required parameter \"" + parameterName + "\" not found."); - } + String parameterName = parameter.value(); + String parameterValue = lookupParameter(parameterName) + .orElseGet(() -> lookupFallbackParameter(parameter)); - if (parameterValue != null) { - if (parameter.trim()) { - LOG.debug("Trimmed parameter value {}", parameterName); - parameterValue = Strings.trim(parameterValue); - } + if (parameterValue == null && fieldValue == null && parameter.required()) { + throw new ParameterException("Required parameter \"" + parameterName + "\" not found."); + } - LOG.debug("Converting parameter value {}", parameterName); - try { - fieldValue = convertStringValue(field.getType(), parameter.converter(), parameterValue); - } catch (ParameterException e) { - throw new ParameterException("Couldn't convert value for parameter \"" + parameterName + "\"", e); - } + if (parameterValue != null) { - LOG.debug("Validating parameter {}", parameterName); - final List>> validators = - new ArrayList<>(Collections.>>singleton(parameter.validator())); - validators.addAll(Arrays.asList(parameter.validators())); - validateParameter(validators, parameterName, fieldValue); + if (parameter.trim()) { + LOG.debug("Trimmed parameter value {}", parameterName); + parameterValue = Strings.trim(parameterValue); } - LOG.debug("Setting parameter {} to {}", parameterName, fieldValue); - + LOG.debug("Converting parameter value {}", parameterName); try { - field.set(configurationBean, fieldValue); - } catch (Exception e) { - throw new ParameterException("Couldn't set field " + field.getName(), e); + fieldValue = convertStringValue(field.getType(), parameter.converter(), parameterValue); + } catch (ParameterException e) { + throw new ParameterException("Couldn't convert value for parameter \"" + parameterName + "\"", e); } + + LOG.debug("Validating parameter {}", parameterName); + final List>> validators = + new ArrayList<>(Collections.>>singleton(parameter.validator())); + validators.addAll(Arrays.asList(parameter.validators())); + validateParameter(validators, parameterName, fieldValue); + } + + LOG.debug("Setting parameter {} to {}", parameterName, fieldValue); + + try { + field.set(configurationBean, fieldValue); + } catch (Exception e) { + throw new ParameterException("Couldn't set field " + field.getName(), e); } } } @@ -242,6 +289,27 @@ private void invokeValidatorMethods(Object configurationBean, Method[] methods) } } + private Map invokeValidatorMethodsFailingLazily(Object configurationBean, Method[] methods) { + Map problems = new HashMap<>(); + + for (Method method : methods) { + if (method.isAnnotationPresent(ValidatorMethod.class)) { + try { + method.invoke(configurationBean); + } catch (InvocationTargetException invEx) { + if (invEx.getTargetException() instanceof ValidationException) { + problems.put(method.getName(), (ValidationException)invEx.getTargetException()); + } else { + problems.put(method.getName(), invEx); + } + } catch (Exception ex) { + problems.put(method.getName(), ex); + } + } + } + return problems; + } + private Class> findConverter(Class clazz) { for (ConverterFactory factory : converterFactories) { Class> result = factory.getConverter(clazz); diff --git a/src/main/java/com/github/joschi/jadconfig/response/ProcessingOutcome.java b/src/main/java/com/github/joschi/jadconfig/response/ProcessingOutcome.java new file mode 100644 index 0000000..4f6e8ac --- /dev/null +++ b/src/main/java/com/github/joschi/jadconfig/response/ProcessingOutcome.java @@ -0,0 +1,35 @@ +package com.github.joschi.jadconfig.response; + +import java.util.Map; + +public class ProcessingOutcome { + + private final Object configurationBean; + private final Map fieldProcessingProblems; + private final Map validationMethodsProblems; + + public ProcessingOutcome(final Object configurationBean, + final Map fieldProcessingProblems, + final Map validationMethodsProblems) { + this.configurationBean = configurationBean; + this.fieldProcessingProblems = fieldProcessingProblems; + this.validationMethodsProblems = validationMethodsProblems; + } + + public boolean hasProblems() { + return (fieldProcessingProblems != null && !fieldProcessingProblems.isEmpty()) || + (validationMethodsProblems != null && !validationMethodsProblems.isEmpty()); + } + + public Object getConfigurationBean() { + return configurationBean; + } + + public Map getFieldProcessingProblems() { + return fieldProcessingProblems; + } + + public Map getValidationMethodsProblems() { + return validationMethodsProblems; + } +} diff --git a/src/main/java/com/github/joschi/jadconfig/response/ProcessingResponse.java b/src/main/java/com/github/joschi/jadconfig/response/ProcessingResponse.java new file mode 100644 index 0000000..f80c47a --- /dev/null +++ b/src/main/java/com/github/joschi/jadconfig/response/ProcessingResponse.java @@ -0,0 +1,29 @@ +package com.github.joschi.jadconfig.response; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +public class ProcessingResponse { + + private List outcomes; + + public ProcessingResponse() { + this.outcomes = new LinkedList<>(); + } + + public void addOutcome(final Object configurationBean, + final Map fieldProcessingProblems, + final Map validationMethodsProblems) { + outcomes.add(new ProcessingOutcome(configurationBean, fieldProcessingProblems, validationMethodsProblems)); + } + + public List getOutcomes() { + return outcomes; + } + + public boolean isSuccess() { + return outcomes.stream().noneMatch(ProcessingOutcome::hasProblems); + } +} + diff --git a/src/test/java/com/github/joschi/jadconfig/JadConfigLazyProcessingTest.java b/src/test/java/com/github/joschi/jadconfig/JadConfigLazyProcessingTest.java new file mode 100644 index 0000000..226436b --- /dev/null +++ b/src/test/java/com/github/joschi/jadconfig/JadConfigLazyProcessingTest.java @@ -0,0 +1,47 @@ +package com.github.joschi.jadconfig; + +import com.github.joschi.jadconfig.repositories.InMemoryRepository; +import com.github.joschi.jadconfig.response.ProcessingOutcome; +import com.github.joschi.jadconfig.response.ProcessingResponse; +import com.github.joschi.jadconfig.testbeans.ValidatedConfigurationBean; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.*; + +public class JadConfigLazyProcessingTest { + + private JadConfig jadConfig; + private Repository repository; + + + @Test + public void testProcess() throws RepositoryException { + HashMap properties = new HashMap<>(); + properties.put("test.byte","1"); + properties.put("test.short","2"); + properties.put("test.integer","-3");//negative, smaller than test.short + properties.put("test.integer.port","70000"); //bigger than allowed port + properties.put("test.long","4"); + properties.put("test.string","Test"); + repository = new InMemoryRepository(properties); + ValidatedConfigurationBean configurationBean = new ValidatedConfigurationBean(); + jadConfig = new JadConfig(repository, configurationBean); + + ProcessingResponse response = jadConfig.processFailingLazily(); + assertFalse(response.isSuccess()); + assertEquals(1, response.getOutcomes().size()); + ProcessingOutcome processingOutcome = response.getOutcomes().get(0); + assertEquals(configurationBean, processingOutcome.getConfigurationBean()); + Map fieldProcessingProblems = processingOutcome.getFieldProcessingProblems(); + assertEquals(2, fieldProcessingProblems.size()); + assertTrue(fieldProcessingProblems.containsKey("test.integer")); + assertTrue(fieldProcessingProblems.containsKey("test.integer.port")); + + Map validationMethodsProblems = processingOutcome.getValidationMethodsProblems(); + assertEquals(1, validationMethodsProblems.size()); + assertTrue(validationMethodsProblems.containsKey("validate")); + } +} From 3ab4f766edc972da40ce087b67b4b75a0a825df2 Mon Sep 17 00:00:00 2001 From: Tomas Dvorak Date: Fri, 19 Apr 2024 13:40:29 +0200 Subject: [PATCH 2/3] Throw exception if lazy validation processing detects any errors --- .../github/joschi/jadconfig/JadConfig.java | 16 ++++-- .../jadconfig/LazyValidationException.java | 39 +++++++++++++ .../JadConfigLazyProcessingTest.java | 55 ++++++++++--------- .../testbeans/ValidatedConfigurationBean.java | 3 +- 4 files changed, 79 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/github/joschi/jadconfig/LazyValidationException.java diff --git a/src/main/java/com/github/joschi/jadconfig/JadConfig.java b/src/main/java/com/github/joschi/jadconfig/JadConfig.java index 1ae2c2d..6bd0a19 100644 --- a/src/main/java/com/github/joschi/jadconfig/JadConfig.java +++ b/src/main/java/com/github/joschi/jadconfig/JadConfig.java @@ -107,14 +107,18 @@ public void process() throws RepositoryException, ValidationException { /** * Processes the configuration provided by the configured {@link Repository} and filling the provided configuration * beans. - * - * Instead of stopping processing on first encountered exception, tries to collect all validation problems and return them in single response, - * allowing identifying many problems at once. - * - * @return Response object, containing encountered problems if processing was not successful. + *

+ * Instead of stopping processing on first encountered exception, tries to collect all validation problems and in + * case of any problems aggregate them all into single exception, listing all the field and validation issues. */ - public ProcessingResponse processFailingLazily() throws RepositoryException { + public void processFailingLazily() throws RepositoryException, LazyValidationException { + final ProcessingResponse result = doProcessFailingLazily(); + if (!result.isSuccess()) { + throw new LazyValidationException(result); + } + } + ProcessingResponse doProcessFailingLazily() throws RepositoryException { ProcessingResponse response = new ProcessingResponse(); for (Repository repository : repositories) { diff --git a/src/main/java/com/github/joschi/jadconfig/LazyValidationException.java b/src/main/java/com/github/joschi/jadconfig/LazyValidationException.java new file mode 100644 index 0000000..146655b --- /dev/null +++ b/src/main/java/com/github/joschi/jadconfig/LazyValidationException.java @@ -0,0 +1,39 @@ +package com.github.joschi.jadconfig; + +import com.github.joschi.jadconfig.response.ProcessingOutcome; +import com.github.joschi.jadconfig.response.ProcessingResponse; + +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Stream; + +public class LazyValidationException extends ValidationException { + private final ProcessingResponse processingResponse; + + public LazyValidationException(ProcessingResponse result) { + super(toMessage(result)); + this.processingResponse = result; + } + + private static String toMessage(ProcessingResponse result) { + final List stringBuilder = new LinkedList<>(); + stringBuilder.add("Following errors ocurred during configuration processing:"); + result.getOutcomes().stream() + .filter(ProcessingOutcome::hasProblems) + .flatMap(processingOutcome -> Stream.concat( + processingOutcome.getFieldProcessingProblems().values().stream().map(e -> toMessage(processingOutcome, e)), + processingOutcome.getValidationMethodsProblems().values().stream().map(e -> toMessage(processingOutcome, e)) + )).forEach(stringBuilder::add); + return String.join("\n", stringBuilder); + } + + private static String toMessage(ProcessingOutcome processingOutcome, Exception exception) { + // TODO: should we distinct between field processing problem and validation method? + // TODO: should we include class name of the bean or not? + return exception.getMessage(); + } + + public ProcessingResponse getProcessingResponse() { + return processingResponse; + } +} diff --git a/src/test/java/com/github/joschi/jadconfig/JadConfigLazyProcessingTest.java b/src/test/java/com/github/joschi/jadconfig/JadConfigLazyProcessingTest.java index 226436b..086301b 100644 --- a/src/test/java/com/github/joschi/jadconfig/JadConfigLazyProcessingTest.java +++ b/src/test/java/com/github/joschi/jadconfig/JadConfigLazyProcessingTest.java @@ -4,6 +4,7 @@ import com.github.joschi.jadconfig.response.ProcessingOutcome; import com.github.joschi.jadconfig.response.ProcessingResponse; import com.github.joschi.jadconfig.testbeans.ValidatedConfigurationBean; +import org.junit.Assert; import org.junit.Test; import java.util.HashMap; @@ -13,35 +14,37 @@ public class JadConfigLazyProcessingTest { - private JadConfig jadConfig; - private Repository repository; - - @Test public void testProcess() throws RepositoryException { HashMap properties = new HashMap<>(); - properties.put("test.byte","1"); - properties.put("test.short","2"); - properties.put("test.integer","-3");//negative, smaller than test.short - properties.put("test.integer.port","70000"); //bigger than allowed port - properties.put("test.long","4"); - properties.put("test.string","Test"); - repository = new InMemoryRepository(properties); + properties.put("test.byte", "1"); + properties.put("test.short", "2"); + properties.put("test.integer", "-3");//negative, smaller than test.short + properties.put("test.integer.port", "70000"); //bigger than allowed port + properties.put("test.long", "4"); + properties.put("test.string", "Test"); + Repository repository = new InMemoryRepository(properties); ValidatedConfigurationBean configurationBean = new ValidatedConfigurationBean(); - jadConfig = new JadConfig(repository, configurationBean); - - ProcessingResponse response = jadConfig.processFailingLazily(); - assertFalse(response.isSuccess()); - assertEquals(1, response.getOutcomes().size()); - ProcessingOutcome processingOutcome = response.getOutcomes().get(0); - assertEquals(configurationBean, processingOutcome.getConfigurationBean()); - Map fieldProcessingProblems = processingOutcome.getFieldProcessingProblems(); - assertEquals(2, fieldProcessingProblems.size()); - assertTrue(fieldProcessingProblems.containsKey("test.integer")); - assertTrue(fieldProcessingProblems.containsKey("test.integer.port")); - - Map validationMethodsProblems = processingOutcome.getValidationMethodsProblems(); - assertEquals(1, validationMethodsProblems.size()); - assertTrue(validationMethodsProblems.containsKey("validate")); + JadConfig jadConfig = new JadConfig(repository, configurationBean); + try { + jadConfig.processFailingLazily(); + Assert.fail("Should throw an exception!"); + } catch (LazyValidationException e) { + final ProcessingResponse response = e.getProcessingResponse(); + assertFalse(response.isSuccess()); + assertEquals(1, response.getOutcomes().size()); + ProcessingOutcome processingOutcome = response.getOutcomes().get(0); + assertEquals(configurationBean, processingOutcome.getConfigurationBean()); + Map fieldProcessingProblems = processingOutcome.getFieldProcessingProblems(); + assertEquals(2, fieldProcessingProblems.size()); + assertTrue(fieldProcessingProblems.containsKey("test.integer")); + assertTrue(fieldProcessingProblems.containsKey("test.integer.port")); + + Map validationMethodsProblems = processingOutcome.getValidationMethodsProblems(); + assertEquals(1, validationMethodsProblems.size()); + assertTrue(validationMethodsProblems.containsKey("myCustomValidatorMethod")); + } + + } } diff --git a/src/test/java/com/github/joschi/jadconfig/testbeans/ValidatedConfigurationBean.java b/src/test/java/com/github/joschi/jadconfig/testbeans/ValidatedConfigurationBean.java index dda6046..b13ad10 100644 --- a/src/test/java/com/github/joschi/jadconfig/testbeans/ValidatedConfigurationBean.java +++ b/src/test/java/com/github/joschi/jadconfig/testbeans/ValidatedConfigurationBean.java @@ -7,7 +7,6 @@ import com.github.joschi.jadconfig.validators.NoValidator; import com.github.joschi.jadconfig.validators.PositiveIntegerValidator; import com.github.joschi.jadconfig.validators.PositiveLongValidator; -import com.github.joschi.jadconfig.validators.PositiveSizeValidator; public class ValidatedConfigurationBean { @@ -54,7 +53,7 @@ public long getMyLong() { } @ValidatorMethod - public void validate() throws ValidationException { + public void myCustomValidatorMethod() throws ValidationException { if (!"Test".equals(myString)) { throw new ValidationException("BOOM"); From dae37137e9e70a1c7c92318809437403636065f2 Mon Sep 17 00:00:00 2001 From: Tomas Dvorak Date: Thu, 6 Jun 2024 12:16:29 +0200 Subject: [PATCH 3/3] Code cleanup --- .../github/joschi/jadconfig/JadConfig.java | 35 +++++++++---------- .../jadconfig/LazyValidationException.java | 10 ++---- .../response/ProcessingResponse.java | 14 ++------ 3 files changed, 22 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/github/joschi/jadconfig/JadConfig.java b/src/main/java/com/github/joschi/jadconfig/JadConfig.java index 6bd0a19..54ca7ff 100644 --- a/src/main/java/com/github/joschi/jadconfig/JadConfig.java +++ b/src/main/java/com/github/joschi/jadconfig/JadConfig.java @@ -2,6 +2,7 @@ import com.github.joschi.jadconfig.converters.NoConverter; import com.github.joschi.jadconfig.converters.StringConverter; +import com.github.joschi.jadconfig.response.ProcessingOutcome; import com.github.joschi.jadconfig.response.ProcessingResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,8 +20,8 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.stream.Collectors; -import static com.github.joschi.jadconfig.ReflectionUtils.*; /** * The main class for JadConfig. It's responsible for parsing the configuration bean(s) that contain(s) the annotated @@ -99,8 +100,8 @@ public void process() throws RepositoryException, ValidationException { for (Object configurationBean : configurationBeans) { LOG.debug("Processing configuration bean {}", configurationBean); - processClassFields(configurationBean, getAllFields(configurationBean.getClass())); - invokeValidatorMethods(configurationBean, getAllMethods(configurationBean.getClass())); + processClassFields(configurationBean, ReflectionUtils.getAllFields(configurationBean.getClass())); + invokeValidatorMethods(configurationBean, ReflectionUtils.getAllMethods(configurationBean.getClass())); } } @@ -119,23 +120,21 @@ public void processFailingLazily() throws RepositoryException, LazyValidationExc } ProcessingResponse doProcessFailingLazily() throws RepositoryException { - ProcessingResponse response = new ProcessingResponse(); - for (Repository repository : repositories) { LOG.debug("Opening repository {}", repository); repository.open(); } - for (Object configurationBean : configurationBeans) { - LOG.debug("Processing configuration bean {}", configurationBean); + return configurationBeans.stream() + .peek(bean -> LOG.debug("Processing configuration bean {}", bean)) + .map(this::processBean) + .collect(Collectors.collectingAndThen(Collectors.toList(), ProcessingResponse::new)); + } - response.addOutcome( - configurationBean, - processClassFieldsFailingLazily(configurationBean, getAllFields(configurationBean.getClass())), - invokeValidatorMethodsFailingLazily(configurationBean, getAllMethods(configurationBean.getClass())) - ); - } - return response; + private ProcessingOutcome processBean(Object bean) { + final Map fieldProcessingProblems = processClassFieldsFailingLazily(bean, ReflectionUtils.getAllFields(bean.getClass())); + final Map validationMethodsProblems = invokeValidatorMethodsFailingLazily(bean, ReflectionUtils.getAllMethods(bean.getClass())); + return new ProcessingOutcome(bean, fieldProcessingProblems, validationMethodsProblems); } @@ -146,7 +145,7 @@ private void processClassFields(Object configurationBean, Field[] fields) throws } private Map processClassFieldsFailingLazily(Object configurationBean, Field[] fields) { - Map fieldProcessingProblems = new HashMap<>(); + final Map fieldProcessingProblems = new HashMap<>(); for (Field field : fields) { try { processClassField(configurationBean, field); @@ -281,7 +280,7 @@ private void validateParameter(Collection>> validat private void invokeValidatorMethods(Object configurationBean, Method[] methods) throws ValidationException { try { - invokeMethodsWithAnnotation(configurationBean, ValidatorMethod.class, methods); + ReflectionUtils.invokeMethodsWithAnnotation(configurationBean, ValidatorMethod.class, methods); } catch (InvocationTargetException e) { if (e.getTargetException() instanceof ValidationException) { throw (ValidationException)e.getTargetException(); @@ -294,7 +293,7 @@ private void invokeValidatorMethods(Object configurationBean, Method[] methods) } private Map invokeValidatorMethodsFailingLazily(Object configurationBean, Method[] methods) { - Map problems = new HashMap<>(); + final Map problems = new HashMap<>(); for (Method method : methods) { if (method.isAnnotationPresent(ValidatorMethod.class)) { @@ -364,7 +363,7 @@ public Map dump() { final Map configurationDump = new HashMap(); for (Object configurationBean : configurationBeans) { - for (Field field : getAllFields(configurationBean.getClass())) { + for (Field field : ReflectionUtils.getAllFields(configurationBean.getClass())) { final Parameter parameter = field.getAnnotation(Parameter.class); if (parameter != null) { diff --git a/src/main/java/com/github/joschi/jadconfig/LazyValidationException.java b/src/main/java/com/github/joschi/jadconfig/LazyValidationException.java index 146655b..0acb777 100644 --- a/src/main/java/com/github/joschi/jadconfig/LazyValidationException.java +++ b/src/main/java/com/github/joschi/jadconfig/LazyValidationException.java @@ -21,18 +21,12 @@ private static String toMessage(ProcessingResponse result) { result.getOutcomes().stream() .filter(ProcessingOutcome::hasProblems) .flatMap(processingOutcome -> Stream.concat( - processingOutcome.getFieldProcessingProblems().values().stream().map(e -> toMessage(processingOutcome, e)), - processingOutcome.getValidationMethodsProblems().values().stream().map(e -> toMessage(processingOutcome, e)) + processingOutcome.getFieldProcessingProblems().values().stream().map(Throwable::getMessage), + processingOutcome.getValidationMethodsProblems().values().stream().map(Throwable::getMessage) )).forEach(stringBuilder::add); return String.join("\n", stringBuilder); } - private static String toMessage(ProcessingOutcome processingOutcome, Exception exception) { - // TODO: should we distinct between field processing problem and validation method? - // TODO: should we include class name of the bean or not? - return exception.getMessage(); - } - public ProcessingResponse getProcessingResponse() { return processingResponse; } diff --git a/src/main/java/com/github/joschi/jadconfig/response/ProcessingResponse.java b/src/main/java/com/github/joschi/jadconfig/response/ProcessingResponse.java index f80c47a..e6cbe2e 100644 --- a/src/main/java/com/github/joschi/jadconfig/response/ProcessingResponse.java +++ b/src/main/java/com/github/joschi/jadconfig/response/ProcessingResponse.java @@ -1,21 +1,13 @@ package com.github.joschi.jadconfig.response; -import java.util.LinkedList; import java.util.List; -import java.util.Map; public class ProcessingResponse { - private List outcomes; + private final List outcomes; - public ProcessingResponse() { - this.outcomes = new LinkedList<>(); - } - - public void addOutcome(final Object configurationBean, - final Map fieldProcessingProblems, - final Map validationMethodsProblems) { - outcomes.add(new ProcessingOutcome(configurationBean, fieldProcessingProblems, validationMethodsProblems)); + public ProcessingResponse(List outcomes) { + this.outcomes = outcomes; } public List getOutcomes() {