diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMessageCode.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMessageCode.java index edcdb065cdd9d24f228f0da6ab6ac17146981e8b..f2e5092837376b33c90d73b78b0fbf2ae963c85f 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMessageCode.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMessageCode.java @@ -32,7 +32,8 @@ public enum PostfachMessageCode { PROCESS_FAILED_MESSAGE_CODE("postfachnachricht.server.processing_failed"), SERVER_CONNECTION_FAILED_MESSAGE_CODE("postfachnachricht.server.connection_failed"), - SEND_SUCCESSFUL_MESSAGE_CODE("postfachnachricht.successful"); + SEND_SUCCESSFUL_MESSAGE_CODE("postfachnachricht.successful"), + SEND_FAILED_UNKNOWN_POSTFACH_ID_MESSAGE_CODE("postfachnachricht.server.unknown_postfach_id"); @Getter private String messageCode; diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachService.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachService.java index 6df32e72ef34ffea7b8eeedf601d29d1527cc7d9..3466e0491f951e78de2774b0630b239188844d01 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachService.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachService.java @@ -30,6 +30,9 @@ import java.util.Set; import java.util.function.Predicate; import java.util.stream.Stream; +import jakarta.annotation.PostConstruct; +import jakarta.validation.Valid; + import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; @@ -43,8 +46,6 @@ import de.ozgcloud.nachrichten.postfach.PostfachNachricht.Direction; import de.ozgcloud.nachrichten.postfach.PostfachNachricht.ReplyOption; import de.ozgcloud.nachrichten.postfach.osi.OsiPostfachServerProcessException; import de.ozgcloud.vorgang.callcontext.CurrentUserService; -import jakarta.annotation.PostConstruct; -import jakarta.validation.Valid; import lombok.NonNull; import lombok.extern.log4j.Log4j2; @@ -160,11 +161,10 @@ class PostfachService { publishMailSentEvent(commandId); return buildSendNachrichtResponse(true, PostfachMessageCode.SEND_SUCCESSFUL_MESSAGE_CODE); - } catch (OsiPostfachServerProcessException e) { - return proceedwithWarnException(commandId, e); } catch (PostfachException e) { - return proceedWithErrorException(commandId, e); + logSendMailFailed(commandId, e); + return proceedWithException(commandId, e); } } @@ -184,20 +184,18 @@ class PostfachService { return antragraumService.map(antragraum -> nachricht.toBuilder().mailBody(antragraum.getUserNotificationText()).build()); } - SendPostfachNachrichtResponse proceedwithWarnException(String commandId, OsiPostfachServerProcessException e) { - LOG.warn(e.getMessage(), e); - return proceedWithException(commandId, e); - } - - SendPostfachNachrichtResponse proceedWithErrorException(String commandId, PostfachException e) { - LOG.error(e.getMessage(), e); - return proceedWithException(commandId, e); + void logSendMailFailed(String commandId, PostfachException exception) { + if (exception instanceof OsiPostfachServerProcessException + || exception.getMessageCode() == PostfachMessageCode.SEND_FAILED_UNKNOWN_POSTFACH_ID_MESSAGE_CODE) { + LOG.warn("Failed to send mail with commandId: {}", commandId, exception); + } else { + LOG.error("Failed to send mail with commandId: {}", commandId, exception); + } } private SendPostfachNachrichtResponse proceedWithException(String commandId, PostfachException e) { publishMailSentFailedEvent(commandId, e.getMessage()); return buildSendNachrichtResponse(false, e.getMessageCode()); - } void doSendMail(PostfachNachricht nachricht) { diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdServerException.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdServerException.java index 76b186249315bb80f205b0d9b5cbadd5d7ba9a4a..d88236f3f5995fa8001cb394e47ea6998055937f 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdServerException.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdServerException.java @@ -1,9 +1,32 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ package de.ozgcloud.nachrichten.postfach.bayernid; import de.ozgcloud.nachrichten.postfach.PostfachException; import de.ozgcloud.nachrichten.postfach.PostfachMessageCode; -class BayernIdServerException extends PostfachException { +class BayernIdServerException extends PostfachException { // NOSONAR static final String TABELLE_NUMMER_EMPFANG_ERGEBNISSTATUS = "9006"; private static final String ERROR_MESSAGE_TEMPLATE = TABELLE_NUMMER_EMPFANG_ERGEBNISSTATUS + " / %s / %s / %s"; @@ -16,15 +39,24 @@ class BayernIdServerException extends PostfachException { } public BayernIdServerException(String message, MailSendingResponseStatus mailSendingResponseStatus) { - super(message, PostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE); + super(message, getPostfachMessageCode(mailSendingResponseStatus)); this.mailSendingResponseStatus = mailSendingResponseStatus; } + static PostfachMessageCode getPostfachMessageCode(MailSendingResponseStatus mailSendingResponseStatus) { + return switch (mailSendingResponseStatus) { + case INVALID_POSTKORB_ID -> PostfachMessageCode.SEND_FAILED_UNKNOWN_POSTFACH_ID_MESSAGE_CODE; + case SUCCESS -> PostfachMessageCode.SEND_SUCCESSFUL_MESSAGE_CODE; + default -> PostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE; + }; + } + @Override public String getMessage() { if (mailSendingResponseStatus == null) { return super.getMessage(); } - return ERROR_MESSAGE_TEMPLATE.formatted(mailSendingResponseStatus.getSchluessel(), mailSendingResponseStatus.getMessage(), super.getMessage()); + return ERROR_MESSAGE_TEMPLATE.formatted(mailSendingResponseStatus.getSchluessel(), mailSendingResponseStatus.getMessage(), + super.getMessage()); } } diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachServiceTest.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachServiceTest.java index 5b5f2a99fe19a2b6f47e676012cfe59d6f2051dc..7a88f0f81a573698705430c9587144ef4180751d 100644 --- a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachServiceTest.java +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachServiceTest.java @@ -33,7 +33,6 @@ import java.util.Optional; import java.util.UUID; import java.util.stream.Stream; -import org.apache.logging.log4j.Logger; import org.bson.types.ObjectId; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -58,16 +57,17 @@ import de.ozgcloud.nachrichten.postfach.PostfachNachricht.Direction; import de.ozgcloud.nachrichten.postfach.PostfachNachricht.ReplyOption; import de.ozgcloud.nachrichten.postfach.osi.MessageAttachmentService; import de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory; -import de.ozgcloud.nachrichten.postfach.osi.OsiPostfachServerProcessException; import de.ozgcloud.nachrichten.postfach.osi.OsiPostfachServerProcessExceptionTestFactory; import de.ozgcloud.vorgang.callcontext.CallContextUserTestFactory; import de.ozgcloud.vorgang.callcontext.CurrentUserService; import nl.altindag.log.LogCaptor; +import nl.altindag.log.model.LogEvent; class PostfachServiceTest { static final String COMMAND_ID = UUID.randomUUID().toString(); static final String USER_ID = UUID.randomUUID().toString(); + @Spy @InjectMocks private PostfachService service; @@ -590,12 +590,13 @@ class PostfachServiceTest { class TestOnOsiPostfachException { private final static String MESSAGE = "Osi Postfach throws an exception."; + private static final PostfachException POSTFACH_EXCEPTION = new PostfachException(MESSAGE, + PostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE); @BeforeEach void mockService() { when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE); - doThrow(new PostfachException(MESSAGE, PostfachMessageCode.SEND_SUCCESSFUL_MESSAGE_CODE)).when(postfachRemoteService) - .sendMessage(any()); + doThrow(POSTFACH_EXCEPTION).when(postfachRemoteService).sendMessage(any()); } @Test @@ -608,14 +609,10 @@ class PostfachServiceTest { } @Test - void shouldLogError() { - var logCaptor = LogCaptor.forClass(PostfachService.class); - + void shouldCallLogSendMailFailed() { service.handleSendMail(COMMAND_ID, mail); - verify(service).proceedWithErrorException(eq(COMMAND_ID), any(PostfachException.class)); - assertThat(logCaptor.getLogEvents().get(0).getLevel()).isEqualTo(LogLevel.ERROR.name()); - assertThat(logCaptor.getLogEvents().get(0).getMessage()).startsWith(MESSAGE); + verify(service).logSendMailFailed(COMMAND_ID, POSTFACH_EXCEPTION); } @Test @@ -623,7 +620,7 @@ class PostfachServiceTest { var response = service.handleSendMail(COMMAND_ID, mail); assertThat(response.isSentSuccessful()).isFalse(); - assertThat(response.getMessageCode()).isEqualTo(PostfachMessageCode.SEND_SUCCESSFUL_MESSAGE_CODE); + assertThat(response.getMessageCode()).isEqualTo(PostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE); } } @@ -633,9 +630,6 @@ class PostfachServiceTest { private final static String MESSAGE = "Postfach server returned false"; - @Mock - private Logger logger; - @BeforeEach void mockService() { doThrow(OsiPostfachServerProcessExceptionTestFactory.create()).when(postfachRemoteService).sendMessage(any()); @@ -651,17 +645,6 @@ class PostfachServiceTest { assertThat(eventFailedCaptor.getValue().getErrorMessage()).startsWith(MESSAGE); } - @Test - void shouldLogWarning() { - var logCaptor = LogCaptor.forClass(PostfachService.class); - - service.handleSendMail(COMMAND_ID, mail); - - verify(service).proceedwithWarnException(eq(COMMAND_ID), any(OsiPostfachServerProcessException.class)); - assertThat(logCaptor.getLogEvents().get(0).getLevel()).isEqualTo(LogLevel.WARN.name()); - assertThat(logCaptor.getLogEvents().get(0).getMessage()).startsWith(MESSAGE); - } - @Test void shouldReturnResponse() { var response = service.handleSendMail(COMMAND_ID, mail); @@ -671,6 +654,47 @@ class PostfachServiceTest { } } } + } + + @Nested + class TestLogSendMailFailed { + + @DisplayName("should log warning on OsiPostfachServerProcessException") + @Test + void shouldLogWarningWhenOsiException() { + try (var logCaptor = LogCaptor.forClass(PostfachService.class)) { + var exception = OsiPostfachServerProcessExceptionTestFactory.create(); + + service.logSendMailFailed(COMMAND_ID, exception); + + assertThat(logCaptor.getLogEvents()).hasSize(1).first().extracting(LogEvent::getLevel).isEqualTo(LogLevel.WARN.name()); + } + } + + @DisplayName("should log warning when error code is unknown postfach id") + @Test + void shouldLogWarningWhenWrongPostfachId() { + try (var logCaptor = LogCaptor.forClass(PostfachService.class)) { + var exception = new PostfachException("Test", PostfachMessageCode.SEND_FAILED_UNKNOWN_POSTFACH_ID_MESSAGE_CODE); + + service.logSendMailFailed(COMMAND_ID, exception); + + assertThat(logCaptor.getLogEvents()).hasSize(1).first().extracting(LogEvent::getLevel).isEqualTo(LogLevel.WARN.name()); + } + } + + @DisplayName("should log error") + @ParameterizedTest(name = "when error code is {0}") + @EnumSource(value = PostfachMessageCode.class, names = { "SEND_FAILED_UNKNOWN_POSTFACH_ID_MESSAGE_CODE" }, mode = EnumSource.Mode.EXCLUDE) + void shouldLogError(PostfachMessageCode messageCode) { + try (var logCaptor = LogCaptor.forClass(PostfachService.class)) { + var exception = new PostfachException("Test", messageCode); + + service.logSendMailFailed(COMMAND_ID, exception); + + assertThat(logCaptor.getLogEvents().get(0).getLevel()).isEqualTo(LogLevel.ERROR.name()); + } + } } @@ -799,7 +823,7 @@ class PostfachServiceTest { @Nested class TestSavingMukAnswer { private final String refId = ObjectId.get().toHexString(); - private PostfachNachricht answer = PostfachNachrichtTestFactory.createBuilder().vorgangId(null).referencedNachricht(refId).build(); + private final PostfachNachricht answer = PostfachNachrichtTestFactory.createBuilder().vorgangId(null).referencedNachricht(refId).build(); @Test void shouldIdentifyAsAnswer() { diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdServerExceptionTest.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdServerExceptionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d603e63d5b70e295a7a9268ed671f1e3ee228e60 --- /dev/null +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdServerExceptionTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.nachrichten.postfach.bayernid; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import de.ozgcloud.nachrichten.postfach.PostfachMessageCode; + +class BayernIdServerExceptionTest { + + @Nested + class TestGetPostfachMessageCode { + + @Test + void shouldReturnSendFailedUnknownPostfachId() { + var result = BayernIdServerException.getPostfachMessageCode(MailSendingResponseStatus.INVALID_POSTKORB_ID); + + assertThat(result).isEqualTo(PostfachMessageCode.SEND_FAILED_UNKNOWN_POSTFACH_ID_MESSAGE_CODE); + } + + @Test + void shouldReturnSendingSuccessful() { + var result = BayernIdServerException.getPostfachMessageCode(MailSendingResponseStatus.SUCCESS); + + assertThat(result).isEqualTo(PostfachMessageCode.SEND_SUCCESSFUL_MESSAGE_CODE); + } + + @DisplayName("should return process failed") + @ParameterizedTest(name = "for {0}") + @EnumSource(value = MailSendingResponseStatus.class, names = { "INVALID_POSTKORB_ID", "SUCCESS" }, mode = EnumSource.Mode.EXCLUDE) + void shouldReturnProcessFailed(MailSendingResponseStatus status) { + var result = BayernIdServerException.getPostfachMessageCode(status); + + assertThat(result).isEqualTo(PostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE); + } + } +} \ No newline at end of file