diff options
12 files changed, 228 insertions, 58 deletions
@@ -27,6 +27,7 @@ <jedisclient.version>2.9.3</jedisclient.version> <guava.version>27.1-jre</guava.version> <immutable-xjc-plugin.version>1.5</immutable-xjc-plugin.version> + <hamcrest.version>1.3</hamcrest.version> </properties> <dependencies> @@ -82,6 +83,13 @@ <artifactId>javax.jws-api</artifactId> <version>${jwsapi.version}</version> </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-all</artifactId> + <version>${hamcrest.version}</version> + <scope>test</scope> + </dependency> + </dependencies> <build> @@ -117,11 +125,17 @@ <extraargs> <extraarg>-xjc-immutable</extraarg> <extraarg>-xjc-imm-builder</extraarg> + <extraarg>-xjc-imm-cc</extraarg> </extraargs> </wsdlOption> <wsdlOption> <wsdl>${project.basedir}/src/main/resources/zusemsg/app2zuse_p2.wsdl</wsdl> <wsdlLocation>classpath:wsdl/app2zuse_p2.wsdl</wsdlLocation> + <extraargs> + <extraarg>-xjc-immutable</extraarg> + <extraarg>-xjc-imm-builder</extraarg> + <extraarg>-xjc-imm-cc</extraarg> + </extraargs> </wsdlOption> </wsdlOptions> </configuration> diff --git a/src/main/java/at/gv/egiz/moazs/App2MzsService.java b/src/main/java/at/gv/egiz/moazs/App2MzsService.java index 66ab795..f84f16c 100644 --- a/src/main/java/at/gv/egiz/moazs/App2MzsService.java +++ b/src/main/java/at/gv/egiz/moazs/App2MzsService.java @@ -1,16 +1,12 @@ package at.gv.egiz.moazs; -import at.gv.e_government.reference.namespace.zustellung.msg.phase2._20181206_.DeliveryAnswerType; import at.gv.e_government.reference.namespace.zustellung.msg.phase2._20181206_.DeliveryAnswerType.DeliveryAnswerTypeBuilder; import at.gv.e_government.reference.namespace.zustellung.msg.phase2._20181206_.DeliveryRequestStatusType; import at.gv.e_government.reference.namespace.zustellung.msg.phase2._20181206_.DeliveryRequestStatusType.DeliveryRequestStatusTypeBuilder; import at.gv.e_government.reference.namespace.zustellung.msg.phase2._20181206_.DeliveryRequestStatusType.Error.ErrorBuilder; -import at.gv.e_government.reference.namespace.zustellung.msg.phase2._20181206_.ErrorInfoType; import at.gv.e_government.reference.namespace.zustellung.msg.phase2._20181206_.ErrorInfoType.ErrorInfoTypeBuilder; -import at.gv.e_government.reference.namespace.zustellung.msg.phase2._20181206_.ObjectFactory; import at.gv.e_government.reference.namespace.zustellung.mzs.app2mzs.App2MzsPortType; import at.gv.e_government.reference.namespace.zustellung.mzs.app2mzs_.DeliveryRequestType; -import at.gv.e_government.reference.namespace.zustellung.mzs.app2mzs_.DeliveryRequestType.DeliveryRequestTypeBuilder; import at.gv.egiz.moazs.pipeline.DeliveryPipeline; import at.gv.egiz.moazs.repository.DeliveryRepository; import org.slf4j.Logger; @@ -37,12 +33,14 @@ public class App2MzsService implements App2MzsPortType { private final DeliveryRepository repository; private final DeliveryPipeline pipeline; private final Mzs2AppClient appClient; - private final ObjectFactory objectFactory = new ObjectFactory(); + private final DeliveryPreprocessor preprocessor; - public App2MzsService(@Autowired DeliveryRepository repository, @Autowired DeliveryPipeline pipeline, @Autowired Mzs2AppClient appClient) { + public App2MzsService(@Autowired DeliveryRepository repository, @Autowired DeliveryPipeline pipeline, + @Autowired Mzs2AppClient appClient, @Autowired DeliveryPreprocessor preprocessor) { this.repository = repository; this.pipeline = pipeline; this.appClient = appClient; + this.preprocessor = preprocessor; } @Override @@ -54,24 +52,25 @@ public class App2MzsService implements App2MzsPortType { final var appDeliveryID = deliveryRequest.getMetaData().getAppDeliveryID(); - var future = supplyAsync(() -> process(deliveryRequest)); + var future = supplyAsync(() -> preprocessor.preProcess(deliveryRequest)) + .thenApply((request) -> process(request)); try { return future.get(TIMEOUT_FOR_ANWSER, TimeUnit.SECONDS); } catch (TimeoutException e) { future.thenAccept(appClient::sendNotification); logger.info("Answer Timed Out", e); - return generatePartialSuccessResponse(appDeliveryID, "Your request timed out; Wait until X for receiving a notification."); + return generatePartialSuccessResponse(appDeliveryID); } catch (Exception e ) { logger.error("Could not deliver request.", e); - final var message = format("An error occured while delivering request: {}", e.getMessage()); + var message = format("An error occured while delivering request: {0}", e.getMessage()); return generateErrorResponse(appDeliveryID, message); } } - private DeliveryRequestStatusType generatePartialSuccessResponse(String appDeliveryId, String message) { + private DeliveryRequestStatusType generatePartialSuccessResponse(String appDeliveryId) { var answer = new DeliveryAnswerTypeBuilder() .withAppDeliveryID(appDeliveryId) @@ -107,13 +106,8 @@ public class App2MzsService implements App2MzsPortType { repository.add(deliveryRequest); pipeline.processRequest(appDeliveryID); - var status = repository.getDeliveryRequestStatus(appDeliveryID); - - if (status.isEmpty()) { - throw new RuntimeException(format("Could not get a response for request with appDeliveryId = {}", appDeliveryID)); - } - - return status.get(); + return repository.getDeliveryRequestStatus(appDeliveryID) + .orElseThrow(() -> new RuntimeException("Could not get a response for appDeliveryId = " + appDeliveryID)); } diff --git a/src/main/java/at/gv/egiz/moazs/DeliveryPreprocessor.java b/src/main/java/at/gv/egiz/moazs/DeliveryPreprocessor.java new file mode 100644 index 0000000..2bb621d --- /dev/null +++ b/src/main/java/at/gv/egiz/moazs/DeliveryPreprocessor.java @@ -0,0 +1,45 @@ +package at.gv.egiz.moazs; + +import at.gv.e_government.reference.namespace.zustellung.mzs.app2mzs_.ConfigType; +import at.gv.e_government.reference.namespace.zustellung.mzs.app2mzs_.ConfigType.ConfigTypeBuilder; +import at.gv.e_government.reference.namespace.zustellung.mzs.app2mzs_.DeliveryRequestType; +import at.gv.e_government.reference.namespace.zustellung.mzs.app2mzs_.DeliveryRequestType.DeliveryRequestTypeBuilder; +import org.springframework.stereotype.Component; + +import static at.gv.egiz.moazs.util.NullCoalesce.coalesce; + +@Component +public class DeliveryPreprocessor { + + /** + * Validates and augments an incoming {@code request} + * + * Validates a {@code request} to ensure the availability of all mandatory fields. Where possible, the method + * augments the request with values taken from the app's configuration. + * @param request + * @return validated and augmented request + */ + public DeliveryRequestType preProcess(DeliveryRequestType request) { + + validateRequest(request); + + return new DeliveryRequestTypeBuilder(request) + .withConfig(coalesce(request.getConfig(), initDefaultConfig()).get()) + .build(); + } + + private void validateRequest(DeliveryRequestType request) { + if (request.getMetaData() == null) + throw new IllegalArgumentException("Metadata is missing."); + + if (request.getMetaData().getAppDeliveryID() == null) + throw new IllegalArgumentException("AppDeliveryID is missing."); + } + + private ConfigType initDefaultConfig() { + return new ConfigTypeBuilder() + .withPerformQueryPersonRequest(false) + .build(); + } + +} diff --git a/src/main/java/at/gv/egiz/moazs/TnvzClient.java b/src/main/java/at/gv/egiz/moazs/TnvzClient.java new file mode 100644 index 0000000..28bcb66 --- /dev/null +++ b/src/main/java/at/gv/egiz/moazs/TnvzClient.java @@ -0,0 +1,14 @@ +package at.gv.egiz.moazs; + +import org.springframework.stereotype.Component; + +import static at.gv.e_government.reference.namespace.zustellung.mzs.app2mzs_.DeliveryRequestType.*; + +@Component +public class TnvzClient { + + public boolean isAddressable(Receiver receiver) { + return true; + } + +} diff --git a/src/main/java/at/gv/egiz/moazs/config/App2MzsServiceConfig.java b/src/main/java/at/gv/egiz/moazs/config/App2MzsServiceConfig.java index 71f5f04..c4c720d 100644 --- a/src/main/java/at/gv/egiz/moazs/config/App2MzsServiceConfig.java +++ b/src/main/java/at/gv/egiz/moazs/config/App2MzsServiceConfig.java @@ -1,6 +1,5 @@ package at.gv.egiz.moazs.config; -import at.gv.e_government.reference.namespace.zustellung.mzs.app2mzs_.ObjectFactory; import at.gv.egiz.moazs.App2MzsService; import org.apache.cxf.Bus; import org.apache.cxf.jaxws.EndpointImpl; @@ -26,9 +25,4 @@ public class App2MzsServiceConfig { endpoint.publish(); return endpoint; } - - @Bean - public ObjectFactory objectFactory() { - return new ObjectFactory(); - } } diff --git a/src/main/java/at/gv/egiz/moazs/pipeline/SameThreadDeliveryPipeline.java b/src/main/java/at/gv/egiz/moazs/pipeline/SameThreadDeliveryPipeline.java index 20252ff..5a8e377 100644 --- a/src/main/java/at/gv/egiz/moazs/pipeline/SameThreadDeliveryPipeline.java +++ b/src/main/java/at/gv/egiz/moazs/pipeline/SameThreadDeliveryPipeline.java @@ -2,37 +2,39 @@ package at.gv.egiz.moazs.pipeline; import at.gv.e_government.reference.namespace.zustellung.mzs.app2mzs_.DeliveryRequestType; +import at.gv.egiz.moazs.TnvzClient; import at.gv.egiz.moazs.repository.DeliveryRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import java.util.Optional; - -import static java.text.MessageFormat.format; - @Component @Profile("!cluster") public class SameThreadDeliveryPipeline implements DeliveryPipeline { private final DeliveryRepository repository; + private final TnvzClient tnvzClient; - public SameThreadDeliveryPipeline(@Autowired DeliveryRepository repository) { + public SameThreadDeliveryPipeline(@Autowired DeliveryRepository repository, TnvzClient tnvzClient) { this.repository = repository; + this.tnvzClient = tnvzClient; } @Override public void processRequest(String appDeliveryId) { - Optional<DeliveryRequestType> request = repository.getDeliveryRequest(appDeliveryId); - if (request.isEmpty()) { - throw new RuntimeException(format( - "Request with appDeliveryId = {} does not exist.", appDeliveryId)); - } - - //do business logic + var request = repository.getDeliveryRequest(appDeliveryId).orElseThrow(); + checkAddressability(request); //store response to repository } + private void checkAddressability(DeliveryRequestType request) { + if (request.getConfig().isPerformQueryPersonRequest()) { + if (!tnvzClient.isAddressable(request.getReceiver())) { + throw new RuntimeException("Receiver is not addressable."); + } + } + } + } diff --git a/src/main/resources/mzs/app2mzs.xsd b/src/main/resources/mzs/app2mzs.xsd index 434db23..29f94df 100644 --- a/src/main/resources/mzs/app2mzs.xsd +++ b/src/main/resources/mzs/app2mzs.xsd @@ -78,6 +78,13 @@ </xs:sequence> </xs:complexType> </xs:element> + <xs:element ref="Config" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + <xs:element name="Config" type="ConfigType"/> + <xs:complexType name="ConfigType"> + <xs:sequence> + <xs:element name="PerformQueryPersonRequest" type="xs:boolean"></xs:element> </xs:sequence> </xs:complexType> <xs:element name="DeliveryResponse" type="msg:DeliveryRequestStatusType"/> diff --git a/src/test/java/at/gv/egiz/moazs/App2MzsServiceTest.java b/src/test/java/at/gv/egiz/moazs/App2MzsServiceTest.java index 5579f06..03992ae 100644 --- a/src/test/java/at/gv/egiz/moazs/App2MzsServiceTest.java +++ b/src/test/java/at/gv/egiz/moazs/App2MzsServiceTest.java @@ -6,6 +6,7 @@ import at.gv.e_government.reference.namespace.zustellung.msg.phase2._20181206_.D import at.gv.e_government.reference.namespace.zustellung.msg.phase2._20181206_.ObjectFactory; import at.gv.egiz.moazs.pipeline.DeliveryPipeline; import at.gv.egiz.moazs.repository.DeliveryRepository; +import org.hamcrest.Matchers; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; @@ -24,9 +25,12 @@ import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.file.Paths; +import java.util.Arrays; import static java.net.http.HttpClient.Version; -import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.text.StringContainsInOrder.stringContainsInOrder; +import static org.junit.Assert.assertEquals; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT) @@ -63,42 +67,43 @@ public class App2MzsServiceTest { } } - @Test public void acceptValidDeliveryRequest() throws IOException, InterruptedException { + var response = sendDeliveryRequestFile("validDeliveryRequest.soap"); + assertEquals(200, response.statusCode()); + } - final String payloadFile = basePath + "validDeliveryRequest.soap"; - - var client = HttpClient.newBuilder().version(Version.HTTP_1_1).build(); - var request = HttpRequest.newBuilder() - .uri(URI.create(serviceUri)) - .header("Content-Type", "text/xml;charset=UTF-8") - .header("SOAPAction", "\"\"") - .POST(HttpRequest.BodyPublishers.ofFile(Paths.get(payloadFile))) - .build(); - - var response = client.send(request, HttpResponse.BodyHandlers.ofString()); - logger.info("response.body was " + response.body()); - logger.info("response.code was " + response.statusCode()); - assertThat(response.statusCode()).isEqualTo(200); + @Test + public void rejectFormallyIncorrectDeliveryRequest() throws IOException, InterruptedException { + var response = sendDeliveryRequestFile("formallyIncorrectDeliveryRequest.soap"); + assertEquals(500, response.statusCode()); + } + @Test + public void rejectRequestWithoutAppDeliveryID() throws IOException, InterruptedException { + var response = sendDeliveryRequestFile("missingAppDeliveryId.soap"); + assertEquals(200, response.statusCode()); + assertThat(response.body(), stringContainsInOrder(Arrays.asList("Code>", "500", "/", "Code>"))); } @Test - public void rejectFormallyIncorrectDeliveryRequest() throws IOException, InterruptedException { + public void rejectRequestWithoutMetaData() throws IOException, InterruptedException { + var response = sendDeliveryRequestFile("missingMetaData.soap"); + assertEquals(500, response.statusCode()); + } - var invalidDeliveryRequest = basePath + "formallyIncorrectDeliveryRequest.soap"; + private HttpResponse<String> sendDeliveryRequestFile(String fileName) throws IOException, InterruptedException { + var path = basePath + fileName; var client = HttpClient.newBuilder().version(Version.HTTP_1_1).build(); var request = HttpRequest.newBuilder() .uri(URI.create(serviceUri)) .header("Content-Type", "text/xml;charset=UTF-8") .header("SOAPAction", "\"\"") - .POST(HttpRequest.BodyPublishers.ofFile(Paths.get(invalidDeliveryRequest))) + .POST(HttpRequest.BodyPublishers.ofFile(Paths.get(path))) .build(); - var response = client.send(request, HttpResponse.BodyHandlers.ofString()); - assertThat(response.statusCode()).isEqualTo(500); + return client.send(request, HttpResponse.BodyHandlers.ofString()); } diff --git a/src/test/resources/at/gv/egiz/moazs/App2MzsServiceTest/formallyIncorrectDeliveryRequest.soap b/src/test/resources/at/gv/egiz/moazs/App2MzsServiceTest/formallyIncorrectDeliveryRequest.soap index e8bd7f2..0570005 100644 --- a/src/test/resources/at/gv/egiz/moazs/App2MzsServiceTest/formallyIncorrectDeliveryRequest.soap +++ b/src/test/resources/at/gv/egiz/moazs/App2MzsServiceTest/formallyIncorrectDeliveryRequest.soap @@ -30,7 +30,7 @@ </p:PostalAddress> </mzs:Receiver> <mzs:MetaData> - <mzs:AppDeliveryID>asd</mzs:AppDeliveryID> + <mzs:AppDeliveryID>formally-incorrect-delivery-request-id</mzs:AppDeliveryID> <mzs:DeliveryQuality>nonRSa</mzs:DeliveryQuality> <mzs:RequiresEncryption>false</mzs:RequiresEncryption> </mzs:MetaData> diff --git a/src/test/resources/at/gv/egiz/moazs/App2MzsServiceTest/missingAppDeliveryId.soap b/src/test/resources/at/gv/egiz/moazs/App2MzsServiceTest/missingAppDeliveryId.soap new file mode 100644 index 0000000..e981b31 --- /dev/null +++ b/src/test/resources/at/gv/egiz/moazs/App2MzsServiceTest/missingAppDeliveryId.soap @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<soapenv:Envelope + xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:mzs="http://reference.e-government.gv.at/namespace/zustellung/mzs/app2mzs#" + xmlns:p="http://reference.e-government.gv.at/namespace/zustellung/mzs/persondata#" + xmlns:msg="http://reference.e-government.gv.at/namespace/zustellung/msg/phase2/20181206#" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <soapenv:Body> + <mzs:DeliveryRequest> + <mzs:Sender> + <p:CorporateBody> + <p:FullName>Bundesministerium für Testzwecke</p:FullName> + </p:CorporateBody> + <mzs:WebserviceURL>https://authority.gv.at/delivery_notification</mzs:WebserviceURL> + </mzs:Sender> + <mzs:Receiver> + <p:PhysicalPerson> + <p:Name> + <p:GivenName>Maxi</p:GivenName> + <p:FamilyName>Mustermann1</p:FamilyName> + </p:Name> + <p:DateOfBirth>1984-01-24</p:DateOfBirth> + </p:PhysicalPerson> + <p:PostalAddress> + <p:CountryCode>AT</p:CountryCode> + <p:PostalCode>1010</p:PostalCode> + <p:Municipality>Wien</p:Municipality> + <p:DeliveryAddress> + <p:StreetName>Muststrasse</p:StreetName> + <p:BuildingNumber>10</p:BuildingNumber> + </p:DeliveryAddress> + </p:PostalAddress> + </mzs:Receiver> + <msg:MetaData /> + <mzs:Payload> + <mzs:DocumentReference>https://authority.gv.at/files/73bdf969781ba41fa07df1ff8439cf685c0db1c3</mzs:DocumentReference> + <mzs:FileName>brief.xml</mzs:FileName> + <mzs:MIMEType>text/xml</mzs:MIMEType> + <msg:CheckSum> + <msg:AlgorithmID>SHA1</msg:AlgorithmID> + <msg:Value>9b972c70fdaf5e1b26b3387c87b0ffb72e5940b6</msg:Value> + </msg:CheckSum> + <mzs:Size>123401</mzs:Size> + </mzs:Payload> + </mzs:DeliveryRequest> + </soapenv:Body> +</soapenv:Envelope> diff --git a/src/test/resources/at/gv/egiz/moazs/App2MzsServiceTest/missingMetaData.soap b/src/test/resources/at/gv/egiz/moazs/App2MzsServiceTest/missingMetaData.soap new file mode 100644 index 0000000..4a1e02d --- /dev/null +++ b/src/test/resources/at/gv/egiz/moazs/App2MzsServiceTest/missingMetaData.soap @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> +<soapenv:Envelope + xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:mzs="http://reference.e-government.gv.at/namespace/zustellung/mzs/app2mzs#" + xmlns:p="http://reference.e-government.gv.at/namespace/zustellung/mzs/persondata#" + xmlns:msg="http://reference.e-government.gv.at/namespace/zustellung/msg/phase2/20181206#" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <soapenv:Body> + <mzs:DeliveryRequest> + <mzs:Sender> + <p:CorporateBody> + <p:FullName>Bundesministerium für Testzwecke</p:FullName> + </p:CorporateBody> + <mzs:WebserviceURL>https://authority.gv.at/delivery_notification</mzs:WebserviceURL> + </mzs:Sender> + <mzs:Receiver> + <p:PhysicalPerson> + <p:Name> + <p:GivenName>Maxi</p:GivenName> + <p:FamilyName>Mustermann1</p:FamilyName> + </p:Name> + <p:DateOfBirth>1984-01-24</p:DateOfBirth> + </p:PhysicalPerson> + <p:PostalAddress> + <p:CountryCode>AT</p:CountryCode> + <p:PostalCode>1010</p:PostalCode> + <p:Municipality>Wien</p:Municipality> + <p:DeliveryAddress> + <p:StreetName>Muststrasse</p:StreetName> + <p:BuildingNumber>10</p:BuildingNumber> + </p:DeliveryAddress> + </p:PostalAddress> + </mzs:Receiver> + <mzs:Payload> + <mzs:DocumentReference>https://authority.gv.at/files/73bdf969781ba41fa07df1ff8439cf685c0db1c3</mzs:DocumentReference> + <mzs:FileName>brief.xml</mzs:FileName> + <mzs:MIMEType>text/xml</mzs:MIMEType> + <msg:CheckSum> + <msg:AlgorithmID>SHA1</msg:AlgorithmID> + <msg:Value>9b972c70fdaf5e1b26b3387c87b0ffb72e5940b6</msg:Value> + </msg:CheckSum> + <mzs:Size>123401</mzs:Size> + </mzs:Payload> + </mzs:DeliveryRequest> + </soapenv:Body> +</soapenv:Envelope> diff --git a/src/test/resources/at/gv/egiz/moazs/App2MzsServiceTest/validDeliveryRequest.soap b/src/test/resources/at/gv/egiz/moazs/App2MzsServiceTest/validDeliveryRequest.soap index d71939b..dcd8c5f 100644 --- a/src/test/resources/at/gv/egiz/moazs/App2MzsServiceTest/validDeliveryRequest.soap +++ b/src/test/resources/at/gv/egiz/moazs/App2MzsServiceTest/validDeliveryRequest.soap @@ -33,7 +33,7 @@ </p:PostalAddress> </mzs:Receiver> <msg:MetaData> - <msg:AppDeliveryID>asd</msg:AppDeliveryID> + <msg:AppDeliveryID>valid-delivery-request-id</msg:AppDeliveryID> <msg:Subject>WichtigeMitteilung</msg:Subject> <msg:DeliveryQuality>RSa</msg:DeliveryQuality> </msg:MetaData> |