001package ca.uhn.hl7v2.hoh.relay.sender; 002 003import java.io.IOException; 004import java.net.ConnectException; 005import java.util.Map; 006 007import org.springframework.beans.factory.BeanNameAware; 008import org.springframework.beans.factory.InitializingBean; 009 010import ca.uhn.hl7v2.HL7Exception; 011import ca.uhn.hl7v2.hoh.api.DecodeException; 012import ca.uhn.hl7v2.hoh.api.EncodeException; 013import ca.uhn.hl7v2.hoh.api.IReceivable; 014import ca.uhn.hl7v2.hoh.hapi.api.MessageSendable; 015import ca.uhn.hl7v2.hoh.hapi.client.HohClientMultithreaded; 016import ca.uhn.hl7v2.hoh.relay.Binder; 017import ca.uhn.hl7v2.hoh.util.Validate; 018import ca.uhn.hl7v2.model.Message; 019import ca.uhn.hl7v2.protocol.ApplicationRouter; 020import ca.uhn.hl7v2.protocol.MetadataKeys; 021import ca.uhn.hl7v2.protocol.ReceivingApplicationException; 022import ca.uhn.hl7v2.util.Terser; 023 024public class RelayHttpSender extends HohClientMultithreaded implements IRelaySender<Message>, BeanNameAware, InitializingBean { 025 026 private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RelayHttpSender.class); 027 private String myBeanName; 028 private int myIoRetries = 0; 029 030 /** 031 * {@inheritDoc} 032 */ 033 public void afterPropertiesSet() throws Exception { 034 Validate.propertySet(getUrl(), "Url"); 035 ourLog.info("Sender [{}] will transmit by HL7 over HTTP to {}", myBeanName, getUrl().toExternalForm()); 036 } 037 038 /** 039 * Returns true 040 * 041 * {@inheritDoc} 042 */ 043 public boolean canProcess(Message theMessage) { 044 return true; 045 } 046 047 /** 048 * {@inheritDoc} 049 */ 050 public String getBeanName() { 051 return myBeanName; 052 } 053 054 /** 055 * @see #setIoRetries(int) 056 */ 057 public int getIoRetries() { 058 return myIoRetries; 059 } 060 061 /** 062 * {@inheritDoc} 063 */ 064 public Message processMessage(Message theMessage, Map<String, Object> theMetadata) throws ReceivingApplicationException, HL7Exception { 065 String sendingIp = (String) theMetadata.get(ApplicationRouter.METADATA_KEY_SENDING_IP); 066 Object sendingPort = theMetadata.get(ApplicationRouter.METADATA_KEY_SENDING_PORT); 067 String controlId = (String) theMetadata.get(ApplicationRouter.METADATA_KEY_MESSAGE_CONTROL_ID); 068 String rawMessage = (String) theMetadata.get(MetadataKeys.IN_RAW_MESSAGE); 069 070 ourLog.info("Relaying message ({} bytes) with ID {} from {}:{} to URL {}", new Object[] {rawMessage.length(), controlId, sendingIp, sendingPort, getUrl()}); 071 072 IReceivable<Message> response; 073 long delay = System.currentTimeMillis(); 074 int attempt = -1; 075 while(true) { 076 attempt++; 077 078 if (attempt > 0) { 079 ourLog.info("This is attempt {}", attempt); 080 } 081 082 try { 083 response = sendAndReceiveMessage(new MessageSendable(theMessage)); 084 delay = System.currentTimeMillis() - delay; 085 } catch (DecodeException e) { 086 ourLog.error("Failed to process HL7 over HTTP response from URL \"" + getUrl().toExternalForm() + "\"", e); 087 throw new HL7Exception(Binder.getProductname() + " - Failed to process HL7 over HTTP response from URL \"" + getUrl().toExternalForm() + "\" - Error was: " + e.getMessage()); 088 } catch (ConnectException e) { 089 ourLog.info("Failed to connect to URL \"" + getUrl().toExternalForm() + "\" - Error was: " + e.getMessage()); 090 throw new HL7Exception(Binder.getProductname() + " - Failed to connect to URL \"" + getUrl().toExternalForm() + "\" - Error was: " + e.getMessage()); 091 } catch (IOException e) { 092 if (attempt < myIoRetries) { 093 ourLog.warn("Got an IOException, going to retry transmission: " + e.toString()); 094 continue; 095 } 096 ourLog.error("IO Exception communicating with URL \"" + getUrl().toExternalForm() + "\"", e); 097 throw new HL7Exception(Binder.getProductname() + " - IO Exception communicating with URL URL \"" + getUrl().toExternalForm() + "\" - Error was: " + e.getMessage()); 098 } catch (EncodeException e) { 099 ourLog.error("Failed to create HTTP request", e); 100 throw new HL7Exception(Binder.getProductname() + " - Failed to create HTTP request - Error was: " + e.getMessage()); 101 } 102 103 break; 104 } 105 106 String responseControlId = new Terser(response.getMessage()).get("/MSH-10"); 107 ourLog.info("Received response to ID {} with ID {} in {} ms", new Object[] {controlId, responseControlId, delay}); 108 109 return response.getMessage(); 110 } 111 112 /** 113 * <i>Automatically called by the container</i> 114 */ 115 public void setBeanName(String theBeanName) { 116 myBeanName = theBeanName; 117 } 118 119 /** 120 * If set to a positive integer, the relay will attempt to redeliver a message up to the given 121 * number of times before giving up, if the transmission fails due to an IO exception. 122 */ 123 public void setIoRetries(int theIoRetries) { 124 myIoRetries = theIoRetries; 125 } 126 127 128}