diff --git a/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/util/services/IMDGMessageResolver.java b/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/util/services/IMDGMessageResolver.java index 4c3807bff..3da17146d 100644 --- a/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/util/services/IMDGMessageResolver.java +++ b/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/util/services/IMDGMessageResolver.java @@ -10,6 +10,7 @@ import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.enumeration.IMessageResolver; import java.util.Arrays; +import java.util.MissingFormatArgumentException; import java.util.function.Supplier; /** @@ -35,7 +36,22 @@ public class IMDGMessageResolver implements IMessageResolver { return simplFormatter.get(); } String textTemplate = errId + " " + errorDictionary.getName(); - return String.format(textTemplate, errMsg.getArgs()); + try { + return String.format(textTemplate, errMsg.getArgs()); + } catch (MissingFormatArgumentException errFormatting) { // MissingFormatArgumentException + int argExpected = 0; + int i = 0, li = -1; + while ((i = textTemplate.indexOf("%", i)) >= 0 && i != li) { + argExpected++; + li = i; + i++; + } + log.warn("Error dictionary {} text \"{}\" contains {} argument position, but message contains only: {}", + errId, textTemplate, argExpected, errMsg.getArgs().length); + Object[] arg = Arrays.copyOf(errMsg.getArgs(), Math.max(errMsg.getArgs().length, argExpected)); + for (i = errMsg.getArgs().length; i < arg.length; i++) arg[i] = " "; + return String.format(textTemplate, arg); + } } catch (Exception errFormatting) { // MissingFormatArgumentException log.warn("Error in message resolver for error {} id {}. Format error: {}", errMsg.getSubject(), errMsg.getSubject().getId(), errFormatting); return simplFormatter.get(); diff --git a/clearing-parent/clearing-validation/src/test/java/ru/spcex/clearing/util/services/IMDGMessageResolverTest.java b/clearing-parent/clearing-validation/src/test/java/ru/spcex/clearing/util/services/IMDGMessageResolverTest.java index 37dd1196b..fddf0fa74 100644 --- a/clearing-parent/clearing-validation/src/test/java/ru/spcex/clearing/util/services/IMDGMessageResolverTest.java +++ b/clearing-parent/clearing-validation/src/test/java/ru/spcex/clearing/util/services/IMDGMessageResolverTest.java @@ -16,15 +16,26 @@ class IMDGMessageResolverTest { @Test void resolve() { ImdgProvider imdgProvider = Mockito.mock(ImdgProvider.class); - Imdg errorCodeDictionary = Mockito.mock(Imdg.class); - ErrorCodeDictionary error1Dict = new ErrorCodeDictionary(); - error1Dict.setId(1L); - error1Dict.setCode("TEST"); - error1Dict.setName("Error 1 test. Two arg %s, %s."); - Mockito.when(errorCodeDictionary.getSingleObjectByID(1L)).thenReturn(error1Dict); - Mockito.when(imdgProvider.getImdg(IMDGDistributedNames.Map_ErrorCodeDictionary, ErrorCodeDictionary.class)) - .thenReturn(errorCodeDictionary); - + { + Imdg errorCodeDictionary = Mockito.mock(Imdg.class); + ErrorCodeDictionary error1Dict = new ErrorCodeDictionary(); + error1Dict.setId(1L); + error1Dict.setCode("TEST"); + error1Dict.setName("Error 1 test. Two arg %s, %s."); + Mockito.when(errorCodeDictionary.getSingleObjectByID(1L)).thenReturn(error1Dict); + ErrorCodeDictionary error2Dict = new ErrorCodeDictionary(); + error2Dict.setId(2L); + error2Dict.setCode("TEST"); + error2Dict.setName("Error 2 test. Two ar \\%QW."); + Mockito.when(errorCodeDictionary.getSingleObjectByID(2L)).thenReturn(error2Dict); + ErrorCodeDictionary error3Dict = new ErrorCodeDictionary(); + error3Dict.setId(3L); + error3Dict.setCode("TEST"); + error3Dict.setName("Error 3 test only."); + Mockito.when(errorCodeDictionary.getSingleObjectByID(3L)).thenReturn(error3Dict); + Mockito.when(imdgProvider.getImdg(IMDGDistributedNames.Map_ErrorCodeDictionary, ErrorCodeDictionary.class)) + .thenReturn(errorCodeDictionary); + } IMDGMessageResolver resolver = new IMDGMessageResolver(imdgProvider); @@ -39,20 +50,32 @@ class IMDGMessageResolverTest { } { String text = resolver.resolve(new EnumMessage(err1, "one only this")); - //assertEquals("Error 1 test. Two arg one only this, %s.", text); + assertEquals("1 Error 1 test. Two arg one only this, .", text); // java.util.MissingFormatArgumentException: Format specifier '%s' - assertEquals("(1) args [one only this]", text); +// assertEquals("(1) args [one only this]", text); } { String text = resolver.resolve(new EnumMessage(err1)); - //assertEquals("Error 1 test. Two arg %s, %s.", text); + assertEquals("1 Error 1 test. Two arg , .", text); // java.util.MissingFormatArgumentException: Format specifier '%s' - assertEquals("(1) args []", text); +// assertEquals("(1) args []", text); + } + { + String text = resolver.resolve(new EnumMessage(ClearingErrorInternalTest.TestError2, "text")); + // java.util.UnknownFormatConversionException: Conversion = 'Q' + assertEquals("(2) args [text]", text); + } + { + String text = resolver.resolve(new EnumMessage(ClearingErrorInternalTest.TestError3, "text")); + assertEquals("3 Error 3 test only.", text); + + text = resolver.resolve(new EnumMessage(ClearingErrorInternalTest.TestError3)); + assertEquals("3 Error 3 test only.", text); } } - static enum ClearingErrorInternalTest implements IErrorEnumId { // see ClearingErrorInternal - TestError(1L); + enum ClearingErrorInternalTest implements IErrorEnumId { // see ClearingErrorInternal + TestError(1L), TestError2(2L), TestError3(3L); private final Long id; ClearingErrorInternalTest(Long id) {