diff options
author | Christof Rabensteiner <christof.rabensteiner@iaik.tugraz.at> | 2019-07-17 13:17:21 +0200 |
---|---|---|
committer | Christof Rabensteiner <christof.rabensteiner@iaik.tugraz.at> | 2019-07-17 13:27:40 +0200 |
commit | f2e1263702901581512131ea587fad7a2ba45baa (patch) | |
tree | b92a38f758fecb039de184963116017921d2e314 /src | |
parent | 896195cc9b287a3f41008cc85997b9c2209120b8 (diff) | |
download | moa-zs-f2e1263702901581512131ea587fad7a2ba45baa.tar.gz moa-zs-f2e1263702901581512131ea587fad7a2ba45baa.tar.bz2 moa-zs-f2e1263702901581512131ea587fad7a2ba45baa.zip |
Put MoaZSException on Diet & Handle Edge Cases
Reason: MoaZSException (and: its builder) were used to collect
intermediary results while stepping through the delivery request
backend. These results were needed to generate meaningful responses
towards the sender application in case of error. However, the builder
sprawled over too many interfaces (e.g. DeliveryRequestBackend and
TNVZHelper) and it became difficult to understand from where
intermediary results originated.
Solution: Put MoaZSException on diet:
- Remove all DeliveryAnswer fields from MoaZSException and refactor
code base to ensure that the removed fields get sourced by other
means.
- Remove Builder since amount of parameters is manageable.
Refactor DeliveryRequestBackend:
- Instead of passing down the builder and using MoaZSException as the
only source for intermediary results, we collect available results
at the outermost stack frame (DeliveryRequestBackend.accept) and
only retrieve results via exception if those results appear
somewhere down the stack frame (E.g. PredviceNoteSent). We collect
available results with the "fallbackAnswerBuilder" and switch to the
msg client response, once received.
Refactor MsgResponseBackend:
- Handle cases (response missing, binary response missing) properly.
- Integrate changes from MsgResponse.generateError()
Refactor TVNZHelper:
- Remove MoaZSExceptionBuilder from all interfaces.
Refactor MsgResponse.generateError:
- Change interface such that it's more intuitive.
- Implement NotificationResponse.generateError.
- Implement RequestStatusResponse.generateError.
Others:
- Replace all invocations against MoaZSException.Builder.
Diffstat (limited to 'src')
15 files changed, 182 insertions, 261 deletions
diff --git a/src/main/java/at/gv/egiz/moazs/MoaZSException.java b/src/main/java/at/gv/egiz/moazs/MoaZSException.java index dbb2894..499dc14 100644 --- a/src/main/java/at/gv/egiz/moazs/MoaZSException.java +++ b/src/main/java/at/gv/egiz/moazs/MoaZSException.java @@ -1,167 +1,51 @@ package at.gv.egiz.moazs; -import at.gv.zustellung.msg.xsd.DeliveryAnswerType; import at.gv.zustellung.msg.xsd.PreAdviceNoteSentType; -import at.gv.zustellung.tnvz.xsd.PersonResultType; import org.springframework.lang.Nullable; public class MoaZSException extends RuntimeException { public static final String ERROR_MZS_MIMETYPE_MISSMATCH = "8001"; public static final String ERROR_MZS_NO_TNVZ_PERSON_QUERY_RESULTS = "8002"; + public static final String ERROR_MZS_BINARY_RESPONSE_MISSING = "8003"; + public static final String ERROR_MZS_RESPONSE_MISSING = "8004"; public static final String ERROR_MOASP_SIGNATURE_INVALID = "7001"; - @Nullable - private final String errorCode; - @Nullable - private final PreAdviceNoteSentType preAdviceNoteSent; - @Nullable - private final String deliverySystem; - @Nullable - private final String gz; - @Nullable - private final String zsDeliveryID; - @Nullable - private final String appDeliveryID; + @Nullable private final String code; + @Nullable private final PreAdviceNoteSentType preAdviceNoteSent; - private MoaZSException(Builder builder) { - super(builder.message, builder.cause); - this.errorCode = builder.errorCode; - this.preAdviceNoteSent = builder.preAdviceNoteSent; - this.deliverySystem = builder.deliverySystem; - this.gz = builder.gz; - this.zsDeliveryID = builder.zsDeliveryID; - this.appDeliveryID = builder.appDeliveryID; + private MoaZSException(String message, Throwable cause, @Nullable String code, @Nullable PreAdviceNoteSentType preAdviceNoteSent) { + super(message, cause); + this.code = code; + this.preAdviceNoteSent = preAdviceNoteSent; } - public static MoaZSException moaZSException(String message, Throwable cause) { - return moaZSExceptionBuilder(message).withCause(cause).build(); - } - - public static MoaZSException moaZSException(String formatString, Object... objects) { - return moaZSExceptionBuilder(formatString, objects).build(); - } - - public static MoaZSException moaZSException(String message) { - return moaZSExceptionBuilder(message).build(); - } - - public static Builder moaZSExceptionBuilder(String formatString, Object... objects) { - return new Builder().withMessage(String.format(formatString, objects)); + @Nullable public String getCode() { + return code; } - public static Builder moaZSExceptionBuilder(String message) { - return new Builder().withMessage(message); - } - - public static Builder moaZSExceptionBuilder() { - return new Builder(); - } - - @Nullable - public String getErrorCode() { - return errorCode; - } - - @Nullable - public PreAdviceNoteSentType getPreAdviceNoteSent() { + @Nullable public PreAdviceNoteSentType getPreAdviceNoteSent() { return preAdviceNoteSent; } - @Nullable - public String getDeliverySystem() { - return deliverySystem; + public static MoaZSException moaZSException(String message, Throwable cause) { + return new MoaZSException(message, cause, null, null); } - @Nullable - public String getGz() { - return gz; + public static MoaZSException moaZSException(String message) { + return new MoaZSException(message, null, null, null); } - @Nullable - public String getZsDeliveryID() { - return zsDeliveryID; + public static MoaZSException moaZSException(String message, String code) { + return new MoaZSException(message, null, code, null); } - @Nullable - public String getAppDeliveryID() { - return appDeliveryID; + public static MoaZSException moaZSException(String message, String code, Throwable cause) { + return new MoaZSException(message, cause, code, null); } - public static class Builder { - - private String message; - private Throwable cause; - private String errorCode; - private PreAdviceNoteSentType preAdviceNoteSent; - private String deliverySystem; - private String gz; - private String zsDeliveryID; - private String appDeliveryID; - - private Builder() { - } - - public Builder(MoaZSException exception){ - this.message = exception.getMessage(); - this.cause = exception.getCause(); - this.errorCode = exception.getErrorCode(); - this.preAdviceNoteSent = exception.getPreAdviceNoteSent(); - this.deliverySystem = exception.getDeliverySystem(); - this.gz = exception.getGz(); - this.zsDeliveryID = exception.getZsDeliveryID(); - this.appDeliveryID = exception.getAppDeliveryID(); - } - - public Builder withMessage(String message) { - this.message = message; - return this; - } - - public Builder withMessage(String formatString, Object... objects ) { - this.message = String.format(formatString, objects); - return this; - } - - public Builder withCause(Throwable cause) { - this.cause = cause; - return this; - } - - public Builder withErrorCode(String errorCode) { - this.errorCode = errorCode; - return this; - } - - public Builder withPreAdviceNoteSent(PersonResultType personResult) { - if (personResult.getError() != null) { - this.preAdviceNoteSent = personResult.getError().getPreAdviceNoteSent(); - } - return this; - } - - public Builder withDeliverySystem(at.gv.zustellung.app2mzs.xsd.DeliveryRequestType mzsRequest) { - this.deliverySystem = mzsRequest.getConfig().getMSGClient().getURL(); - return this; - } - - - public Builder withAllParametersInAnswer(DeliveryAnswerType answer) { - this.deliverySystem = answer.getDeliverySystem(); - this.gz = answer.getGZ(); - this.zsDeliveryID = answer.getZSDeliveryID(); - this.appDeliveryID = answer.getAppDeliveryID(); - return this; - } - - public Builder withAppDeliveryID(String appDeliveryID) { - this.appDeliveryID = appDeliveryID; - return this; - } - - public MoaZSException build() { - return new MoaZSException(this); - } + public static MoaZSException moaZSException(String message, String code, PreAdviceNoteSentType preAdviceNoteSent) { + return new MoaZSException(message, null, code, preAdviceNoteSent); } } diff --git a/src/main/java/at/gv/egiz/moazs/backend/DeliveryRequestBackend.java b/src/main/java/at/gv/egiz/moazs/backend/DeliveryRequestBackend.java index 06eba80..6a1e0fd 100644 --- a/src/main/java/at/gv/egiz/moazs/backend/DeliveryRequestBackend.java +++ b/src/main/java/at/gv/egiz/moazs/backend/DeliveryRequestBackend.java @@ -9,6 +9,7 @@ import at.gv.egiz.moazs.scheme.Mzs2MsgConverter; import at.gv.egiz.moazs.scheme.RequestStatusResponse; import at.gv.zustellung.app2mzs.xsd.DeliveryRequestType; import at.gv.zustellung.msg.xsd.App2ZusePort; +import at.gv.zustellung.msg.xsd.DeliveryRequestStatusType; import at.gv.zustellung.tnvz.xsd.TNVZServicePort; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; @@ -17,8 +18,10 @@ import org.springframework.stereotype.Component; import java.util.function.Consumer; -import static at.gv.egiz.moazs.MoaZSException.moaZSExceptionBuilder; -import static at.gv.egiz.moazs.scheme.RequestStatusResponse.generateErrorFromException; +import static at.gv.egiz.moazs.scheme.RequestStatusResponse.*; +import static at.gv.egiz.moazs.scheme.RequestStatusResponse.generateError; +import static at.gv.zustellung.msg.xsd.DeliveryRequestStatusType.Error.errorBuilder; +import static at.gv.zustellung.msg.xsd.DeliveryRequestStatusType.deliveryRequestStatusTypeBuilder; import static java.lang.String.format; @Component @@ -28,6 +31,10 @@ public class DeliveryRequestBackend implements Consumer<String> { private static final Logger log = Logger.getLogger(DeliveryRequestBackend.class); private static final String MZS_PIPELINE_ERROR_MSG = "An error occured while processing the DeliveryRequest with AppDeliveryID=%s. "; + private static final String DELIVERY_REQUEST_MISSING_ERROR_MSG = + "DeliveryRequest for AppDeliveryID=%s is not in repository. " ; + private static final String BINARY_RESPONSE_MISSING_ERROR_MSG = + "Binary DeliveryRequestStatus for AppDeliveryID=%s is not in repository. " ; private final DeliveryRepository repository; private final TnvzHelper tnvzHelper; @@ -60,49 +67,53 @@ public class DeliveryRequestBackend implements Consumer<String> { @Override public void accept(String appDeliveryID) { - var exceptionBuilder = moaZSExceptionBuilder(); + DeliveryRequestStatusType status = null; + var fallbackAnswerBuilder = errorBuilder().withAppDeliveryID(appDeliveryID); try { - var mzsRequest = repository.retrieveDeliveryRequest(appDeliveryID).orElseThrow(); - exceptionBuilder.withDeliverySystem(mzsRequest); - - at.gv.zustellung.msg.xsd.DeliveryRequestType msgRequest = buildMsgRequest(mzsRequest, exceptionBuilder); + var mzsRequest = repository.retrieveDeliveryRequest(appDeliveryID).orElseThrow( + () -> MoaZSException.moaZSException(format(DELIVERY_REQUEST_MISSING_ERROR_MSG, appDeliveryID))); + fallbackAnswerBuilder.withDeliverySystem(mzsRequest.getConfig().getMSGClient().getURL()); + var msgRequest = buildMsgRequest(mzsRequest); var msgClientParams = mzsRequest.getConfig().getMSGClient(); App2ZusePort client = clientFactory.create(msgClientParams, App2ZusePort.class); - var status = client.delivery(msgRequest); + status = client.delivery(msgRequest); var response = new RequestStatusResponse(status); - exceptionBuilder.withAllParametersInAnswer(response.getAnswer()); - verifySignedStatus(response.getResponseID(), appDeliveryID, exceptionBuilder); + verifySignedStatus(response.getResponseID(), appDeliveryID); repository.store(response); } catch (MoaZSException exception) { log.error(format(MZS_PIPELINE_ERROR_MSG, appDeliveryID), exception); - var errorResponse = generateErrorFromException(exception); - repository.store(errorResponse); + + var templateAnswer = (status == null) + ? fallbackAnswerBuilder.build() + : getAnswer(status); + + var errorStatus = generateError(exception, templateAnswer); + repository.store(errorStatus); } } - private void verifySignedStatus(String responseID, String appDeliveryID, MoaZSException.Builder exceptionBuilder) throws MoaZSException { + private void verifySignedStatus(String responseID, String appDeliveryID) throws MoaZSException { try { - var signedStatus = repository.retrieveBinaryResponse(responseID).get(); + var signedStatus = repository.retrieveBinaryResponse(responseID).orElseThrow( + () -> MoaZSException.moaZSException(format(BINARY_RESPONSE_MISSING_ERROR_MSG, responseID))); signatureVerifier.accept(signedStatus); } catch (MoaZSException ex) { - throw exceptionBuilder.withMessage(format(MsgResponseBackend.MOASP_SIGNATURE_INVALID_ERROR_MSG, appDeliveryID)) - .withErrorCode(MoaZSException.ERROR_MOASP_SIGNATURE_INVALID) - .withCause(ex) - .build(); + var message = format(MsgResponseBackend.MOASP_SIGNATURE_INVALID_ERROR_MSG, appDeliveryID); + var code = MoaZSException.ERROR_MOASP_SIGNATURE_INVALID; + throw MoaZSException.moaZSException(message, code, ex); } } - private at.gv.zustellung.msg.xsd.DeliveryRequestType buildMsgRequest(DeliveryRequestType mzsRequest, - MoaZSException.Builder exceptionBuilder) throws MoaZSException { + private at.gv.zustellung.msg.xsd.DeliveryRequestType buildMsgRequest(DeliveryRequestType mzsRequest) throws MoaZSException { if (mzsRequest.getConfig().isPerformQueryPersonRequest()) { var tnvzClientParams = mzsRequest.getConfig().getTNVZClient(); TNVZServicePort tvnzPort = clientFactory.create(tnvzClientParams, TNVZServicePort.class); - var identification = tnvzHelper.performQueryPersonRequest(mzsRequest, tvnzPort, exceptionBuilder); + var identification = tnvzHelper.performQueryPersonRequest(mzsRequest, tvnzPort); return converter.convert(mzsRequest, identification); } else { return converter.convert(mzsRequest); 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 9e3cd36..8649a32 100644 --- a/src/main/java/at/gv/egiz/moazs/backend/MsgResponseBackend.java +++ b/src/main/java/at/gv/egiz/moazs/backend/MsgResponseBackend.java @@ -12,7 +12,7 @@ import org.springframework.stereotype.Component; import java.util.function.Consumer; -import static at.gv.egiz.moazs.MoaZSException.moaZSExceptionBuilder; +import static at.gv.egiz.moazs.MoaZSException.*; import static java.lang.String.format; import static java.util.concurrent.CompletableFuture.supplyAsync; @@ -23,6 +23,8 @@ public class MsgResponseBackend implements Consumer<String> { public static final String MOASP_SIGNATURE_INVALID_ERROR_MSG = "Signature of Msg Response " + "with AppDeliveryID=%s is not valid."; + public static final String BINARY_RESPONSE_MISSING_ERROR_MSG = "Binary Response is not in repository."; + public static final String RESPONSE_MISSING_ERROR_MSG = "Response with ResponseID=%s is not in repository."; private final DeliveryRepository repository; private final Consumer<byte[]> signatureVerifier; @@ -58,28 +60,28 @@ public class MsgResponseBackend implements Consumer<String> { public void accept(String responseID) { supplyAsync(() -> verify(responseID)) - .thenAcceptAsync(msgResponse -> applySinks(msgResponse)); + .thenAcceptAsync(msgResponse -> applySinks(msgResponse)) + .exceptionally(ex -> { + log.error(ex.getMessage(), ex); + return null; + }); } private MsgResponse verify(String responseID) { - var response = repository.retrieveResponse(responseID).get(); - var builder = moaZSExceptionBuilder().withAllParametersInAnswer(response.getAnswer()); - - var binaryResponse = repository.retrieveBinaryResponse(responseID).get(); + var response = repository.retrieveResponse(responseID).orElseThrow( + ()-> moaZSException(format(RESPONSE_MISSING_ERROR_MSG, responseID))); try { + var binaryResponse = repository.retrieveBinaryResponse(responseID).orElseThrow( + () -> moaZSException(BINARY_RESPONSE_MISSING_ERROR_MSG, MoaZSException.ERROR_MZS_BINARY_RESPONSE_MISSING)); signatureVerifier.accept(binaryResponse); return response; } catch (MoaZSException ex) { log.error(ex.getMessage(), ex); - var wrappingEx = builder - .withMessage(format(MOASP_SIGNATURE_INVALID_ERROR_MSG, response.getAppDeliveryID())) - .withErrorCode(MoaZSException.ERROR_MOASP_SIGNATURE_INVALID) - .withCause(ex) - .build(); - - return response.generateError(wrappingEx); + var text = format(MOASP_SIGNATURE_INVALID_ERROR_MSG, response.getAppDeliveryID()); + var code = ERROR_MOASP_SIGNATURE_INVALID; + return response.generateError(text, code); } } diff --git a/src/main/java/at/gv/egiz/moazs/backend/SignatureVerifier.java b/src/main/java/at/gv/egiz/moazs/backend/SignatureVerifier.java index f9bbeb3..874e4f4 100644 --- a/src/main/java/at/gv/egiz/moazs/backend/SignatureVerifier.java +++ b/src/main/java/at/gv/egiz/moazs/backend/SignatureVerifier.java @@ -3,13 +3,13 @@ package at.gv.egiz.moazs.backend; import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.ISignatureVerificationService; import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXMLSignatureVerificationResponse; import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceException; +import at.gv.egiz.moazs.MoaZSException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.function.Consumer; import static at.gv.egiz.moazs.MoaZSException.moaZSException; -import static at.gv.egiz.moazs.MoaZSException.moaZSExceptionBuilder; import static java.lang.String.format; public class SignatureVerifier implements Consumer<byte[]> { @@ -21,6 +21,8 @@ public class SignatureVerifier implements Consumer<byte[]> { private static final String CERT_CODE_ERROR_MSG = "Certificate chain is not valid: Check code was %d. "; private static final String MANIFEST_CODE_ERROR_MSG = "Signature Manifest is not valid: Check code was %d. "; private static final String XMLMANIFEST_CODE_ERROR_MSG = "XmlDSIGManifest is not valid: Check code was %d. "; + + //TODO: Dont make this multiline! private static final String XML_SIGNATURE_RESPONSE_TEMPLATE = " XmlDsigSubjectName: %s\n" + " SignatureManifestCheckCode: %s\n" + @@ -93,14 +95,12 @@ public class SignatureVerifier implements Consumer<byte[]> { var msg = builder.toString(); - if(msg.length() > 0) { + if(!msg.isEmpty()) { throw moaZSException(msg); } } catch (MOASigServiceException e) { - throw moaZSExceptionBuilder(MOASIG_SERVICE_ERROR_MSG) - .withCause(e) - .build(); + throw moaZSException(MOASIG_SERVICE_ERROR_MSG, e); } } diff --git a/src/main/java/at/gv/egiz/moazs/client/SSLContextCreator.java b/src/main/java/at/gv/egiz/moazs/client/SSLContextCreator.java index 8fb5d80..47a2f1c 100644 --- a/src/main/java/at/gv/egiz/moazs/client/SSLContextCreator.java +++ b/src/main/java/at/gv/egiz/moazs/client/SSLContextCreator.java @@ -6,13 +6,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.lang.Nullable; import org.springframework.stereotype.Component; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import javax.net.ssl.X509TrustManager; import javax.net.ssl.*; import java.io.IOException; import java.security.*; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; import static at.gv.egiz.moazs.MoaZSException.moaZSException; import static java.lang.String.format; diff --git a/src/main/java/at/gv/egiz/moazs/client/TnvzHelper.java b/src/main/java/at/gv/egiz/moazs/client/TnvzHelper.java index 884be3e..de22805 100644 --- a/src/main/java/at/gv/egiz/moazs/client/TnvzHelper.java +++ b/src/main/java/at/gv/egiz/moazs/client/TnvzHelper.java @@ -19,6 +19,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import static at.gv.egiz.moazs.MoaZSException.moaZSException; import static at.gv.zustellung.tnvz.xsd.PersonQueryType.MetaData.metaDataBuilder; import static at.gv.zustellung.tnvz.xsd.PersonQueryType.personQueryTypeBuilder; import static at.gv.zustellung.tnvz.xsd.QueryPersonRequest.QueryEntryList.queryEntryListBuilder; @@ -52,21 +53,19 @@ public class TnvzHelper { * {@code tvnzPort}, validates the tnvz's response and extracts the {@code Identification} Element. * @param mzsRequest Data source for the QueryPersonRequest * @param tvnzPort Client for communicating with the tnvz service - * @param exceptionBuilder Utility to collect information and build a meaningful exception in case of errors. * @throws MoaZSException in case of an error. * @return */ public IdentificationType performQueryPersonRequest(DeliveryRequestType mzsRequest, - TNVZServicePort tvnzPort, - MoaZSException.Builder exceptionBuilder) { + TNVZServicePort tvnzPort) { var tvnzQuery = buildQuery(mzsRequest); var tvnzResponse = tvnzPort.queryPerson(tvnzQuery); - verifyResponse(tvnzResponse, exceptionBuilder); + verifyResponse(tvnzResponse); var tvnzResult = getResult(tvnzResponse); var typesInRequest = extractListOfMimemtypesIn(mzsRequest); - checkMimetypes(tvnzResult, typesInRequest, exceptionBuilder); + checkMimetypes(tvnzResult, typesInRequest); return tvnzResult.getSuccess().getIdentification(); } @@ -170,30 +169,26 @@ public class TnvzHelper { .collect(toSet()); } - private void verifyResponse(QueryPersonResponse tvnzResponse, MoaZSException.Builder mzsBuilder) { + private void verifyResponse(QueryPersonResponse tvnzResponse) { var error = tvnzResponse.getError(); if (error != null) { - throw mzsBuilder.withErrorCode(error.getCode()) - .withMessage(error.getText()) - .build(); + throw MoaZSException.moaZSException(error.getText(), error.getCode()); } var results = tvnzResponse.getQueryResultList().getQueryResult(); if (results.isEmpty()) { - throw mzsBuilder.withErrorCode(MoaZSException.ERROR_MZS_NO_TNVZ_PERSON_QUERY_RESULTS) - .withMessage(MZS_NO_TNVZ_PERSON_QUERY_RESULTS_ERROR_MSG) - .build(); + throw MoaZSException.moaZSException(MZS_NO_TNVZ_PERSON_QUERY_RESULTS_ERROR_MSG, + MoaZSException.ERROR_MZS_NO_TNVZ_PERSON_QUERY_RESULTS); } var tnvzResult = results.get(0); - mzsBuilder.withPreAdviceNoteSent(tnvzResult); if (tnvzResult.getError() != null) { var info = tnvzResult.getError().getErrorInfo(); - throw mzsBuilder.withErrorCode(info.getCode()) - .withMessage(RECEIVER_NOT_ADRESSABLE_ERROR_MSG, info.getText()) - .build(); + var message = String.format(RECEIVER_NOT_ADRESSABLE_ERROR_MSG, info.getText()); + var code = info.getCode(); + throw moaZSException(message, code, tnvzResult.getError().getPreAdviceNoteSent()); } } @@ -201,14 +196,14 @@ public class TnvzHelper { return tvnzResponse.getQueryResultList().getQueryResult().get(0); } - private void checkMimetypes(PersonResultType tnvzResult, Set<String> typesInRequest, MoaZSException.Builder mzsBuilder) { + private void checkMimetypes(PersonResultType tnvzResult, Set<String> typesInRequest) { var mismatchedTypes = findMimeTypeMismatches(tnvzResult, typesInRequest); if (!mismatchedTypes.isEmpty()) { var acceptedTypesString = join(",", getAcceptedTypes(tnvzResult)); var mismatchedTypesString = join(",", mismatchedTypes); - throw mzsBuilder.withErrorCode(MoaZSException.ERROR_MZS_MIMETYPE_MISSMATCH) - .withMessage(MIMETYPE_MISSMATCH_ERROR_MSG, mismatchedTypesString, acceptedTypesString) - .build(); + var message = String.format(MIMETYPE_MISSMATCH_ERROR_MSG, mismatchedTypesString, acceptedTypesString); + var code = MoaZSException.ERROR_MZS_MIMETYPE_MISSMATCH; + throw MoaZSException.moaZSException(message, code); } } diff --git a/src/main/java/at/gv/egiz/moazs/preprocess/DeliveryRequestAugmenter.java b/src/main/java/at/gv/egiz/moazs/preprocess/DeliveryRequestAugmenter.java index eac7ea6..e7ee357 100644 --- a/src/main/java/at/gv/egiz/moazs/preprocess/DeliveryRequestAugmenter.java +++ b/src/main/java/at/gv/egiz/moazs/preprocess/DeliveryRequestAugmenter.java @@ -9,6 +9,7 @@ import java.util.Map; import static at.gv.egiz.moazs.MoaZSException.moaZSException; import static at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.deliveryRequestTypeBuilder; +import static java.lang.String.format; @Component public class DeliveryRequestAugmenter { @@ -62,7 +63,8 @@ public class DeliveryRequestAugmenter { : util.merge(requestConfig, fallbackConfig); if (!validator.isConfigProfileComplete(mergedConfig)) { - throw moaZSException(INCOMPLETE_MERGED_CONFIG_ERROR_MESSAGE, fallbackProfileId); + var message = format(INCOMPLETE_MERGED_CONFIG_ERROR_MESSAGE, fallbackProfileId); + throw moaZSException(message); } var mergedRequest = deliveryRequestTypeBuilder(request) diff --git a/src/main/java/at/gv/egiz/moazs/scheme/MsgResponse.java b/src/main/java/at/gv/egiz/moazs/scheme/MsgResponse.java index 8bd88d9..c4fd0b7 100644 --- a/src/main/java/at/gv/egiz/moazs/scheme/MsgResponse.java +++ b/src/main/java/at/gv/egiz/moazs/scheme/MsgResponse.java @@ -1,6 +1,5 @@ package at.gv.egiz.moazs.scheme; -import at.gv.egiz.moazs.MoaZSException; import at.gv.zustellung.app2mzs.xsd.Mzs2AppPortType; import at.gv.zustellung.msg.xsd.DeliveryAnswerType; @@ -33,7 +32,14 @@ public abstract class MsgResponse <T> { public abstract String getAppDeliveryID(); public abstract String getZSDeliveryID(); public abstract DeliveryAnswerType getAnswer(); - public abstract MsgResponse<T> generateError(MoaZSException exception); + + /** + * Create an error response that is based on the current response. + * @param text describes the error. + * @param code contains an error code. + * @return Deep Copy of response but of "error" type + */ + public abstract MsgResponse<T> generateError(String text, String code); public abstract CompletableFuture<Void> sendToMzsClient(Msg2MzsConverter converter, Optional<byte[]> signedStatus, Mzs2AppPortType client); } diff --git a/src/main/java/at/gv/egiz/moazs/scheme/NameSpace.java b/src/main/java/at/gv/egiz/moazs/scheme/NameSpace.java index bb7f621..6b6f34a 100644 --- a/src/main/java/at/gv/egiz/moazs/scheme/NameSpace.java +++ b/src/main/java/at/gv/egiz/moazs/scheme/NameSpace.java @@ -16,5 +16,6 @@ public class NameSpace { public static final String MSG_DELIVERY_REQUEST_STATUS = MSG_FACTORY.createDeliveryRequestStatus(null).getName().getLocalPart(); public static final String MSG_DELIVERY_NOTIFICATION = MSG_FACTORY.createDeliveryNotification(null).getName().getLocalPart(); + public static final String MSG_APP_DELIVERY_ID = MSG_FACTORY.createAppDeliveryID("").getName().getLocalPart(); } diff --git a/src/main/java/at/gv/egiz/moazs/scheme/NotificationResponse.java b/src/main/java/at/gv/egiz/moazs/scheme/NotificationResponse.java index 21e00a1..4e7abae 100644 --- a/src/main/java/at/gv/egiz/moazs/scheme/NotificationResponse.java +++ b/src/main/java/at/gv/egiz/moazs/scheme/NotificationResponse.java @@ -1,16 +1,17 @@ package at.gv.egiz.moazs.scheme; -import at.gv.egiz.moazs.MoaZSException; import at.gv.zustellung.app2mzs.xsd.Mzs2AppPortType; import at.gv.zustellung.msg.xsd.DeliveryAnswerType; import at.gv.zustellung.msg.xsd.DeliveryNotificationType; +import at.gv.zustellung.msg.xsd.ErrorInfoType; import at.gv.zustellung.msg.xsd.ObjectFactory; import javax.xml.bind.JAXBElement; - +import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; +import static at.gv.zustellung.msg.xsd.DeliveryErrorType.deliveryErrorTypeBuilder; import static at.gv.zustellung.msg.xsd.DeliveryNotificationType.deliveryNotificationTypeBuilder; public class NotificationResponse extends MsgResponse<DeliveryNotificationType> { @@ -54,14 +55,19 @@ public class NotificationResponse extends MsgResponse<DeliveryNotificationType> } @Override - public NotificationResponse generateError(MoaZSException exception) { - - //TODO: use copy constructor? - var notificationType = deliveryNotificationTypeBuilder() - .withAppDeliveryID(exception.getAppDeliveryID()) - .withDeliverySystem(exception.getDeliverySystem()) - .withGZ(exception.getGz()) - .withZSDeliveryID(exception.getZsDeliveryID()) + public NotificationResponse generateError(String text, String code) { + + var info = ErrorInfoType.errorInfoTypeBuilder() + .withCode(code) + .withText(text) + .build(); + + var error = deliveryErrorTypeBuilder() + .withErrorInfo(info) + .build(); + + var notificationType = deliveryNotificationTypeBuilder(notification) + .withAnswer(List.of(factory.createAnswer(error))) .build(); return new NotificationResponse(notificationType); diff --git a/src/main/java/at/gv/egiz/moazs/scheme/RequestStatusResponse.java b/src/main/java/at/gv/egiz/moazs/scheme/RequestStatusResponse.java index 14e22ad..8a4b590 100644 --- a/src/main/java/at/gv/egiz/moazs/scheme/RequestStatusResponse.java +++ b/src/main/java/at/gv/egiz/moazs/scheme/RequestStatusResponse.java @@ -6,11 +6,13 @@ import at.gv.zustellung.msg.xsd.DeliveryAnswerType; import at.gv.zustellung.msg.xsd.DeliveryRequestStatusType; import at.gv.zustellung.msg.xsd.ErrorInfoType; import at.gv.zustellung.msg.xsd.ObjectFactory; +import org.springframework.lang.Nullable; import javax.xml.bind.JAXBElement; import java.util.Optional; import java.util.concurrent.CompletableFuture; +import static at.gv.egiz.moazs.MoaZSException.moaZSException; import static at.gv.egiz.moazs.util.NullCoalesce.coalesce; import static at.gv.zustellung.msg.xsd.DeliveryRequestStatusType.Error.errorBuilder; import static at.gv.zustellung.msg.xsd.DeliveryRequestStatusType.deliveryRequestStatusTypeBuilder; @@ -26,10 +28,19 @@ public class RequestStatusResponse extends MsgResponse<DeliveryRequestStatusType public RequestStatusResponse(DeliveryRequestStatusType status) { this.status = status; - this.answer = coalesce(status.getSuccess(), status.getPartialSuccess(), status.getError()).get(); + this.answer = getAnswer(status); super.id = createResponseId(answer.getAppDeliveryID(), ID_SUFFIX); } + /** + * Convenience method to access DeliveryAnswerType's base fields of Success, PartialSuccess or Error. + * @param status + * @return Success, PartialSuccess, or Error casted to DeliveryAnswerType + */ + public static DeliveryAnswerType getAnswer(DeliveryRequestStatusType status) { + return coalesce(status.getSuccess(), status.getPartialSuccess(), status.getError()).get(); + } + public static String getResponseID(String appDeliveryID) { return appDeliveryID + ID_SUFFIX; } @@ -60,31 +71,42 @@ public class RequestStatusResponse extends MsgResponse<DeliveryRequestStatusType } @Override - public MsgResponse<DeliveryRequestStatusType> generateError(MoaZSException exception) { - return generateErrorFromException(exception); + public MsgResponse<DeliveryRequestStatusType> generateError(String text, String code) { + var auxException = moaZSException(text, code); + return generateError(auxException, answer); } - public static MsgResponse<DeliveryRequestStatusType> generateErrorFromException(MoaZSException exception) { + /** + * Creates A MsgResponse with a DeliveryRequestStatus of type error and merges fields from + * {@code exception} and {@code answer} + * @param exception + * @param answer + * @return + */ + public static MsgResponse<DeliveryRequestStatusType> generateError(MoaZSException exception, + @Nullable DeliveryAnswerType answer) { ErrorInfoType info = errorInfoTypeBuilder() .withText(exception.getMessage()) - .withCode(exception.getErrorCode()) + .withCode(exception.getCode()) .build(); - DeliveryRequestStatusType.Error error = errorBuilder() - .withErrorInfo(info) - .withAppDeliveryID(exception.getAppDeliveryID()) - .withDeliverySystem(exception.getDeliverySystem()) - .withGZ(exception.getGz()) + var errorBuilder = errorBuilder() .withPreAdviceNoteSent(exception.getPreAdviceNoteSent()) - .withZSDeliveryID(exception.getZsDeliveryID()) - .build(); - - var status = deliveryRequestStatusTypeBuilder() - .withError(error) - .withVersion(NameSpace.MSG_VERSION) + .withErrorInfo(info); + + if (answer != null) { + errorBuilder + .withAppDeliveryID(answer.getAppDeliveryID()) + .withDeliverySystem(answer.getDeliverySystem()) + .withZSDeliveryID(answer.getZSDeliveryID()) + .withGZ(answer.getGZ()); + } + + var errorStatus = deliveryRequestStatusTypeBuilder() + .withError(errorBuilder.build()) .build(); - return new RequestStatusResponse(status); + return new RequestStatusResponse(errorStatus); } @Override diff --git a/src/main/java/at/gv/egiz/moazs/scheme/SOAPUtils.java b/src/main/java/at/gv/egiz/moazs/scheme/SOAPUtils.java index 8b8219a..6e96a6b 100644 --- a/src/main/java/at/gv/egiz/moazs/scheme/SOAPUtils.java +++ b/src/main/java/at/gv/egiz/moazs/scheme/SOAPUtils.java @@ -1,6 +1,7 @@ package at.gv.egiz.moazs.scheme; import at.gv.egiz.eaaf.core.impl.utils.DOMUtils; +import at.gv.egiz.moazs.MoaZSException; import org.apache.cxf.binding.soap.Soap11; import org.springframework.stereotype.Component; import org.w3c.dom.Element; @@ -12,7 +13,6 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; -import static at.gv.egiz.moazs.MoaZSException.moaZSExceptionBuilder; @Component public class SOAPUtils { @@ -31,12 +31,12 @@ public class SOAPUtils { .getBytes(StandardCharsets.UTF_8); } catch (IOException | TransformerException e) { - throw moaZSExceptionBuilder("Error while parsing message. ").withCause(e).build(); + throw MoaZSException.moaZSException("Error while parsing message. ", e); } } public String getAppDeliveryIDFrom(Element document) { - var elements = document.getElementsByTagNameNS(NameSpace.MSG, "AppDeliveryID"); + var elements = document.getElementsByTagNameNS(NameSpace.MSG, NameSpace.MSG_APP_DELIVERY_ID); var appDeliveryIdElement = elements.item(0).getFirstChild(); diff --git a/src/main/java/at/gv/egiz/moazs/service/MzsService.java b/src/main/java/at/gv/egiz/moazs/service/MzsService.java index cbc56e4..8f0ef86 100644 --- a/src/main/java/at/gv/egiz/moazs/service/MzsService.java +++ b/src/main/java/at/gv/egiz/moazs/service/MzsService.java @@ -20,8 +20,8 @@ import java.util.concurrent.TimeoutException; import java.util.function.Consumer; import static at.gv.egiz.moazs.MoaZSException.moaZSException; -import static at.gv.egiz.moazs.MoaZSException.moaZSExceptionBuilder; import static at.gv.zustellung.app2mzs.xsd.PartialSuccessType.partialSuccessTypeBuilder; +import static java.lang.String.format; import static java.util.concurrent.CompletableFuture.supplyAsync; //todo : validate Schema in both directions. @@ -33,6 +33,9 @@ public class MzsService implements App2MzsPortType { //TODO move timeout and namespaces to config private static final int TIMEOUT_FOR_ANWSER = 10; + private static final String MZS_SERVICE_ERROR_MSG = "An error occurred while processing DeliveryRequest " + + "with AppDeliveryID=%s."; + private static final String RESPONSE_MISSING_ERROR_MSG = "Could not get a response for AppDeliveryID=%s."; private final DeliveryRepository repository; private final Consumer<String> backend; @@ -71,10 +74,8 @@ public class MzsService implements App2MzsPortType { return generatePartialSuccessResponse(appDeliveryID); } catch (Exception e) { - throw moaZSExceptionBuilder("An error occurred while processing DeliveryRequest " + - "with AppDeliveryID=%s.", appDeliveryID) - .withCause(e) - .build(); + var message = format(MZS_SERVICE_ERROR_MSG, appDeliveryID); + throw moaZSException(message, e); } } @@ -82,6 +83,7 @@ public class MzsService implements App2MzsPortType { private DeliveryRequestStatusType process(DeliveryRequestType deliveryRequest) { var appDeliveryID = deliveryRequest.getMetaData().getAppDeliveryID(); + //TODO: fix too. logger.info("Receive request with appDeliveryID = {}.", appDeliveryID); repository.store(deliveryRequest); @@ -89,7 +91,7 @@ public class MzsService implements App2MzsPortType { var statusId = RequestStatusResponse.getResponseID(appDeliveryID); var response = repository.retrieveResponse(statusId) - .orElseThrow(() -> moaZSException("Could not get a response for AppDeliveryID=%s.", appDeliveryID)); + .orElseThrow(() -> moaZSException(format(RESPONSE_MISSING_ERROR_MSG, appDeliveryID))); return (DeliveryRequestStatusType) response.getResponse(); } diff --git a/src/test/java/at/gv/egiz/moazs/DeliveryRequestBackendTest.java b/src/test/java/at/gv/egiz/moazs/DeliveryRequestBackendTest.java index ed63489..9ae0a14 100644 --- a/src/test/java/at/gv/egiz/moazs/DeliveryRequestBackendTest.java +++ b/src/test/java/at/gv/egiz/moazs/DeliveryRequestBackendTest.java @@ -20,7 +20,6 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import static at.gv.egiz.moazs.MoaZSException.moaZSException; -import static at.gv.egiz.moazs.MoaZSException.moaZSExceptionBuilder; import static at.gv.egiz.moazs.scheme.RequestStatusResponse.getResponseID; import static at.gv.zustellung.app2mzs.xsd.ClientType.clientTypeBuilder; import static at.gv.zustellung.app2mzs.xsd.ConfigType.configTypeBuilder; @@ -57,11 +56,11 @@ public class DeliveryRequestBackendTest { private SignatureVerifier verifier; - private DeliveryRequestBackend pipeline; + private DeliveryRequestBackend backend; @Before public void setup() { - pipeline = new DeliveryRequestBackend( + backend = new DeliveryRequestBackend( repository, tnvzHelper, converter, @@ -74,7 +73,7 @@ public class DeliveryRequestBackendTest { var appDeliveryID = "no-tnvz-request"; var expectedStatus = setupMocks(appDeliveryID, false); - pipeline.accept(appDeliveryID); + backend.accept(appDeliveryID); verifyZeroInteractions(tnvzHelper); var response = repository.retrieveResponse(getResponseID(appDeliveryID)).get(); @@ -87,10 +86,10 @@ public class DeliveryRequestBackendTest { public void rejectDeliveryWhenReceiverIsNotAddressable() { var appDeliveryID = "not-addressable"; setupMocks(appDeliveryID, true); - when(tnvzHelper.performQueryPersonRequest(any(), any(), any())) - .thenThrow(buildMzsException("400", appDeliveryID)); + when(tnvzHelper.performQueryPersonRequest(any(), any())) + .thenThrow(moaZSException("Not addressable", "400")); - pipeline.accept(appDeliveryID); + backend.accept(appDeliveryID); var responseID = getResponseID(appDeliveryID); var response = repository.retrieveResponse(responseID).get(); @@ -99,7 +98,7 @@ public class DeliveryRequestBackendTest { assertThat(actualCode).isEqualTo("400"); verifyZeroInteractions(converter); - verify(tnvzHelper).performQueryPersonRequest(any(), any(), any()); + verify(tnvzHelper).performQueryPersonRequest(any(), any()); } @Test @@ -107,7 +106,7 @@ public class DeliveryRequestBackendTest { var appDeliveryID = "tnvz-request"; var expectedStatus = setupMocks(appDeliveryID, true); - pipeline.accept(appDeliveryID); + backend.accept(appDeliveryID); var response = repository.retrieveResponse(getResponseID(appDeliveryID)).get(); var actualStatus = (DeliveryRequestStatusType) response.getResponse(); @@ -120,7 +119,7 @@ public class DeliveryRequestBackendTest { setupMocks(appDeliveryID, true); doThrow(moaZSException("Signature Invalid!")).when(verifier).accept(any()); - pipeline.accept(appDeliveryID); + backend.accept(appDeliveryID); var response = repository.retrieveResponse(getResponseID(appDeliveryID)).get(); var status = (DeliveryRequestStatusType) response.getResponse(); var actualCode = status.getError().getErrorInfo().getCode(); @@ -146,19 +145,12 @@ public class DeliveryRequestBackendTest { if (tnvzRequest) { when(clientFactory.create(any(), same(TNVZServicePort.class))).thenReturn(tnvzClient); - when(tnvzHelper.performQueryPersonRequest(any(), any(), any())).thenReturn(identification); + when(tnvzHelper.performQueryPersonRequest(any(), any())).thenReturn(identification); } return status; } - private MoaZSException buildMzsException(String code, String appDeliveryID) { - return moaZSExceptionBuilder("") - .withErrorCode(code) - .withAppDeliveryID(appDeliveryID) - .build(); - } - private DeliveryRequestStatusType setupStatus(String appDeliveryId) { var success = successBuilder() diff --git a/src/test/java/at/gv/egiz/moazs/TnvzHelperTest.java b/src/test/java/at/gv/egiz/moazs/TnvzHelperTest.java index b58002b..020e270 100644 --- a/src/test/java/at/gv/egiz/moazs/TnvzHelperTest.java +++ b/src/test/java/at/gv/egiz/moazs/TnvzHelperTest.java @@ -16,7 +16,6 @@ import org.mockito.junit.MockitoJUnitRunner; import java.util.List; -import static at.gv.egiz.moazs.MoaZSException.moaZSExceptionBuilder; import static at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Payload.payloadBuilder; import static at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Receiver.receiverBuilder; import static at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Sender.senderBuilder; @@ -62,7 +61,7 @@ public class TnvzHelperTest { var success = tnvzSuccess(acceptedTypes, receiverId); when(port.queryPerson(any())).thenReturn(success); - var actual = helper.performQueryPersonRequest(deliveryRequest, port, moaZSExceptionBuilder()); + var actual = helper.performQueryPersonRequest(deliveryRequest, port); assertThat(actual).isEqualToComparingFieldByFieldRecursively(receiverId); } @@ -75,7 +74,7 @@ public class TnvzHelperTest { var error = tnvzError("400", "Person not found."); when(port.queryPerson(any())).thenReturn(error); - helper.performQueryPersonRequest(deliveryRequest, port, moaZSExceptionBuilder()); + helper.performQueryPersonRequest(deliveryRequest, port); } @Test(expected = MoaZSException.class) @@ -87,7 +86,7 @@ public class TnvzHelperTest { var success = tnvzSuccess(acceptedTypes, receiverId); when(port.queryPerson(any())).thenReturn(success); - helper.performQueryPersonRequest(deliveryRequest, port, moaZSExceptionBuilder()); + helper.performQueryPersonRequest(deliveryRequest, port); } @Test @@ -99,7 +98,7 @@ public class TnvzHelperTest { var success = tnvzSuccess(acceptedTypes, receiverId); when(port.queryPerson(any())).thenReturn(success); - var actual = helper.performQueryPersonRequest(deliveryRequest, port, moaZSExceptionBuilder()); + var actual = helper.performQueryPersonRequest(deliveryRequest, port); assertThat(actual).isEqualToComparingFieldByFieldRecursively(receiverId); } |