001package ca.uhn.fhir.jpa.subscription.match.deliver; 002 003/*- 004 * #%L 005 * HAPI FHIR Subscription Server 006 * %% 007 * Copyright (C) 2014 - 2022 Smile CDR, Inc. 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import ca.uhn.fhir.i18n.Msg; 024import ca.uhn.fhir.context.FhirContext; 025import ca.uhn.fhir.i18n.Msg; 026import ca.uhn.fhir.interceptor.api.HookParams; 027import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; 028import ca.uhn.fhir.interceptor.api.Pointcut; 029import ca.uhn.fhir.jpa.subscription.match.registry.ActiveSubscription; 030import ca.uhn.fhir.jpa.subscription.match.registry.SubscriptionRegistry; 031import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription; 032import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryMessage; 033import com.google.common.annotations.VisibleForTesting; 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036import org.springframework.beans.factory.annotation.Autowired; 037import org.springframework.messaging.Message; 038import org.springframework.messaging.MessageHandler; 039import org.springframework.messaging.MessagingException; 040 041public abstract class BaseSubscriptionDeliverySubscriber implements MessageHandler { 042 private static final Logger ourLog = LoggerFactory.getLogger(BaseSubscriptionDeliverySubscriber.class); 043 044 @Autowired 045 protected FhirContext myFhirContext; 046 @Autowired 047 protected SubscriptionRegistry mySubscriptionRegistry; 048 @Autowired 049 private IInterceptorBroadcaster myInterceptorBroadcaster; 050 051 @Override 052 public void handleMessage(Message theMessage) throws MessagingException { 053 if (!(theMessage.getPayload() instanceof ResourceDeliveryMessage)) { 054 ourLog.warn("Unexpected payload type: {}", theMessage.getPayload()); 055 return; 056 } 057 058 ResourceDeliveryMessage msg = (ResourceDeliveryMessage) theMessage.getPayload(); 059 String subscriptionId = msg.getSubscriptionId(myFhirContext); 060 if (subscriptionId == null) { 061 ourLog.warn("Subscription has no ID, ignoring"); 062 return; 063 } 064 065 ActiveSubscription updatedSubscription = mySubscriptionRegistry.get(msg.getSubscription().getIdElement(myFhirContext).getIdPart()); 066 if (updatedSubscription != null) { 067 msg.setSubscription(updatedSubscription.getSubscription()); 068 } 069 070 try { 071 072 // Interceptor call: SUBSCRIPTION_BEFORE_DELIVERY 073 HookParams params = new HookParams() 074 .add(ResourceDeliveryMessage.class, msg) 075 .add(CanonicalSubscription.class, msg.getSubscription()); 076 if (!myInterceptorBroadcaster.callHooks(Pointcut.SUBSCRIPTION_BEFORE_DELIVERY, params)) { 077 return; 078 } 079 080 handleMessage(msg); 081 082 // Interceptor call: SUBSCRIPTION_AFTER_DELIVERY 083 myInterceptorBroadcaster.callHooks(Pointcut.SUBSCRIPTION_AFTER_DELIVERY, params); 084 085 } catch (Exception e) { 086 087 String errorMsg = "Failure handling subscription payload for subscription: " + subscriptionId; 088 ourLog.error(errorMsg, e); 089 090 // Interceptor call: SUBSCRIPTION_AFTER_DELIVERY 091 HookParams hookParams = new HookParams() 092 .add(ResourceDeliveryMessage.class, msg) 093 .add(Exception.class, e); 094 if (!myInterceptorBroadcaster.callHooks(Pointcut.SUBSCRIPTION_AFTER_DELIVERY_FAILED, hookParams)) { 095 return; 096 } 097 098 throw new MessagingException(theMessage, Msg.code(2) + errorMsg, e); 099 } 100 } 101 102 public abstract void handleMessage(ResourceDeliveryMessage theMessage) throws Exception; 103 104 @VisibleForTesting 105 public void setFhirContextForUnitTest(FhirContext theCtx) { 106 myFhirContext = theCtx; 107 } 108 109 @VisibleForTesting 110 public void setInterceptorBroadcasterForUnitTest(IInterceptorBroadcaster theInterceptorBroadcaster) { 111 myInterceptorBroadcaster = theInterceptorBroadcaster; 112 } 113 114 @VisibleForTesting 115 public void setSubscriptionRegistryForUnitTest(SubscriptionRegistry theSubscriptionRegistry) { 116 mySubscriptionRegistry = theSubscriptionRegistry; 117 } 118 119 public IInterceptorBroadcaster getInterceptorBroadcaster() { 120 return myInterceptorBroadcaster; 121 } 122}