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.net.URI;
22 import java.util.List;
23 import javax.xml.transform.Result;
24 import javax.xml.transform.Source;
25 import javax.xml.transform.Transformer;
26 import javax.xml.transform.TransformerConfigurationException;
27 import javax.xml.transform.TransformerException;
28
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31
32 import org.springframework.beans.factory.BeanInitializationException;
33 import org.springframework.core.io.ClassPathResource;
34 import org.springframework.core.io.Resource;
35 import org.springframework.oxm.Marshaller;
36 import org.springframework.oxm.Unmarshaller;
37 import org.springframework.util.Assert;
38 import org.springframework.util.ClassUtils;
39 import org.springframework.util.ObjectUtils;
40 import org.springframework.ws.FaultAwareWebServiceMessage;
41 import org.springframework.ws.WebServiceMessage;
42 import org.springframework.ws.WebServiceMessageFactory;
43 import org.springframework.ws.client.WebServiceClientException;
44 import org.springframework.ws.client.WebServiceIOException;
45 import org.springframework.ws.client.WebServiceTransformerException;
46 import org.springframework.ws.client.WebServiceTransportException;
47 import org.springframework.ws.client.support.WebServiceAccessor;
48 import org.springframework.ws.client.support.destination.DestinationProvider;
49 import org.springframework.ws.client.support.interceptor.ClientInterceptor;
50 import org.springframework.ws.context.DefaultMessageContext;
51 import org.springframework.ws.context.MessageContext;
52 import org.springframework.ws.soap.client.core.SoapFaultMessageResolver;
53 import org.springframework.ws.support.DefaultStrategiesHelper;
54 import org.springframework.ws.support.MarshallingUtils;
55 import org.springframework.ws.transport.FaultAwareWebServiceConnection;
56 import org.springframework.ws.transport.TransportException;
57 import org.springframework.ws.transport.WebServiceConnection;
58 import org.springframework.ws.transport.WebServiceMessageSender;
59 import org.springframework.ws.transport.context.DefaultTransportContext;
60 import org.springframework.ws.transport.context.TransportContext;
61 import org.springframework.ws.transport.context.TransportContextHolder;
62 import org.springframework.ws.transport.http.HttpUrlConnectionMessageSender;
63 import org.springframework.ws.transport.support.TransportUtils;
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
94
95
96
97
98
99
100
101
102
103
104 public class WebServiceTemplate extends WebServiceAccessor implements WebServiceOperations {
105
106
107 public static final String MESSAGE_TRACING_LOG_CATEGORY = "org.springframework.ws.client.MessageTracing";
108
109
110 protected static final Log sentMessageTracingLogger =
111 LogFactory.getLog(WebServiceTemplate.MESSAGE_TRACING_LOG_CATEGORY + ".sent");
112
113
114 protected static final Log receivedMessageTracingLogger =
115 LogFactory.getLog(WebServiceTemplate.MESSAGE_TRACING_LOG_CATEGORY + ".received");
116
117 private Marshaller marshaller;
118
119 private Unmarshaller unmarshaller;
120
121 private FaultMessageResolver faultMessageResolver;
122
123 private boolean checkConnectionForError = true;
124
125 private boolean checkConnectionForFault = true;
126
127 private ClientInterceptor[] interceptors;
128
129 private DestinationProvider destinationProvider;
130
131
132 public WebServiceTemplate() {
133 initDefaultStrategies();
134 }
135
136
137
138
139
140
141 public WebServiceTemplate(WebServiceMessageFactory messageFactory) {
142 setMessageFactory(messageFactory);
143 initDefaultStrategies();
144 }
145
146
147 public String getDefaultUri() {
148 if (destinationProvider != null) {
149 URI uri = destinationProvider.getDestination();
150 return uri != null ? uri.toString() : null;
151 }
152 else {
153 return null;
154 }
155 }
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170 public void setDefaultUri(final String uri) {
171 destinationProvider = new DestinationProvider() {
172
173 public URI getDestination() {
174 return URI.create(uri);
175 }
176 };
177 }
178
179
180 public DestinationProvider getDestinationProvider() {
181 return destinationProvider;
182 }
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197 public void setDestinationProvider(DestinationProvider destinationProvider) {
198 this.destinationProvider = destinationProvider;
199 }
200
201
202 public Marshaller getMarshaller() {
203 return marshaller;
204 }
205
206
207 public void setMarshaller(Marshaller marshaller) {
208 this.marshaller = marshaller;
209 }
210
211
212 public Unmarshaller getUnmarshaller() {
213 return unmarshaller;
214 }
215
216
217 public void setUnmarshaller(Unmarshaller unmarshaller) {
218 this.unmarshaller = unmarshaller;
219 }
220
221
222 public FaultMessageResolver getFaultMessageResolver() {
223 return faultMessageResolver;
224 }
225
226
227
228
229
230 public void setFaultMessageResolver(FaultMessageResolver faultMessageResolver) {
231 this.faultMessageResolver = faultMessageResolver;
232 }
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249 public void setCheckConnectionForError(boolean checkConnectionForError) {
250 this.checkConnectionForError = checkConnectionForError;
251 }
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268 public void setCheckConnectionForFault(boolean checkConnectionForFault) {
269 this.checkConnectionForFault = checkConnectionForFault;
270 }
271
272
273
274
275
276
277 public ClientInterceptor[] getInterceptors() {
278 return interceptors;
279 }
280
281
282
283
284
285
286 public final void setInterceptors(ClientInterceptor[] interceptors) {
287 this.interceptors = interceptors;
288 }
289
290
291
292
293
294
295
296
297
298
299 protected void initDefaultStrategies() {
300 Resource resource = new ClassPathResource(ClassUtils.getShortName(WebServiceTemplate.class) + ".properties",
301 WebServiceTemplate.class);
302 DefaultStrategiesHelper strategiesHelper = new DefaultStrategiesHelper(resource);
303 if (getMessageFactory() == null) {
304 initMessageFactory(strategiesHelper);
305 }
306 if (ObjectUtils.isEmpty(getMessageSenders())) {
307 initMessageSenders(strategiesHelper);
308 }
309 if (getFaultMessageResolver() == null) {
310 initFaultMessageResolver(strategiesHelper);
311 }
312 }
313
314 private void initMessageFactory(DefaultStrategiesHelper helper) throws BeanInitializationException {
315 WebServiceMessageFactory messageFactory =
316 (WebServiceMessageFactory) helper.getDefaultStrategy(WebServiceMessageFactory.class);
317 setMessageFactory(messageFactory);
318 }
319
320 private void initMessageSenders(DefaultStrategiesHelper helper) {
321 List messageSenders = helper.getDefaultStrategies(WebServiceMessageSender.class);
322 setMessageSenders(
323 (WebServiceMessageSender[]) messageSenders.toArray(new WebServiceMessageSender[messageSenders.size()]));
324 }
325
326 private void initFaultMessageResolver(DefaultStrategiesHelper helper) throws BeanInitializationException {
327 FaultMessageResolver faultMessageResolver =
328 (FaultMessageResolver) helper.getDefaultStrategy(FaultMessageResolver.class);
329 setFaultMessageResolver(faultMessageResolver);
330 }
331
332
333
334
335
336 public Object marshalSendAndReceive(final Object requestPayload) {
337 return marshalSendAndReceive(requestPayload, null);
338 }
339
340 public Object marshalSendAndReceive(String uri, final Object requestPayload) {
341 return marshalSendAndReceive(uri, requestPayload, null);
342 }
343
344 public Object marshalSendAndReceive(final Object requestPayload, final WebServiceMessageCallback requestCallback) {
345 return marshalSendAndReceive(getDefaultUri(), requestPayload, requestCallback);
346 }
347
348 public Object marshalSendAndReceive(String uri,
349 final Object requestPayload,
350 final WebServiceMessageCallback requestCallback) {
351 return sendAndReceive(uri, new WebServiceMessageCallback() {
352
353 public void doWithMessage(WebServiceMessage request) throws IOException, TransformerException {
354 if (requestPayload != null) {
355 Marshaller marshaller = getMarshaller();
356 if (marshaller == null) {
357 throw new IllegalStateException(
358 "No marshaller registered. Check configuration of WebServiceTemplate.");
359 }
360 MarshallingUtils.marshal(marshaller, requestPayload, request);
361 if (requestCallback != null) {
362 requestCallback.doWithMessage(request);
363 }
364 }
365 }
366 }, new WebServiceMessageExtractor() {
367
368 public Object extractData(WebServiceMessage response) throws IOException {
369 Unmarshaller unmarshaller = getUnmarshaller();
370 if (unmarshaller == null) {
371 throw new IllegalStateException(
372 "No unmarshaller registered. Check configuration of WebServiceTemplate.");
373 }
374 return MarshallingUtils.unmarshal(unmarshaller, response);
375 }
376 });
377 }
378
379
380
381
382
383 public boolean sendSourceAndReceiveToResult(Source requestPayload, Result responseResult) {
384 return sendSourceAndReceiveToResult(requestPayload, null, responseResult);
385 }
386
387 public boolean sendSourceAndReceiveToResult(String uri, Source requestPayload, Result responseResult) {
388 return sendSourceAndReceiveToResult(uri, requestPayload, null, responseResult);
389 }
390
391 public boolean sendSourceAndReceiveToResult(Source requestPayload,
392 WebServiceMessageCallback requestCallback,
393 final Result responseResult) {
394 return sendSourceAndReceiveToResult(getDefaultUri(), requestPayload, requestCallback, responseResult);
395 }
396
397 public boolean sendSourceAndReceiveToResult(String uri,
398 Source requestPayload,
399 WebServiceMessageCallback requestCallback,
400 final Result responseResult) {
401 try {
402 final Transformer transformer = createTransformer();
403 Boolean retVal = (Boolean) doSendAndReceive(uri, transformer, requestPayload, requestCallback,
404 new SourceExtractor() {
405
406 public Object extractData(Source source) throws IOException, TransformerException {
407 transformer.transform(source, responseResult);
408 return Boolean.TRUE;
409 }
410 });
411 return retVal != null && retVal.booleanValue();
412 }
413 catch (TransformerConfigurationException ex) {
414 throw new WebServiceTransformerException("Could not create transformer", ex);
415 }
416 }
417
418
419
420
421
422 public Object sendSourceAndReceive(final Source requestPayload, final SourceExtractor responseExtractor) {
423 return sendSourceAndReceive(requestPayload, null, responseExtractor);
424 }
425
426 public Object sendSourceAndReceive(String uri,
427 final Source requestPayload,
428 final SourceExtractor responseExtractor) {
429 return sendSourceAndReceive(uri, requestPayload, null, responseExtractor);
430 }
431
432 public Object sendSourceAndReceive(final Source requestPayload,
433 final WebServiceMessageCallback requestCallback,
434 final SourceExtractor responseExtractor) {
435 return sendSourceAndReceive(getDefaultUri(), requestPayload, requestCallback, responseExtractor);
436 }
437
438 public Object sendSourceAndReceive(String uri,
439 final Source requestPayload,
440 final WebServiceMessageCallback requestCallback,
441 final SourceExtractor responseExtractor) {
442
443 try {
444 return doSendAndReceive(uri, createTransformer(), requestPayload, requestCallback, responseExtractor);
445 }
446 catch (TransformerConfigurationException ex) {
447 throw new WebServiceTransformerException("Could not create transformer", ex);
448 }
449 }
450
451 private Object doSendAndReceive(String uri,
452 final Transformer transformer,
453 final Source requestPayload,
454 final WebServiceMessageCallback requestCallback,
455 final SourceExtractor responseExtractor) {
456 Assert.notNull(responseExtractor, "responseExtractor must not be null");
457 return sendAndReceive(uri, new WebServiceMessageCallback() {
458 public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
459 transformer.transform(requestPayload, message.getPayloadResult());
460 if (requestCallback != null) {
461 requestCallback.doWithMessage(message);
462 }
463 }
464 }, new SourceExtractorMessageExtractor(responseExtractor));
465 }
466
467
468
469
470
471 public boolean sendAndReceive(WebServiceMessageCallback requestCallback,
472 WebServiceMessageCallback responseCallback) {
473 return sendAndReceive(getDefaultUri(), requestCallback, responseCallback);
474 }
475
476 public boolean sendAndReceive(String uri,
477 WebServiceMessageCallback requestCallback,
478 WebServiceMessageCallback responseCallback) {
479 Assert.notNull(responseCallback, "responseCallback must not be null");
480 Boolean result = (Boolean) sendAndReceive(uri, requestCallback,
481 new WebServiceMessageCallbackMessageExtractor(responseCallback));
482 return result != null && result.booleanValue();
483 }
484
485 public Object sendAndReceive(WebServiceMessageCallback requestCallback,
486 WebServiceMessageExtractor responseExtractor) {
487 return sendAndReceive(getDefaultUri(), requestCallback, responseExtractor);
488 }
489
490 public Object sendAndReceive(String uriString,
491 WebServiceMessageCallback requestCallback,
492 WebServiceMessageExtractor responseExtractor) {
493 Assert.notNull(responseExtractor, "'responseExtractor' must not be null");
494 Assert.hasLength(uriString, "'uri' must not be empty");
495 TransportContext previousTransportContext = TransportContextHolder.getTransportContext();
496 WebServiceConnection connection = null;
497 try {
498 connection = createConnection(URI.create(uriString));
499 TransportContextHolder.setTransportContext(new DefaultTransportContext(connection));
500 MessageContext messageContext = new DefaultMessageContext(getMessageFactory());
501
502 return doSendAndReceive(messageContext, connection, requestCallback, responseExtractor);
503 }
504 catch (TransportException ex) {
505 throw new WebServiceTransportException("Could not use transport: " + ex.getMessage(), ex);
506 }
507 catch (IOException ex) {
508 throw new WebServiceIOException("I/O error: " + ex.getMessage(), ex);
509 }
510 finally {
511 TransportUtils.closeConnection(connection);
512 TransportContextHolder.setTransportContext(previousTransportContext);
513 }
514 }
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529 protected Object doSendAndReceive(MessageContext messageContext,
530 WebServiceConnection connection,
531 WebServiceMessageCallback requestCallback,
532 WebServiceMessageExtractor responseExtractor) throws IOException {
533 try {
534 if (requestCallback != null) {
535 requestCallback.doWithMessage(messageContext.getRequest());
536 }
537
538 int interceptorIndex = -1;
539 if (interceptors != null) {
540 for (int i = 0; i < interceptors.length; i++) {
541 interceptorIndex = i;
542 if (!interceptors[i].handleRequest(messageContext)) {
543 break;
544 }
545 }
546 }
547
548 if (!messageContext.hasResponse()) {
549 sendRequest(connection, messageContext.getRequest());
550 if (hasError(connection, messageContext.getRequest())) {
551 return handleError(connection, messageContext.getRequest());
552 }
553 WebServiceMessage response = connection.receive(getMessageFactory());
554 messageContext.setResponse(response);
555 }
556 logResponse(messageContext);
557 if (messageContext.hasResponse()) {
558 if (!hasFault(connection, messageContext.getResponse())) {
559 triggerHandleResponse(interceptorIndex, messageContext);
560 return responseExtractor.extractData(messageContext.getResponse());
561 }
562 else {
563 triggerHandleFault(interceptorIndex, messageContext);
564 return handleFault(connection, messageContext);
565 }
566 }
567 else {
568 return null;
569 }
570 }
571 catch (TransformerException ex) {
572 throw new WebServiceTransformerException("Transformation error: " + ex.getMessage(), ex);
573 }
574 }
575
576
577 private void sendRequest(WebServiceConnection connection, WebServiceMessage request) throws IOException {
578 if (sentMessageTracingLogger.isTraceEnabled()) {
579 ByteArrayOutputStream os = new ByteArrayOutputStream();
580 request.writeTo(os);
581 sentMessageTracingLogger.trace("Sent request [" + os.toString("UTF-8") + "]");
582 }
583 else if (sentMessageTracingLogger.isDebugEnabled()) {
584 sentMessageTracingLogger.debug("Sent request [" + request + "]");
585 }
586 connection.send(request);
587 }
588
589
590
591
592
593
594
595
596
597
598
599
600 protected boolean hasError(WebServiceConnection connection, WebServiceMessage request) throws IOException {
601 if (checkConnectionForError && connection.hasError()) {
602
603 if (checkConnectionForFault && connection instanceof FaultAwareWebServiceConnection) {
604 FaultAwareWebServiceConnection faultConnection = (FaultAwareWebServiceConnection) connection;
605 return !(faultConnection.hasFault() && request instanceof FaultAwareWebServiceMessage);
606 }
607 else {
608 return true;
609 }
610 }
611 return false;
612 }
613
614
615
616
617
618
619
620
621
622
623 protected Object handleError(WebServiceConnection connection, WebServiceMessage request) throws IOException {
624 if (logger.isDebugEnabled()) {
625 logger.debug("Received error for request [" + request + "]");
626 }
627 throw new WebServiceTransportException(connection.getErrorMessage());
628 }
629
630 private void logResponse(MessageContext messageContext) throws IOException {
631 if (messageContext.hasResponse()) {
632 if (receivedMessageTracingLogger.isTraceEnabled()) {
633 ByteArrayOutputStream requestStream = new ByteArrayOutputStream();
634 messageContext.getRequest().writeTo(requestStream);
635 ByteArrayOutputStream responseStream = new ByteArrayOutputStream();
636 messageContext.getResponse().writeTo(responseStream);
637 receivedMessageTracingLogger
638 .trace("Received response [" + responseStream.toString("UTF-8") + "] for request [" +
639 requestStream.toString("UTF-8") + "]");
640 }
641 else if (receivedMessageTracingLogger.isDebugEnabled()) {
642 receivedMessageTracingLogger
643 .debug("Received response [" + messageContext.getResponse() + "] for request [" +
644 messageContext.getRequest() + "]");
645 }
646 }
647 else {
648 if (logger.isDebugEnabled()) {
649 receivedMessageTracingLogger
650 .debug("Received no response for request [" + messageContext.getRequest() + "]");
651 }
652 }
653 }
654
655
656
657
658
659
660
661
662
663
664
665
666
667 protected boolean hasFault(WebServiceConnection connection, WebServiceMessage response) throws IOException {
668 if (checkConnectionForFault && connection instanceof FaultAwareWebServiceConnection) {
669
670 FaultAwareWebServiceConnection faultConnection = (FaultAwareWebServiceConnection) connection;
671 if (!faultConnection.hasFault()) {
672 return false;
673 }
674 }
675 if (response instanceof FaultAwareWebServiceMessage) {
676
677 FaultAwareWebServiceMessage faultMessage = (FaultAwareWebServiceMessage) response;
678 return faultMessage.hasFault();
679 }
680 return false;
681 }
682
683
684
685
686
687
688
689
690
691
692
693 private void triggerHandleResponse(int interceptorIndex, MessageContext messageContext) {
694 if (messageContext.hasResponse() && interceptors != null) {
695 for (int i = interceptorIndex; i >= 0; i--) {
696 if (!interceptors[i].handleResponse(messageContext)) {
697 break;
698 }
699 }
700 }
701 }
702
703
704
705
706
707
708
709
710
711
712
713 private void triggerHandleFault(int interceptorIndex, MessageContext messageContext) {
714 if (messageContext.hasResponse() && interceptors != null) {
715 for (int i = interceptorIndex; i >= 0; i--) {
716 if (!interceptors[i].handleFault(messageContext)) {
717 break;
718 }
719 }
720 }
721 }
722
723
724
725
726
727
728
729
730
731
732
733 protected Object handleFault(WebServiceConnection connection, MessageContext messageContext) throws IOException {
734 if (logger.isDebugEnabled()) {
735 logger.debug("Received Fault message for request [" + messageContext.getRequest() + "]");
736 }
737 if (getFaultMessageResolver() != null) {
738 getFaultMessageResolver().resolveFault(messageContext.getResponse());
739 return null;
740 }
741 else {
742 return handleError(connection, messageContext.getRequest());
743 }
744 }
745
746
747 private static class WebServiceMessageCallbackMessageExtractor implements WebServiceMessageExtractor {
748
749 private final WebServiceMessageCallback callback;
750
751 private WebServiceMessageCallbackMessageExtractor(WebServiceMessageCallback callback) {
752 this.callback = callback;
753 }
754
755 public Object extractData(WebServiceMessage message) throws IOException, TransformerException {
756 callback.doWithMessage(message);
757 return Boolean.TRUE;
758 }
759 }
760
761
762 private static class SourceExtractorMessageExtractor implements WebServiceMessageExtractor {
763
764 private final SourceExtractor sourceExtractor;
765
766 private SourceExtractorMessageExtractor(SourceExtractor sourceExtractor) {
767 this.sourceExtractor = sourceExtractor;
768 }
769
770 public Object extractData(WebServiceMessage message) throws IOException, TransformerException {
771 return sourceExtractor.extractData(message.getPayloadSource());
772 }
773 }
774
775 }