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