/******************************************************************************* * Copyright 2019 Graz University of Technology * MOA ZS has been developed in a cooperation between EGIZ * and Graz University of Technology. * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. *******************************************************************************/ package at.gv.egiz.moazs.service; import at.gv.egiz.moazs.backend.MsgResponseBackend; import at.gv.egiz.moazs.repository.DeliveryRepository; import at.gv.egiz.moazs.scheme.MsgResponse; import at.gv.egiz.moazs.scheme.NameSpace; import at.gv.egiz.moazs.scheme.NotificationResponse; import at.gv.egiz.moazs.scheme.RequestStatusResponse; import at.gv.zustellung.msg.xsd.*; import org.apache.cxf.annotations.SchemaValidation; import org.apache.cxf.binding.soap.SoapFault; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.task.TaskExecutor; import org.springframework.stereotype.Service; import javax.xml.namespace.QName; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import static at.gv.zustellung.msg.xsd.DeliveryNotificationACKType.deliveryNotificationACKTypeBuilder; import static at.gv.zustellung.msg.xsd.DeliveryRequestStatusACKType.deliveryRequestStatusACKTypeBuilder; import static at.gv.zustellung.msg.xsd.GetVersionResponse.getVersionResponseBuilder; import static java.lang.String.format; import static java.util.concurrent.CompletableFuture.runAsync; /** * @author Christof Rabensteiner * */ @Service @SchemaValidation(type = SchemaValidation.SchemaValidationType.BOTH) @org.apache.cxf.feature.Features (features = "org.apache.cxf.ext.logging.LoggingFeature") public class MsgService implements Zuse2AppPort { private static final Logger log = LoggerFactory.getLogger(MsgService.class); private static final String BACKEND_ERROR_MSG = "Could not process %s."; private final DeliveryRepository repository; private final MsgResponseBackend backend; private final TaskExecutor taskExecutor; @Autowired public MsgService(DeliveryRepository repository, MsgResponseBackend msgResponseBackend, TaskExecutor taskExecutor) { this.repository = repository; this.backend = msgResponseBackend; this.taskExecutor = taskExecutor; } @Override public GetVersionResponse getVersion(SimpleRequestType getVersionRequest) { return getVersionResponseBuilder() .withVersion(NameSpace.MSG_VERSION) .build(); } @Override public DeliveryRequestStatusACKType status(DeliveryRequestStatusType status) { var response = new RequestStatusResponse(status); try { sendToBackend(response).get(); return statusAck(response.getAppDeliveryID(), response.getZSDeliveryID()); } catch (InterruptedException | ExecutionException e) { var message = format(BACKEND_ERROR_MSG, "request status"); log.error(message, e); throw toFault(e, message); } } private DeliveryRequestStatusACKType statusAck(String appDeliveryID, String zsDeliveryID) { return deliveryRequestStatusACKTypeBuilder() .withAppDeliveryID(appDeliveryID) .withZSDeliveryID(zsDeliveryID) .withVersion(NameSpace.MSG_VERSION) .build(); } @Override public DeliveryNotificationACKType notification(DeliveryNotificationType notification) { var response = new NotificationResponse(notification); try { sendToBackend(response).get(); return notificationAck(response.getAppDeliveryID(), response.getZSDeliveryID()); } catch (InterruptedException | ExecutionException e) { var message = format(BACKEND_ERROR_MSG, "delivery notification"); log.error(message, e); throw toFault(e, message); } } private RuntimeException toFault(Exception e, String fallbackMessage) { Throwable cause = (e.getCause() != null) ? e.getCause() : e; return new SoapFault(fallbackMessage, cause, new QName("faultcode")); } private CompletableFuture sendToBackend(MsgResponse response) { return runAsync(() -> repository.store(response), taskExecutor) .thenCompose(ignore -> backend.accept(response.getResponseID())); } private DeliveryNotificationACKType notificationAck(String appDeliveryID, String zsDeliveryID) { return deliveryNotificationACKTypeBuilder() .withAppDeliveryID(appDeliveryID) .withZSDeliveryID(zsDeliveryID) .withVersion(NameSpace.MSG_VERSION) .build(); } }