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