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; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.jws.WebParam; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static java.text.MessageFormat.format; import static java.util.concurrent.CompletableFuture.supplyAsync; @Service public class App2MzsService implements App2MzsPortType { private static final Logger logger = LoggerFactory.getLogger(App2MzsService.class); //TODO move timeout and namespaces to config private static final int TIMEOUT_FOR_ANWSER = 10; private static final String MZSTNS = "http://reference.e-government.gv.at/namespace/zustellung/mzs/app2mzs#"; private final DeliveryRepository repository; private final DeliveryPipeline pipeline; private final Mzs2AppClient appClient; private final ObjectFactory objectFactory = new ObjectFactory(); public App2MzsService(@Autowired DeliveryRepository repository, @Autowired DeliveryPipeline pipeline, @Autowired Mzs2AppClient appClient) { this.repository = repository; this.pipeline = pipeline; this.appClient = appClient; } @Override public DeliveryRequestStatusType app2Mzs( @WebParam(partName = "DeliveryRequest", name = "DeliveryRequest", targetNamespace = MZSTNS) DeliveryRequestType deliveryRequest) { final var appDeliveryID = deliveryRequest.getMetaData().getAppDeliveryID(); var future = supplyAsync(() -> process(deliveryRequest)); 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."); } catch (Exception e ) { logger.error("Could not deliver request.", e); final var message = format("An error occured while delivering request: {}", e.getMessage()); return generateErrorResponse(appDeliveryID, message); } } private DeliveryRequestStatusType generatePartialSuccessResponse(String appDeliveryId, String message) { var answer = new DeliveryAnswerTypeBuilder() .withAppDeliveryID(appDeliveryId) .build(); return new DeliveryRequestStatusTypeBuilder() .withPartialSuccess(answer) .build(); } private DeliveryRequestStatusType generateErrorResponse(String appDeliveryId, String message) { var info = new ErrorInfoTypeBuilder() .withCode("500") .withText(message) .build(); var error = new ErrorBuilder() .withAppDeliveryID(appDeliveryId) .withErrorInfo(info) .build(); return new DeliveryRequestStatusTypeBuilder() .withError(error) .build(); } private DeliveryRequestStatusType process(DeliveryRequestType deliveryRequest) throws RuntimeException { var appDeliveryID = deliveryRequest.getMetaData().getAppDeliveryID(); logger.info("Receive request with appDeliveryID = {}.", appDeliveryID); 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(); } }