From 25d68c8900c2cc791f03ea3db173955ca237fd55 Mon Sep 17 00:00:00 2001 From: Christof Rabensteiner Date: Fri, 12 Jul 2019 15:40:05 +0200 Subject: Allow App To Choose Between MsgResponse Sinks - MZS Schema Change: Add "MsgResponseSinks" element to mzs:DeliveryRequest/Config that allows sender to configure how MsgResponses should be archived. - ConfigUtil: Interpret MsgResponseSink parameters from Spring Environment and merge with ConfigType. - MsgResponseBackend: Send responses to sinks according to MsgResponseSinks in Config - application.yaml: Add MsgResponseSinks parameter to configuration. - Uncouple Sink implementations from java.util.function.Function, because the sink interfaces are going to differ and there is no need to unite them under one interface. - Add and test LogResponseSink, which logs responses to it's logger. - MsgResponse: Add JAXB getter for response. Reason: Can be passed to marshaller. --- .../at/gv/egiz/moazs/backend/LogResponseSink.java | 44 ++++++++++++++++++++++ .../gv/egiz/moazs/backend/MsgResponseBackend.java | 41 ++++++++++++++++---- .../egiz/moazs/backend/SaveResponseToFileSink.java | 14 +++++-- 3 files changed, 88 insertions(+), 11 deletions(-) create mode 100644 src/main/java/at/gv/egiz/moazs/backend/LogResponseSink.java (limited to 'src/main/java/at/gv/egiz/moazs/backend') diff --git a/src/main/java/at/gv/egiz/moazs/backend/LogResponseSink.java b/src/main/java/at/gv/egiz/moazs/backend/LogResponseSink.java new file mode 100644 index 0000000..d419944 --- /dev/null +++ b/src/main/java/at/gv/egiz/moazs/backend/LogResponseSink.java @@ -0,0 +1,44 @@ +package at.gv.egiz.moazs.backend; + +import at.gv.egiz.moazs.scheme.Marshaller; +import at.gv.egiz.moazs.scheme.MsgResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.concurrent.CompletableFuture; + +import static java.util.concurrent.CompletableFuture.completedFuture; + +@Component +public class LogResponseSink { + + private static final Logger log = LoggerFactory.getLogger(LogResponseSink.class); + private static final String LOG_LEVEL_WARN_MESSAGE = "Will not log response because INFO level is disabled."; + + private final Marshaller msgMarshaller; + + public LogResponseSink(Marshaller msgMarshaller) { + this.msgMarshaller = msgMarshaller; + } + + /** + * Log response to class logger at level=INFO. + * + * @param msgResponse + * @return + */ + public CompletableFuture log(MsgResponse msgResponse) { + + if(log.isInfoEnabled()) { + var builder = new StringBuilder("Received the following Message: \n"); + builder.append(msgMarshaller.marshallXml(msgResponse.getResponseAsJAXBElement())); + log.info(builder.toString()); + } else { + log.warn(LOG_LEVEL_WARN_MESSAGE); + } + + return completedFuture(null); + + } +} diff --git a/src/main/java/at/gv/egiz/moazs/backend/MsgResponseBackend.java b/src/main/java/at/gv/egiz/moazs/backend/MsgResponseBackend.java index 414c2dc..1b17f34 100644 --- a/src/main/java/at/gv/egiz/moazs/backend/MsgResponseBackend.java +++ b/src/main/java/at/gv/egiz/moazs/backend/MsgResponseBackend.java @@ -4,14 +4,13 @@ import at.gv.egiz.moazs.MoaZSException; import at.gv.egiz.moazs.repository.DeliveryRepository; import at.gv.egiz.moazs.scheme.MsgResponse; import at.gv.egiz.moazs.service.MsgService; +import at.gv.zustellung.app2mzs.xsd.MsgResponseSinksType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; -import java.util.function.Function; import static at.gv.egiz.moazs.MoaZSException.moaZSExceptionBuilder; import static java.lang.String.format; @@ -27,29 +26,38 @@ public class MsgResponseBackend implements Consumer { private final DeliveryRepository repository; private final Consumer signatureVerifier; - private final Function> sink; + private final SaveResponseToFileSink saveResponseToFileSink; + private final LogResponseSink logResponseSink; @Autowired public MsgResponseBackend(DeliveryRepository repository, Consumer signatureVerifier, - Function> sink) { + SaveResponseToFileSink saveResponseToFileSink, + LogResponseSink logResponseSink) { this.repository = repository; this.signatureVerifier = signatureVerifier; - this.sink = sink; + this.saveResponseToFileSink = saveResponseToFileSink; + this.logResponseSink = logResponseSink; } /** * Performs all {@code MsgResponse}'s Back-End Tasks, such as verifying * its signature and archiving the response. * + * Note: When the signature verification fails, this method will not archive + * the original response (the one that was received from msg) to the sink, + * but an error message. + * * @param responseID refers to MsgResponse Object. */ @Override public void accept(String responseID) { - supplyAsync(() -> verify(responseID)).thenAcceptAsync(sink::apply); + + supplyAsync(() -> verify(responseID)) + .thenAcceptAsync(msgResponse -> applySinks(msgResponse)); } - public MsgResponse verify(String responseID) { + private MsgResponse verify(String responseID) { var response = repository.retrieveResponse(responseID).get(); var builder = moaZSExceptionBuilder().withAllParametersInAnswer(response.getAnswer()); @@ -72,4 +80,23 @@ public class MsgResponseBackend implements Consumer { } + private void applySinks(MsgResponse msgResponse) { + + var sinkParams = getSinkParams(msgResponse); + + if (sinkParams.isSafeResponseToFile()) { + supplyAsync(() -> saveResponseToFileSink.save(msgResponse)); + } + + if (sinkParams.isLogResponse()) { + supplyAsync(() -> logResponseSink.log(msgResponse)); + } + } + + private MsgResponseSinksType getSinkParams(MsgResponse msgResponse) { + var appDeliveryID = msgResponse.getAppDeliveryID(); + var request = repository.retrieveDeliveryRequest(appDeliveryID).get(); + return request.getConfig().getMsgResponseSinks(); + } + } diff --git a/src/main/java/at/gv/egiz/moazs/backend/SaveResponseToFileSink.java b/src/main/java/at/gv/egiz/moazs/backend/SaveResponseToFileSink.java index 02771a9..7da76ef 100644 --- a/src/main/java/at/gv/egiz/moazs/backend/SaveResponseToFileSink.java +++ b/src/main/java/at/gv/egiz/moazs/backend/SaveResponseToFileSink.java @@ -15,7 +15,6 @@ import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.CompletableFuture; -import java.util.function.Function; import static at.gv.egiz.moazs.MoaZSException.moaZSException; import static java.lang.String.format; @@ -23,10 +22,11 @@ import static java.util.concurrent.CompletableFuture.allOf; import static java.util.concurrent.CompletableFuture.supplyAsync; @Component -public class SaveResponseToFileSink implements Function> { +public class SaveResponseToFileSink { private static final Logger log = LoggerFactory.getLogger(SaveResponseToFileSink.class); private static final String SAVING_FAILED_MSG = "Could not save response with AppDeliveryId=%s."; + private static final String SAVE_RESPONSE_MSG = "Saving response to {}..." ; private final SimpleDateFormat isoFormatter; private final Marshaller msgMarshaller; @@ -41,8 +41,13 @@ public class SaveResponseToFileSink implements Function apply(MsgResponse response) { + /** + * Save response and it's binary version to the file system. + * + * @param response + * @return Future that completes when both responses have been written to the file system. + */ + public CompletableFuture save(MsgResponse response) { var responseID = response.getResponseID(); @@ -79,6 +84,7 @@ public class SaveResponseToFileSink implements Function