1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.ws.client.core;
18
19 import java.io.ByteArrayOutputStream;
20 import java.io.IOException;
21 import java.util.List;
22 import javax.xml.transform.Result;
23 import javax.xml.transform.Source;
24 import javax.xml.transform.Transformer;
25 import javax.xml.transform.TransformerConfigurationException;
26 import javax.xml.transform.TransformerException;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31 import org.springframework.beans.factory.BeanInitializationException;
32 import org.springframework.core.io.ClassPathResource;
33 import org.springframework.core.io.Resource;
34 import org.springframework.oxm.Marshaller;
35 import org.springframework.oxm.Unmarshaller;
36 import org.springframework.util.Assert;
37 import org.springframework.util.ClassUtils;
38 import org.springframework.util.ObjectUtils;
39 import org.springframework.ws.FaultAwareWebServiceMessage;
40 import org.springframework.ws.WebServiceMessage;
41 import org.springframework.ws.WebServiceMessageFactory;
42 import org.springframework.ws.client.WebServiceIOException;
43 import org.springframework.ws.client.WebServiceTransformerException;
44 import org.springframework.ws.client.WebServiceTransportException;
45 import org.springframework.ws.client.support.WebServiceAccessor;
46 import org.springframework.ws.soap.client.core.SoapFaultMessageResolver;
47 import org.springframework.ws.support.MarshallingUtils;
48 import org.springframework.ws.transport.FaultAwareWebServiceConnection;
49 import org.springframework.ws.transport.TransportException;
50 import org.springframework.ws.transport.WebServiceConnection;
51 import org.springframework.ws.transport.WebServiceMessageSender;
52 import org.springframework.ws.transport.context.DefaultTransportContext;
53 import org.springframework.ws.transport.context.TransportContext;
54 import org.springframework.ws.transport.context.TransportContextHolder;
55 import org.springframework.ws.transport.http.HttpUrlConnectionMessageSender;
56 import org.springframework.ws.transport.support.DefaultStrategiesHelper;
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 public class WebServiceTemplate extends WebServiceAccessor implements WebServiceOperations {
94
95
96 public static final String MESSAGE_TRACING_LOG_CATEGORY = "org.springframework.ws.client.MessageTracing";
97
98
99 protected static final Log messageTracingLogger =
100 LogFactory.getLog(WebServiceTemplate.MESSAGE_TRACING_LOG_CATEGORY);
101
102 private Marshaller marshaller;
103
104 private Unmarshaller unmarshaller;
105
106 private FaultMessageResolver faultMessageResolver;
107
108 private String defaultUri;
109
110 private boolean checkConnectionForFault = true;
111
112
113 public WebServiceTemplate() {
114 initDefaultStrategies();
115 }
116
117
118
119
120
121
122 public WebServiceTemplate(WebServiceMessageFactory messageFactory) {
123 setMessageFactory(messageFactory);
124 initDefaultStrategies();
125 }
126
127
128 public String getDefaultUri() {
129 return defaultUri;
130 }
131
132
133
134
135
136
137
138
139
140
141
142
143 public void setDefaultUri(String uri) {
144 defaultUri = uri;
145 }
146
147
148 public Marshaller getMarshaller() {
149 return marshaller;
150 }
151
152
153 public void setMarshaller(Marshaller marshaller) {
154 this.marshaller = marshaller;
155 }
156
157
158 public Unmarshaller getUnmarshaller() {
159 return unmarshaller;
160 }
161
162
163 public void setUnmarshaller(Unmarshaller unmarshaller) {
164 this.unmarshaller = unmarshaller;
165 }
166
167
168 public FaultMessageResolver getFaultMessageResolver() {
169 return faultMessageResolver;
170 }
171
172
173
174
175
176 public void setFaultMessageResolver(FaultMessageResolver faultMessageResolver) {
177 this.faultMessageResolver = faultMessageResolver;
178 }
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195 public void setCheckConnectionForFault(boolean checkConnectionForFault) {
196 this.checkConnectionForFault = checkConnectionForFault;
197 }
198
199
200
201
202
203
204
205
206
207
208 protected void initDefaultStrategies() {
209 Resource resource = new ClassPathResource(ClassUtils.getShortName(getClass()) + ".properties", getClass());
210 DefaultStrategiesHelper strategiesHelper = new DefaultStrategiesHelper(resource);
211 if (getMessageFactory() == null) {
212 initMessageFactory(strategiesHelper);
213 }
214 if (ObjectUtils.isEmpty(getMessageSenders())) {
215 initMessageSenders(strategiesHelper);
216 }
217 if (getFaultMessageResolver() == null) {
218 initFaultMessageResolver(strategiesHelper);
219 }
220 }
221
222 private void initMessageFactory(DefaultStrategiesHelper helper) throws BeanInitializationException {
223 WebServiceMessageFactory messageFactory = (WebServiceMessageFactory) helper
224 .getDefaultStrategy(WebServiceMessageFactory.class);
225 setMessageFactory(messageFactory);
226 }
227
228 private void initMessageSenders(DefaultStrategiesHelper helper) {
229 List messageSenders = helper.getDefaultStrategies(WebServiceMessageSender.class);
230 setMessageSenders(
231 (WebServiceMessageSender[]) messageSenders.toArray(new WebServiceMessageSender[messageSenders.size()]));
232 }
233
234 private void initFaultMessageResolver(DefaultStrategiesHelper helper) throws BeanInitializationException {
235 FaultMessageResolver faultMessageResolver =
236 (FaultMessageResolver) helper.getDefaultStrategy(FaultMessageResolver.class);
237 setFaultMessageResolver(faultMessageResolver);
238 }
239
240
241
242
243
244 public Object marshalSendAndReceive(final Object requestPayload) {
245 return marshalSendAndReceive(requestPayload, null);
246 }
247
248 public Object marshalSendAndReceive(String uri, final Object requestPayload) {
249 return marshalSendAndReceive(uri, requestPayload, null);
250 }
251
252 public Object marshalSendAndReceive(final Object requestPayload, final WebServiceMessageCallback requestCallback) {
253 return marshalSendAndReceive(getDefaultUri(), requestPayload, requestCallback);
254 }
255
256 public Object marshalSendAndReceive(String uri,
257 final Object requestPayload,
258 final WebServiceMessageCallback requestCallback) {
259 if (getMarshaller() == null) {
260 throw new IllegalStateException("No marshaller registered. Check configuration of WebServiceTemplate.");
261 }
262 if (getUnmarshaller() == null) {
263 throw new IllegalStateException("No unmarshaller registered. Check configuration of WebServiceTemplate.");
264 }
265 return sendAndReceive(uri, new WebServiceMessageCallback() {
266
267 public void doWithMessage(WebServiceMessage request) throws IOException, TransformerException {
268 MarshallingUtils.marshal(getMarshaller(), requestPayload, request);
269 if (requestCallback != null) {
270 requestCallback.doWithMessage(request);
271 }
272 }
273 }, new WebServiceMessageExtractor() {
274
275 public Object extractData(WebServiceMessage response) throws IOException {
276 return MarshallingUtils.unmarshal(getUnmarshaller(), response);
277 }
278 });
279 }
280
281
282
283
284
285 public boolean sendSourceAndReceiveToResult(Source requestPayload, Result responseResult) {
286 return sendSourceAndReceiveToResult(requestPayload, null, responseResult);
287 }
288
289 public boolean sendSourceAndReceiveToResult(String uri, Source requestPayload, Result responseResult) {
290 return sendSourceAndReceiveToResult(uri, requestPayload, null, responseResult);
291 }
292
293 public boolean sendSourceAndReceiveToResult(Source requestPayload,
294 WebServiceMessageCallback requestCallback,
295 final Result responseResult) {
296 return sendSourceAndReceiveToResult(getDefaultUri(), requestPayload, requestCallback, responseResult);
297 }
298
299 public boolean sendSourceAndReceiveToResult(String uri,
300 Source requestPayload,
301 WebServiceMessageCallback requestCallback,
302 final Result responseResult) {
303 try {
304 final Transformer transformer = createTransformer();
305 Boolean retVal = (Boolean) doSendAndReceive(uri, transformer, requestPayload, requestCallback,
306 new SourceExtractor() {
307
308 public Object extractData(Source source) throws IOException, TransformerException {
309 transformer.transform(source, responseResult);
310 return Boolean.TRUE;
311 }
312 });
313 return retVal != null && retVal.booleanValue();
314 }
315 catch (TransformerConfigurationException ex) {
316 throw new WebServiceTransformerException("Could not create transformer", ex);
317 }
318 }
319
320
321
322
323
324 public Object sendSourceAndReceive(final Source requestPayload, final SourceExtractor responseExtractor) {
325 return sendSourceAndReceive(requestPayload, null, responseExtractor);
326 }
327
328 public Object sendSourceAndReceive(String uri,
329 final Source requestPayload,
330 final SourceExtractor responseExtractor) {
331 return sendSourceAndReceive(uri, requestPayload, null, responseExtractor);
332 }
333
334 public Object sendSourceAndReceive(final Source requestPayload,
335 final WebServiceMessageCallback requestCallback,
336 final SourceExtractor responseExtractor) {
337 return sendSourceAndReceive(getDefaultUri(), requestPayload, requestCallback, responseExtractor);
338 }
339
340 public Object sendSourceAndReceive(String uri,
341 final Source requestPayload,
342 final WebServiceMessageCallback requestCallback,
343 final SourceExtractor responseExtractor) {
344
345 try {
346 return doSendAndReceive(uri, createTransformer(), requestPayload, requestCallback, responseExtractor);
347 }
348 catch (TransformerConfigurationException ex) {
349 throw new WebServiceTransformerException("Could not create transformer", ex);
350 }
351 }
352
353 private Object doSendAndReceive(String uri,
354 final Transformer transformer,
355 final Source requestPayload,
356 final WebServiceMessageCallback requestCallback,
357 final SourceExtractor responseExtractor) {
358 Assert.notNull(responseExtractor, "responseExtractor must not be null");
359 return sendAndReceive(uri, new WebServiceMessageCallback() {
360 public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
361 transformer.transform(requestPayload, message.getPayloadResult());
362 if (requestCallback != null) {
363 requestCallback.doWithMessage(message);
364 }
365 }
366 }, new SourceExtractorMessageExtractor(responseExtractor));
367 }
368
369
370
371
372
373 public boolean sendAndReceive(WebServiceMessageCallback requestCallback,
374 WebServiceMessageCallback responseCallback) {
375 return sendAndReceive(getDefaultUri(), requestCallback, responseCallback);
376 }
377
378 public boolean sendAndReceive(String uri,
379 WebServiceMessageCallback requestCallback,
380 WebServiceMessageCallback responseCallback) {
381 Assert.notNull(responseCallback, "responseCallback must not be null");
382 Boolean result = (Boolean) sendAndReceive(uri, requestCallback,
383 new WebServiceMessageCallbackMessageExtractor(responseCallback));
384 return result != null && result.booleanValue();
385 }
386
387 public Object sendAndReceive(WebServiceMessageCallback requestCallback,
388 WebServiceMessageExtractor responseExtractor) {
389 return sendAndReceive(getDefaultUri(), requestCallback, responseExtractor);
390 }
391
392 public Object sendAndReceive(String uri,
393 WebServiceMessageCallback requestCallback,
394 WebServiceMessageExtractor responseExtractor) {
395 Assert.notNull(responseExtractor, "'responseExtractor' must not be null");
396 Assert.hasLength(uri, "'uri' must not be empty");
397 TransportContext previousTransportContext = TransportContextHolder.getTransportContext();
398 WebServiceConnection connection = null;
399 try {
400 connection = createConnection(uri);
401 TransportContextHolder.setTransportContext(new DefaultTransportContext(connection));
402 WebServiceMessage request = getMessageFactory().createWebServiceMessage();
403 if (requestCallback != null) {
404 requestCallback.doWithMessage(request);
405 }
406 sendRequest(connection, request);
407 if (hasError(connection, request)) {
408 return handleError(connection, request);
409 }
410 WebServiceMessage response = connection.receive(getMessageFactory());
411 if (response != null) {
412 if (hasFault(connection, response)) {
413 return handleFault(connection, request, response);
414 }
415 else {
416 logResponse(request, response);
417 return responseExtractor.extractData(response);
418 }
419 }
420 else {
421 if (logger.isDebugEnabled()) {
422 logger.debug("Received no response for request [" + request + "]");
423 }
424 return null;
425 }
426 }
427 catch (TransportException ex) {
428 throw new WebServiceTransportException("Could not use transport: " + ex.getMessage(), ex);
429 }
430 catch (TransformerException ex) {
431 throw new WebServiceTransformerException("Transformation error: " + ex.getMessage(), ex);
432 }
433 catch (IOException ex) {
434 throw new WebServiceIOException("I/O error: " + ex.getMessage(), ex);
435 }
436 finally {
437 if (connection != null) {
438 try {
439 connection.close();
440 }
441 catch (IOException ex) {
442 logger.debug("Could not close WebServiceConnection", ex);
443 }
444 }
445 TransportContextHolder.setTransportContext(previousTransportContext);
446 }
447 }
448
449
450
451
452
453
454
455
456
457
458
459
460 protected boolean hasError(WebServiceConnection connection, WebServiceMessage request) throws IOException {
461 if (connection.hasError() && checkConnectionForFault) {
462 if (connection instanceof FaultAwareWebServiceConnection) {
463 FaultAwareWebServiceConnection faultConnection = (FaultAwareWebServiceConnection) connection;
464 return !(faultConnection.hasFault() && request instanceof FaultAwareWebServiceMessage);
465 }
466 else {
467 return true;
468 }
469 }
470 return false;
471 }
472
473
474
475
476
477
478
479
480
481
482 protected Object handleError(WebServiceConnection connection, WebServiceMessage request) throws IOException {
483 throw new WebServiceTransportException(connection.getErrorMessage());
484 }
485
486
487
488
489
490
491
492
493
494
495
496
497
498 protected boolean hasFault(WebServiceConnection connection, WebServiceMessage response) throws IOException {
499 if (checkConnectionForFault && connection instanceof FaultAwareWebServiceConnection) {
500
501 FaultAwareWebServiceConnection faultConnection = (FaultAwareWebServiceConnection) connection;
502 if (!faultConnection.hasFault()) {
503 return false;
504 }
505 }
506 if (response instanceof FaultAwareWebServiceMessage) {
507
508 FaultAwareWebServiceMessage faultMessage = (FaultAwareWebServiceMessage) response;
509 return faultMessage.hasFault();
510 }
511 return false;
512 }
513
514
515
516
517
518
519
520
521
522
523
524
525 protected Object handleFault(WebServiceConnection connection, WebServiceMessage request, WebServiceMessage response)
526 throws IOException {
527 if (getFaultMessageResolver() != null) {
528 logger.debug("Received Fault message for request [" + request + "]");
529 getFaultMessageResolver().resolveFault(response);
530 return null;
531 }
532 else {
533 return handleError(connection, request);
534 }
535 }
536
537
538 private void sendRequest(WebServiceConnection connection, WebServiceMessage request) throws IOException {
539 if (messageTracingLogger.isTraceEnabled()) {
540 ByteArrayOutputStream os = new ByteArrayOutputStream();
541 request.writeTo(os);
542 messageTracingLogger.trace("Sent request [" + os.toString("UTF-8") + "]");
543 }
544 else if (messageTracingLogger.isDebugEnabled()) {
545 messageTracingLogger.debug("Sent request [" + request + "]");
546 }
547 connection.send(request);
548 }
549
550 private void logResponse(WebServiceMessage request, WebServiceMessage response) throws IOException {
551 if (messageTracingLogger.isTraceEnabled()) {
552 ByteArrayOutputStream requestStream = new ByteArrayOutputStream();
553 request.writeTo(requestStream);
554 ByteArrayOutputStream responseStream = new ByteArrayOutputStream();
555 response.writeTo(responseStream);
556 messageTracingLogger.trace("Received response [" + responseStream.toString("UTF-8") + "] for request [" +
557 requestStream.toString("UTF-8") + "]");
558 }
559 else if (messageTracingLogger.isDebugEnabled()) {
560 messageTracingLogger.debug("Received response [" + response + "] for request [" + request + "]");
561 }
562 }
563
564
565 private static class WebServiceMessageCallbackMessageExtractor implements WebServiceMessageExtractor {
566
567 private final WebServiceMessageCallback callback;
568
569 private WebServiceMessageCallbackMessageExtractor(WebServiceMessageCallback callback) {
570 this.callback = callback;
571 }
572
573 public Object extractData(WebServiceMessage message) throws IOException, TransformerException {
574 callback.doWithMessage(message);
575 return Boolean.TRUE;
576 }
577 }
578
579
580 private static class SourceExtractorMessageExtractor implements WebServiceMessageExtractor {
581
582 private final SourceExtractor sourceExtractor;
583
584 private SourceExtractorMessageExtractor(SourceExtractor sourceExtractor) {
585 this.sourceExtractor = sourceExtractor;
586 }
587
588 public Object extractData(WebServiceMessage message) throws IOException, TransformerException {
589 return sourceExtractor.extractData(message.getPayloadSource());
590 }
591 }
592
593 }