diff options
author | Christof Rabensteiner <christof.rabensteiner@iaik.tugraz.at> | 2019-05-23 10:20:38 +0200 |
---|---|---|
committer | Christof Rabensteiner <christof.rabensteiner@iaik.tugraz.at> | 2019-05-23 10:26:08 +0200 |
commit | 7665997a90c87a400f92ae9bf1ec6cc5a3099e16 (patch) | |
tree | f8a143a834a9204fbdfc64591ce0f61b60cb495b /src | |
parent | 59a13bea5783aa666bcbcec793df19f129965ff3 (diff) | |
download | moa-zs-7665997a90c87a400f92ae9bf1ec6cc5a3099e16.tar.gz moa-zs-7665997a90c87a400f92ae9bf1ec6cc5a3099e16.tar.bz2 moa-zs-7665997a90c87a400f92ae9bf1ec6cc5a3099e16.zip |
MZS Schema Changes + Changes in Interface
- MZS cant reply with a msg:DeliveryRequestStatusType to a
mzs:DeliveryRequest. Reason: unmarshalling a
msg:DeliveryRequestStatusType with JAXB (after receiving the msg
reply) breaks the signature in msg:DeliveryRequestStatusType. Why?
Because JAXB marshalling tinkers with the namespaces and, as for the
current state of knowledge, we cannot configure the JAXB marshaller
to reconstruct a XML Document byte-by-byte such that a signature
that went through this process can be verified successfully (see [1]).
- For this reason, we revert back to mzs:DeliveryResponse and add new
fields / remove obsolete fields / capture all changes between zusemsg
1.5.3 and zusemsg 2.0.0.
- The easier solution would be to wrap and transmit signed data +
signature in a binary (base64) container, such that apache cxf and
other web service frameworks won't unmarshall them. This doesnt work
because zusemsg 2.0.0 is final.
app2mzs.xsd Changes in Detail :
- Add DeliverySystem, ZSDeliveryID and GZ to MessageType (MessageType
is the base type of DeliveryResponse.Success, -PartialSuccess, and
-Error); Reason: It was added to zusemsg 2.0.0.
- Add SignedDeliveryRequestStatus to MessageType. Reason: If msg
returns signed reply, this element contains the reply as byte[] such
that the signature does not break.
- Add optional PreadvicenoteSend to ErrorType (because it was added in
zusemsg 2.0.0)
- Remove MZSDeliveryID from every instance because this ID does not
exist anymore (moa zs does not maintain requests in a database).
- Remove DocumentReference from ErrorType as it was removed from
zusemsg 2.0.0.
- Remove DeliveryConfirmation as node in DeliveryNotificiationType
because it does not exist anymore in zusemsg 2.0.0;
DeliveryConfirmation is also obsolete because all msg' replies are
signed and need to be transferred to the sender application as a
byte[], which is done by SignedDeliveryRequestStatus node in
MessageType.
- Remove DeliveryStatement as node in DeliveryNotificiationType
because it does not exist anymore in zusemsg 2.0.0.
Other Changes
- Adapt codebase: MzsService returns mzs:DeliveryResponse.
- Implement conversion from msg:DeliveryRequestStatus to
mzs:DeliveryResponse.
- Add store / retrieve interface to DeliveryRepository that stores
signed delivery request statuses as byte[].
Temporary Changes
- Disable integration tests which have external dependencies.
[1] https://download.oracle.com/javaee-archive/jaxb.java.net/users/2007/03/6674.html
Signed-off-by: Christof Rabensteiner <christof.rabensteiner@iaik.tugraz.at>
Diffstat (limited to 'src')
9 files changed, 152 insertions, 46 deletions
diff --git a/src/main/java/at/gv/egiz/moazs/MoaZSException.java b/src/main/java/at/gv/egiz/moazs/MoaZSException.java index ad211bd..11d9b4e 100644 --- a/src/main/java/at/gv/egiz/moazs/MoaZSException.java +++ b/src/main/java/at/gv/egiz/moazs/MoaZSException.java @@ -13,4 +13,8 @@ public class MoaZSException extends RuntimeException { return new MoaZSException(String.format(formatString, objects)); } + public static MoaZSException moaZSException(String message) { + return new MoaZSException(String.format(message)); + } + } diff --git a/src/main/java/at/gv/egiz/moazs/mzs/MzsClient.java b/src/main/java/at/gv/egiz/moazs/mzs/MzsClient.java index 5785703..295d11a 100644 --- a/src/main/java/at/gv/egiz/moazs/mzs/MzsClient.java +++ b/src/main/java/at/gv/egiz/moazs/mzs/MzsClient.java @@ -1,12 +1,13 @@ package at.gv.egiz.moazs.mzs; +import at.gv.zustellung.app2mzs.xsd.DeliveryResponseType; import at.gv.zustellung.msg.xsd.DeliveryRequestStatusType; import org.springframework.stereotype.Component; @Component public class MzsClient { - public void sendNotification(DeliveryRequestStatusType status) { + public void sendNotification(DeliveryResponseType responseType) { throw new UnsupportedOperationException("Not implemented."); } diff --git a/src/main/java/at/gv/egiz/moazs/mzs/MzsService.java b/src/main/java/at/gv/egiz/moazs/mzs/MzsService.java index 774f7f4..e031b0b 100644 --- a/src/main/java/at/gv/egiz/moazs/mzs/MzsService.java +++ b/src/main/java/at/gv/egiz/moazs/mzs/MzsService.java @@ -4,8 +4,13 @@ import at.gv.egiz.moazs.MoaZSException; import at.gv.egiz.moazs.pipeline.DeliveryPipeline; import at.gv.egiz.moazs.preprocess.DeliveryRequestAugmenter; import at.gv.egiz.moazs.repository.DeliveryRepository; +import at.gv.egiz.moazs.scheme.Msg2MzsConverter; +import at.gv.egiz.moazs.scheme.Mzs2MsgConverter; import at.gv.zustellung.app2mzs.xsd.App2MzsPortType; import at.gv.zustellung.app2mzs.xsd.DeliveryRequestType; +import at.gv.zustellung.app2mzs.xsd.DeliveryResponseType; +import at.gv.zustellung.app2mzs.xsd.PartialSuccessType; +import at.gv.zustellung.msg.xsd.DeliveryAnswerType; import at.gv.zustellung.msg.xsd.DeliveryRequestStatusType; import org.apache.cxf.annotations.SchemaValidation; import org.slf4j.Logger; @@ -18,8 +23,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static at.gv.egiz.moazs.MoaZSException.moaZSException; -import static at.gv.zustellung.msg.xsd.DeliveryAnswerType.deliveryAnswerTypeBuilder; -import static at.gv.zustellung.msg.xsd.DeliveryRequestStatusType.deliveryRequestStatusTypeBuilder; +import static at.gv.zustellung.app2mzs.xsd.PartialSuccessType.partialSuccessTypeBuilder; import static java.lang.String.format; import static java.util.concurrent.CompletableFuture.supplyAsync; @@ -37,18 +41,20 @@ public class MzsService implements App2MzsPortType { private final DeliveryPipeline pipeline; private final MzsClient appClient; private final DeliveryRequestAugmenter augmenter; + private final Msg2MzsConverter converter; @Autowired public MzsService(DeliveryRepository repository, DeliveryPipeline pipeline, MzsClient appClient, - DeliveryRequestAugmenter augmenter) { + DeliveryRequestAugmenter augmenter, Msg2MzsConverter converter) { this.repository = repository; this.pipeline = pipeline; this.appClient = appClient; this.augmenter = augmenter; + this.converter = converter; } @Override - public DeliveryRequestStatusType app2Mzs( + public DeliveryResponseType app2Mzs( @WebParam(partName = "DeliveryRequest", name = "DeliveryRequest") DeliveryRequestType deliveryRequest) { @@ -56,13 +62,15 @@ public class MzsService implements App2MzsPortType { var appDeliveryID = deliveryRequest.getMetaData().getAppDeliveryID(); var future = supplyAsync(() -> augmenter.augment(deliveryRequest)) - .thenApply(this::process); + .thenApply(this::process) + .thenApply(status -> converter.convert(status, repository.getSignedDeliveryRequestStatus(appDeliveryID))); try { return future.get(TIMEOUT_FOR_ANWSER, TimeUnit.SECONDS); } catch (TimeoutException e) { - future.thenAccept(appClient::sendNotification); logger.info("Answer Timed Out", e); + + future.thenAccept(appClient::sendNotification); return generatePartialSuccessResponse(appDeliveryID); } catch (Exception e ) { @@ -86,14 +94,14 @@ public class MzsService implements App2MzsPortType { } - private DeliveryRequestStatusType generatePartialSuccessResponse(String appDeliveryId) { + private DeliveryResponseType generatePartialSuccessResponse(String appDeliveryId) { - var answer = deliveryAnswerTypeBuilder() + var partial = partialSuccessTypeBuilder() .withAppDeliveryID(appDeliveryId) .build(); - return deliveryRequestStatusTypeBuilder() - .withPartialSuccess(answer) + return DeliveryResponseType.deliveryResponseTypeBuilder() + .withPartialSuccess(partial) .build(); } diff --git a/src/main/java/at/gv/egiz/moazs/repository/DeliveryRepository.java b/src/main/java/at/gv/egiz/moazs/repository/DeliveryRepository.java index 228d55e..be61d1e 100644 --- a/src/main/java/at/gv/egiz/moazs/repository/DeliveryRepository.java +++ b/src/main/java/at/gv/egiz/moazs/repository/DeliveryRepository.java @@ -17,5 +17,9 @@ public interface DeliveryRepository { Optional<DeliveryRequestStatusType> getDeliveryRequestStatus(String appDeliveryID); + void addSignedDeliveryRequestStatus(byte[] bytes, String appDeliveryId); + + Optional<byte[]> getSignedDeliveryRequestStatus(String appDeliveryID); + } diff --git a/src/main/java/at/gv/egiz/moazs/repository/InMemoryDeliveryRepository.java b/src/main/java/at/gv/egiz/moazs/repository/InMemoryDeliveryRepository.java index 570296f..58ec92c 100644 --- a/src/main/java/at/gv/egiz/moazs/repository/InMemoryDeliveryRepository.java +++ b/src/main/java/at/gv/egiz/moazs/repository/InMemoryDeliveryRepository.java @@ -30,6 +30,10 @@ public class InMemoryDeliveryRepository implements DeliveryRepository { .expireAfterWrite(30, TimeUnit.MINUTES) .build(); + private static final Cache<String, byte[]> signedStatusRepository = CacheBuilder.newBuilder() + .expireAfterWrite(30, TimeUnit.MINUTES) + .build(); + @Override public void add(DeliveryRequestType request) { var key = request.getMetaData().getAppDeliveryID(); @@ -38,8 +42,7 @@ public class InMemoryDeliveryRepository implements DeliveryRepository { @Override public Optional<DeliveryRequestType> getDeliveryRequest(String appDeliveryID) { - var deliveryRequestType = requestRepository.getIfPresent(appDeliveryID); - return ofNullable(deliveryRequestType); + return ofNullable(requestRepository.getIfPresent(appDeliveryID)); } @Override @@ -51,7 +54,16 @@ public class InMemoryDeliveryRepository implements DeliveryRepository { @Override public Optional<DeliveryRequestStatusType> getDeliveryRequestStatus(String appDeliveryID) { - var deliveryRequestType = statusRepository.getIfPresent(appDeliveryID); - return ofNullable(deliveryRequestType); + return ofNullable(statusRepository.getIfPresent(appDeliveryID)); + } + + @Override + public void addSignedDeliveryRequestStatus(byte[] bytes, String appDeliveryId) { + signedStatusRepository.put(appDeliveryId, bytes); + } + + @Override + public Optional<byte[]> getSignedDeliveryRequestStatus(String appDeliveryID) { + return ofNullable(signedStatusRepository.getIfPresent(appDeliveryID)); } } diff --git a/src/main/java/at/gv/egiz/moazs/repository/RedisDeliveryRepository.java b/src/main/java/at/gv/egiz/moazs/repository/RedisDeliveryRepository.java index c24902d..4ffe85d 100644 --- a/src/main/java/at/gv/egiz/moazs/repository/RedisDeliveryRepository.java +++ b/src/main/java/at/gv/egiz/moazs/repository/RedisDeliveryRepository.java @@ -69,4 +69,14 @@ public class RedisDeliveryRepository implements DeliveryRepository { public Optional<DeliveryRequestStatusType> getDeliveryRequestStatus(String appDeliveryID) { throw new UnsupportedOperationException("Not Implemented Yet"); } + + @Override + public void addSignedDeliveryRequestStatus(byte[] bytes, String appDeliveryId) { + throw new UnsupportedOperationException("Not Implemented Yet"); + } + + @Override + public Optional<byte[]> getSignedDeliveryRequestStatus(String appDeliveryID) { + return Optional.empty(); + } } diff --git a/src/main/java/at/gv/egiz/moazs/scheme/Msg2MzsConverter.java b/src/main/java/at/gv/egiz/moazs/scheme/Msg2MzsConverter.java new file mode 100644 index 0000000..67f3d13 --- /dev/null +++ b/src/main/java/at/gv/egiz/moazs/scheme/Msg2MzsConverter.java @@ -0,0 +1,75 @@ +package at.gv.egiz.moazs.scheme; + +import at.gv.zustellung.app2mzs.xsd.DeliveryResponseType; +import at.gv.zustellung.app2mzs.xsd.ErrorType; +import at.gv.zustellung.app2mzs.xsd.PartialSuccessType; +import at.gv.zustellung.app2mzs.xsd.SuccessType; +import at.gv.zustellung.msg.xsd.DeliveryAnswerType; +import at.gv.zustellung.msg.xsd.DeliveryRequestStatusType; +import org.springframework.stereotype.Component; + +import java.math.BigInteger; +import java.util.Optional; + +import static at.gv.zustellung.app2mzs.xsd.DeliveryResponseType.deliveryResponseTypeBuilder; +import static at.gv.zustellung.app2mzs.xsd.ErrorType.errorTypeBuilder; +import static at.gv.zustellung.app2mzs.xsd.PartialSuccessType.partialSuccessTypeBuilder; +import static at.gv.zustellung.app2mzs.xsd.SuccessType.successTypeBuilder; + +@Component +public class Msg2MzsConverter { + + public DeliveryResponseType convert(DeliveryRequestStatusType status, Optional<byte[]> signedStatus) { + + var responseBuilder = deliveryResponseTypeBuilder(); + + if (status.getError() != null) { + responseBuilder.withError(convert(status.getError(), signedStatus)); + } else if (status.getSuccess() != null) { + responseBuilder.withSuccess(convert(status.getSuccess(), signedStatus)); + } else { + responseBuilder.withPartialSuccess(convert(status.getPartialSuccess(), signedStatus)); + } + + return responseBuilder.build(); + } + + private SuccessType convert(DeliveryRequestStatusType.Success success, Optional<byte[]> signedStatus) { + return successTypeBuilder() + .withAppDeliveryID(success.getAppDeliveryID()) + .withDeliverySystem(success.getDeliverySystem()) + .withGZ(success.getGZ()) + .withZSDeliveryID(success.getZSDeliveryID()) + .withSignedDeliveryRequestStatus(signedStatus.orElse(null)) + .withRelayedViaERV(success.isRelayedViaERV()) + .withDeliveryTimestamp(success.getDeliveryTimestamp()) + .build(); + } + + private PartialSuccessType convert(DeliveryAnswerType answer, Optional<byte[]> signedStatus) { + return partialSuccessTypeBuilder() + .withAppDeliveryID(answer.getAppDeliveryID()) + .withDeliverySystem(answer.getDeliverySystem()) + .withGZ(answer.getGZ()) + .withZSDeliveryID(answer.getZSDeliveryID()) + .withSignedDeliveryRequestStatus(signedStatus.orElse(null)) + .build(); + } + + private ErrorType convert(DeliveryRequestStatusType.Error error, Optional<byte[]> signedStatus) { + var builder = errorTypeBuilder() + .withAppDeliveryID(error.getAppDeliveryID()) + .withDeliverySystem(error.getDeliverySystem()) + .withGZ(error.getGZ()) + .withZSDeliveryID(error.getZSDeliveryID()) + .withSignedDeliveryRequestStatus(signedStatus.orElse(null)) + .withPreAdviceNoteSent(error.getPreAdviceNoteSent()) + .withCode(new BigInteger(error.getErrorInfo().getCode())); + + if(error.getErrorInfo().getText() != null) builder.withText(error.getErrorInfo().getText()); + + return builder.build(); + } + + +} diff --git a/src/main/resources/mzs/app2mzs.xsd b/src/main/resources/mzs/app2mzs.xsd index 74a63db..05a9ea4 100644 --- a/src/main/resources/mzs/app2mzs.xsd +++ b/src/main/resources/mzs/app2mzs.xsd @@ -92,7 +92,14 @@ <xs:element name="X509" type="xs:base64Binary" minOccurs="0"/> </xs:sequence> </xs:complexType> - <xs:element name="DeliveryResponse" type="msg:DeliveryRequestStatusType"/> + <xs:element name="DeliveryResponse" type="DeliveryResponseType"/> + <xs:complexType name="DeliveryResponseType"> + <xs:choice> + <xs:element ref="PartialSuccess"/> + <xs:element ref="Success"/> + <xs:element ref="Error"/> + </xs:choice> + </xs:complexType> <xs:element name="DeliveryNotification" type="DeliveryNotificationType"> <xs:annotation> <xs:documentation>asynchronous communication moazs2app</xs:documentation> @@ -102,8 +109,6 @@ <xs:choice> <xs:element ref="Success"/> <xs:element ref="Error"/> - <xs:element name="DeliveryConfirmation" type="xs:base64Binary"/> - <xs:element ref="DeliveryStatement"/> </xs:choice> </xs:complexType> <xs:element name="DeliveryNotificationACK" type="DeliveryNotificationACKType"> @@ -114,7 +119,6 @@ <xs:complexType name="DeliveryNotificationACKType"> <xs:sequence> <xs:element ref="AppDeliveryID"/> - <xs:element ref="MZSDeliveryID"/> </xs:sequence> </xs:complexType> <xs:element name="AppDeliveryID" nillable="false"> @@ -125,7 +129,6 @@ </xs:restriction> </xs:simpleType> </xs:element> - <xs:element name="MZSDeliveryID" type="xs:string"/> <xs:element name="Success" type="SuccessType"> <xs:annotation> <xs:documentation>Zustellstück was successfully delivered to MOA-ZS</xs:documentation> @@ -133,7 +136,12 @@ </xs:element> <xs:complexType name="SuccessType"> <xs:complexContent> - <xs:extension base="MessageType"/> + <xs:extension base="MessageType"> + <xs:sequence> + <xs:element ref="msg:DeliveryTimestamp"/> + <xs:element ref="msg:RelayedViaERV" minOccurs="0"/> + </xs:sequence> + </xs:extension> </xs:complexContent> </xs:complexType> <xs:element name="PartialSuccess" type="PartialSuccessType"> @@ -157,27 +165,7 @@ <xs:sequence> <xs:element name="Code" type="xs:integer"/> <xs:element name="Text" type="xs:string"/> - <xs:element name="DocumentReference" type="xs:anyURI" minOccurs="0"> - <xs:annotation> - <xs:documentation>download of callback attachment failed</xs:documentation> - </xs:annotation> - </xs:element> - </xs:sequence> - </xs:extension> - </xs:complexContent> - </xs:complexType> - <xs:element name="DeliveryStatement" type="DeliveryStatementType"> - <xs:annotation> - <xs:documentation>Zustellstück was successfully forwarded to the Zustellserver</xs:documentation> - </xs:annotation> - </xs:element> - <xs:complexType name="DeliveryStatementType"> - <xs:complexContent> - <xs:extension base="MessageType"> - <xs:sequence> - <xs:element name="DeliveryServer" type="xs:anyURI"/> - <xs:element name="ZSDeliveryID" type="xs:token"/> - <xs:element name="Timestamp" type="xs:dateTime"/> + <xs:element ref="msg:PreAdviceNoteSent" minOccurs="0"/> </xs:sequence> </xs:extension> </xs:complexContent> @@ -188,7 +176,10 @@ </xs:annotation> <xs:sequence> <xs:element ref="AppDeliveryID"/> - <xs:element ref="MZSDeliveryID"/> + <xs:element ref="msg:DeliverySystem"/> + <xs:element ref="msg:ZSDeliveryID" /> + <xs:element ref="msg:GZ" minOccurs="0"/> + <xs:element name="SignedDeliveryRequestStatus" type="xs:base64Binary" minOccurs="0"/> </xs:sequence> </xs:complexType> diff --git a/src/test/java/at/gv/egiz/moazs/MsgClientTest.java b/src/test/java/at/gv/egiz/moazs/MsgClientTest.java index 5b6419f..9d79435 100644 --- a/src/test/java/at/gv/egiz/moazs/MsgClientTest.java +++ b/src/test/java/at/gv/egiz/moazs/MsgClientTest.java @@ -23,8 +23,8 @@ import static at.gv.zustellung.app2mzs.xsd.ConfigType.configTypeBuilder; import static at.gv.zustellung.app2mzs.xsd.ServerType.serverTypeBuilder; -@RunWith(SpringRunner.class) -@SpringBootTest +//@RunWith(SpringRunner.class) +//@SpringBootTest public class MsgClientTest { private final static Logger logger = LoggerFactory.getLogger(MsgClient.class); @@ -44,7 +44,8 @@ public class MsgClientTest { // this test requires that a zusemsg service runs under httpServiceUri! - @Test + //tmp disabled. todo: set up integration tests + //@Test public void sendValidMessage() throws IOException { var request = loadFromFile("validDeliveryRequest.xml"); |