1
2
3
4
5
6
7
8
9
10
11
12
13
14 package uk.nhs.interoperability.consumer;
15
16 import java.io.IOException;
17
18 import javax.servlet.ServletException;
19 import javax.servlet.http.HttpServletRequest;
20 import javax.servlet.http.HttpServletResponse;
21 import javax.xml.parsers.ParserConfigurationException;
22 import javax.xml.xpath.XPathConstants;
23 import javax.xml.xpath.XPathExpressionException;
24
25 import org.w3c.dom.Document;
26 import org.w3c.dom.Node;
27 import org.xml.sax.SAXException;
28
29 import com.xmlsolutions.annotation.Requirement;
30
31 import uk.nhs.interoperability.capabilities.AuditException;
32 import uk.nhs.interoperability.capabilities.AuditService;
33 import uk.nhs.interoperability.consumer.ITKMessageConsumer;
34 import uk.nhs.interoperability.infrastructure.ITKMessagePropertiesImpl;
35 import uk.nhs.interoperability.infrastructure.ITKMessagingException;
36 import uk.nhs.interoperability.infrastructure.ITKTransportPropertiesImpl;
37 import uk.nhs.interoperability.payload.ITKMessage;
38 import uk.nhs.interoperability.payload.SimpleMessage;
39 import uk.nhs.interoperability.service.ITKSimpleAudit;
40 import uk.nhs.interoperability.transport.ITKTransportProperties;
41 import uk.nhs.interoperability.transport.WS.ITKSOAPException;
42 import uk.nhs.interoperability.transport.WS.WSSOAPMessageImpl;
43 import uk.nhs.interoperability.util.Logger;
44 import uk.nhs.interoperability.util.ServletUtils;
45 import uk.nhs.interoperability.util.StringUtils;
46 import uk.nhs.interoperability.util.xml.DomUtils;
47 import uk.nhs.interoperability.util.xml.XPaths;
48
49
50
51
52
53
54
55
56 @SuppressWarnings("serial")
57 public abstract class AbstractSimpleMessageServlet extends ITKServlet {
58
59
60
61 private ITKMessageConsumer messageConsumer;
62
63
64
65
66 @Override
67 public void init() throws ServletException {
68 this.messageConsumer = getMessageConsumer();
69 super.init();
70 }
71
72
73
74
75
76
77 public abstract ITKMessageConsumer getMessageConsumer();
78
79
80
81
82 @Override
83 @Requirement(traceTo={"WS-PAT-01"})
84 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
85 Logger.debug("Received a message");
86
87 try {
88 byte[] requestMsg = ServletUtils.readRequestContent(req);
89 if (requestMsg == null) {
90 throw new ITKMessagingException(ITKMessagingException.INVALID_MESSAGE_CODE, "The request did not contain any content");
91 }
92 String requestString = new String(requestMsg);
93 ITKMessage responseMsg = this.processMessage(requestString);
94
95
96 if (responseMsg == null) {
97 resp.setStatus(HttpServletResponse.SC_ACCEPTED);
98 Logger.trace("Replying HTTP 202");
99 return;
100 }
101 Logger.trace("Response business payload:" + responseMsg.getFullPayload());
102
103
104
105
106 ITKMessage response = new WSSOAPMessageImpl(responseMsg, WSSOAPMessageImpl.SYNCRESP);
107
108 resp.getWriter().write(response.getFullPayload());
109 return;
110 } catch (ITKMessagingException e) {
111 Logger.error("Could not process message", e);
112 resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
113 resp.getWriter().write(new ITKSOAPException(e).serialiseXML());
114 } catch (Throwable t) {
115 Logger.error("Could not process message - general error", t);
116 resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
117 resp.getWriter().write(t.getLocalizedMessage());
118 } finally {
119 Logger.debug("Completed processing");
120 }
121 }
122
123
124
125
126
127
128
129
130 @Requirement(traceTo={"WS-PAT-01"})
131 private ITKMessage processMessage(String requestString) throws ITKMessagingException {
132 ITKTransportProperties itkTransportProperties = null;
133 ITKMessagePropertiesImpl itkMessageProperties = null;
134 try {
135
136
137
138 Document doc = DomUtils.parse(requestString);
139
140 Logger.trace(DomUtils.serialiseToXML(doc, DomUtils.PRETTY_PRINT));
141
142
143
144 itkTransportProperties = ITKTransportPropertiesImpl.buildFromSoap(doc);
145
146
147
148 Document de = ITKMessagePropertiesImpl.extractDistributionEnvelopeFromSoap(doc);
149
150 itkMessageProperties = (ITKMessagePropertiesImpl) ITKMessagePropertiesImpl.build(de);
151
152 this.validateDistributionEnvelope(itkMessageProperties);
153
154 itkMessageProperties.setInboundTransportProperties(itkTransportProperties);
155
156
157
158 Document businessPayload = DomUtils.createDocumentFromNode((Node)XPaths.SOAP_WRAPPED_ITK_FIRST_PAYLOAD_XPATH.evaluate(doc, XPathConstants.NODE));
159 String businessPayloadXML = DomUtils.serialiseToXML(businessPayload);
160
161 Logger.trace(DomUtils.serialiseToXML(businessPayload, DomUtils.PRETTY_PRINT));
162
163
164
165
166 ITKMessage requestMsg = new SimpleMessage(itkMessageProperties, businessPayloadXML);
167
168
169 ITKMessage response = null;
170
171 if (StringUtils.hasValue(itkTransportProperties.getTransportReplyTo())) {
172
173
174
175
176 this.messageConsumer.onMessage(requestMsg);
177 } else {
178
179
180
181
182 response = this.messageConsumer.onSyncMessage(requestMsg);
183 }
184
185 ITKSimpleAudit.getInstance().auditEvent(AuditService.MESSAGE_RECEIPT_EVENT, System.currentTimeMillis(), itkMessageProperties);
186
187
188
189 response = this.addITKWrappers(response);
190
191 return response;
192 } catch (XPathExpressionException e) {
193 throw new ITKMessagingException(itkTransportProperties, itkMessageProperties, ITKMessagingException.PROCESSING_ERROR_NOT_RETRYABLE_CODE, "Could not extract values from request", e);
194 } catch (IOException e) {
195 throw new ITKMessagingException(itkTransportProperties, itkMessageProperties, ITKMessagingException.PROCESSING_ERROR_NOT_RETRYABLE_CODE, "Could not parse request", e);
196 } catch (ParserConfigurationException e) {
197 throw new ITKMessagingException(itkTransportProperties, itkMessageProperties, ITKMessagingException.PROCESSING_ERROR_NOT_RETRYABLE_CODE, "XML parser configuration error", e);
198 } catch (AuditException e) {
199 throw new ITKMessagingException(itkTransportProperties, itkMessageProperties, ITKMessagingException.PROCESSING_ERROR_RETRYABLE_CODE, "Failed to write audit", e);
200 } catch (SAXException e) {
201 throw new ITKMessagingException(itkTransportProperties, itkMessageProperties, ITKMessagingException.PROCESSING_ERROR_NOT_RETRYABLE_CODE, "Error parsing request XML", e);
202 }
203 }
204
205 }