001/* 002 * Copyright 2012-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.webservices.client; 018 019import java.net.URI; 020import java.util.Arrays; 021import java.util.Collection; 022import java.util.Collections; 023import java.util.LinkedHashSet; 024import java.util.Set; 025 026import javax.xml.transform.TransformerFactory; 027 028import org.springframework.beans.BeanUtils; 029import org.springframework.boot.context.properties.PropertyMapper; 030import org.springframework.oxm.Marshaller; 031import org.springframework.oxm.Unmarshaller; 032import org.springframework.util.Assert; 033import org.springframework.util.CollectionUtils; 034import org.springframework.ws.WebServiceMessageFactory; 035import org.springframework.ws.client.core.FaultMessageResolver; 036import org.springframework.ws.client.core.WebServiceTemplate; 037import org.springframework.ws.client.support.destination.DestinationProvider; 038import org.springframework.ws.client.support.interceptor.ClientInterceptor; 039import org.springframework.ws.transport.WebServiceMessageSender; 040 041/** 042 * Builder that can be used to configure and create a {@link WebServiceTemplate}. Provides 043 * convenience methods to register {@link #messageSenders(WebServiceMessageSender...) 044 * message senders}, {@link #interceptors(ClientInterceptor...) client interceptors} and 045 * {@link #customizers(WebServiceTemplateCustomizer...) customizers}. 046 * <p> 047 * By default the built {@link WebServiceTemplate} uses the most suitable HTTP-based 048 * {@link WebServiceMessageSender}, call {@link #detectHttpMessageSender(boolean) 049 * detectHttpMessageSender(false)} if you prefer to keep the default. In a typical 050 * auto-configured Spring Boot application this builder is available as a bean and can be 051 * injected whenever a {@link WebServiceTemplate} is needed. 052 * 053 * @author Dmytro Nosan 054 * @author Stephane Nicoll 055 * @since 2.1.0 056 */ 057public class WebServiceTemplateBuilder { 058 059 private final boolean detectHttpMessageSender; 060 061 private final Set<ClientInterceptor> interceptors; 062 063 private final Set<WebServiceTemplateCustomizer> internalCustomizers; 064 065 private final Set<WebServiceTemplateCustomizer> customizers; 066 067 private final WebServiceMessageSenders messageSenders; 068 069 private final Marshaller marshaller; 070 071 private final Unmarshaller unmarshaller; 072 073 private final DestinationProvider destinationProvider; 074 075 private final Class<? extends TransformerFactory> transformerFactoryClass; 076 077 private final WebServiceMessageFactory messageFactory; 078 079 public WebServiceTemplateBuilder(WebServiceTemplateCustomizer... customizers) { 080 this.detectHttpMessageSender = true; 081 this.interceptors = null; 082 this.internalCustomizers = null; 083 this.customizers = Collections 084 .unmodifiableSet(new LinkedHashSet<>(Arrays.asList(customizers))); 085 this.messageSenders = new WebServiceMessageSenders(); 086 this.marshaller = null; 087 this.unmarshaller = null; 088 this.destinationProvider = null; 089 this.transformerFactoryClass = null; 090 this.messageFactory = null; 091 } 092 093 private WebServiceTemplateBuilder(boolean detectHttpMessageSender, 094 Set<ClientInterceptor> interceptors, 095 Set<WebServiceTemplateCustomizer> internalCustomizers, 096 Set<WebServiceTemplateCustomizer> customizers, 097 WebServiceMessageSenders messageSenders, Marshaller marshaller, 098 Unmarshaller unmarshaller, DestinationProvider destinationProvider, 099 Class<? extends TransformerFactory> transformerFactoryClass, 100 WebServiceMessageFactory messageFactory) { 101 this.detectHttpMessageSender = detectHttpMessageSender; 102 this.interceptors = interceptors; 103 this.internalCustomizers = internalCustomizers; 104 this.customizers = customizers; 105 this.messageSenders = messageSenders; 106 this.marshaller = marshaller; 107 this.unmarshaller = unmarshaller; 108 this.destinationProvider = destinationProvider; 109 this.transformerFactoryClass = transformerFactoryClass; 110 this.messageFactory = messageFactory; 111 } 112 113 /** 114 * Set if a suitable HTTP-based {@link WebServiceMessageSender} should be detected 115 * based on the classpath. Default is {@code true}. 116 * @param detectHttpMessageSender if a HTTP-based {@link WebServiceMessageSender} 117 * should be detected 118 * @return a new builder instance 119 * @see HttpWebServiceMessageSenderBuilder 120 */ 121 public WebServiceTemplateBuilder detectHttpMessageSender( 122 boolean detectHttpMessageSender) { 123 return new WebServiceTemplateBuilder(detectHttpMessageSender, this.interceptors, 124 this.internalCustomizers, this.customizers, this.messageSenders, 125 this.marshaller, this.unmarshaller, this.destinationProvider, 126 this.transformerFactoryClass, this.messageFactory); 127 } 128 129 /** 130 * Sets the {@link WebServiceMessageSender WebServiceMessageSenders} that should be 131 * used with the {@link WebServiceTemplate}. Setting this value will replace any 132 * previously defined message senders, including the HTTP-based message sender, if 133 * any. Consider using {@link #additionalMessageSenders(WebServiceMessageSender...)} 134 * to keep it with user-defined message senders. 135 * @param messageSenders the message senders to set 136 * @return a new builder instance. 137 * @see #additionalMessageSenders(WebServiceMessageSender...) 138 * @see #detectHttpMessageSender(boolean) 139 */ 140 public WebServiceTemplateBuilder messageSenders( 141 WebServiceMessageSender... messageSenders) { 142 Assert.notNull(messageSenders, "MessageSenders must not be null"); 143 return messageSenders(Arrays.asList(messageSenders)); 144 } 145 146 /** 147 * Sets the {@link WebServiceMessageSender WebServiceMessageSenders} that should be 148 * used with the {@link WebServiceTemplate}. Setting this value will replace any 149 * previously defined message senders, including the HTTP-based message sender, if 150 * any. Consider using {@link #additionalMessageSenders(Collection)} to keep it with 151 * user-defined message senders. 152 * @param messageSenders the message senders to set 153 * @return a new builder instance. 154 * @see #additionalMessageSenders(Collection) 155 * @see #detectHttpMessageSender(boolean) 156 */ 157 public WebServiceTemplateBuilder messageSenders( 158 Collection<? extends WebServiceMessageSender> messageSenders) { 159 Assert.notNull(messageSenders, "MessageSenders must not be null"); 160 return new WebServiceTemplateBuilder(this.detectHttpMessageSender, 161 this.interceptors, this.internalCustomizers, this.customizers, 162 this.messageSenders.set(messageSenders), this.marshaller, 163 this.unmarshaller, this.destinationProvider, this.transformerFactoryClass, 164 this.messageFactory); 165 } 166 167 /** 168 * Add additional {@link WebServiceMessageSender WebServiceMessageSenders} that should 169 * be used with the {@link WebServiceTemplate}. 170 * @param messageSenders the message senders to add 171 * @return a new builder instance. 172 * @see #messageSenders(WebServiceMessageSender...) 173 */ 174 public WebServiceTemplateBuilder additionalMessageSenders( 175 WebServiceMessageSender... messageSenders) { 176 Assert.notNull(messageSenders, "MessageSenders must not be null"); 177 return additionalMessageSenders(Arrays.asList(messageSenders)); 178 } 179 180 /** 181 * Add additional {@link WebServiceMessageSender WebServiceMessageSenders} that should 182 * be used with the {@link WebServiceTemplate}. 183 * @param messageSenders the message senders to add 184 * @return a new builder instance. 185 * @see #messageSenders(Collection) 186 */ 187 public WebServiceTemplateBuilder additionalMessageSenders( 188 Collection<? extends WebServiceMessageSender> messageSenders) { 189 Assert.notNull(messageSenders, "MessageSenders must not be null"); 190 return new WebServiceTemplateBuilder(this.detectHttpMessageSender, 191 this.interceptors, this.internalCustomizers, this.customizers, 192 this.messageSenders.add(messageSenders), this.marshaller, 193 this.unmarshaller, this.destinationProvider, this.transformerFactoryClass, 194 this.messageFactory); 195 } 196 197 /** 198 * Set the {@link ClientInterceptor ClientInterceptors} that should be used with the 199 * {@link WebServiceTemplate}. Setting this value will replace any previously defined 200 * interceptors. 201 * @param interceptors the interceptors to set 202 * @return a new builder instance 203 * @see #additionalInterceptors(ClientInterceptor...) 204 */ 205 public WebServiceTemplateBuilder interceptors(ClientInterceptor... interceptors) { 206 Assert.notNull(interceptors, "Interceptors must not be null"); 207 return interceptors(Arrays.asList(interceptors)); 208 } 209 210 /** 211 * Set the {@link ClientInterceptor ClientInterceptors} that should be used with the 212 * {@link WebServiceTemplate}. Setting this value will replace any previously defined 213 * interceptors. 214 * @param interceptors the interceptors to set 215 * @return a new builder instance 216 * @see #additionalInterceptors(Collection) 217 */ 218 public WebServiceTemplateBuilder interceptors( 219 Collection<? extends ClientInterceptor> interceptors) { 220 Assert.notNull(interceptors, "Interceptors must not be null"); 221 return new WebServiceTemplateBuilder(this.detectHttpMessageSender, 222 append(Collections.<ClientInterceptor>emptySet(), interceptors), 223 this.internalCustomizers, this.customizers, this.messageSenders, 224 this.marshaller, this.unmarshaller, this.destinationProvider, 225 this.transformerFactoryClass, this.messageFactory); 226 } 227 228 /** 229 * Add additional {@link ClientInterceptor ClientInterceptors} that should be used 230 * with the {@link WebServiceTemplate}. 231 * @param interceptors the interceptors to add 232 * @return a new builder instance 233 * @see #interceptors(ClientInterceptor...) 234 */ 235 public WebServiceTemplateBuilder additionalInterceptors( 236 ClientInterceptor... interceptors) { 237 Assert.notNull(interceptors, "Interceptors must not be null"); 238 return additionalInterceptors(Arrays.asList(interceptors)); 239 } 240 241 /** 242 * Add additional {@link ClientInterceptor ClientInterceptors} that should be used 243 * with the {@link WebServiceTemplate}. 244 * @param interceptors the interceptors to add 245 * @return a new builder instance 246 * @see #interceptors(Collection) 247 */ 248 public WebServiceTemplateBuilder additionalInterceptors( 249 Collection<? extends ClientInterceptor> interceptors) { 250 Assert.notNull(interceptors, "Interceptors must not be null"); 251 return new WebServiceTemplateBuilder(this.detectHttpMessageSender, 252 append(this.interceptors, interceptors), this.internalCustomizers, 253 this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, 254 this.destinationProvider, this.transformerFactoryClass, 255 this.messageFactory); 256 } 257 258 /** 259 * Set {@link WebServiceTemplateCustomizer WebServiceTemplateCustomizers} that should 260 * be applied to the {@link WebServiceTemplate}. Customizers are applied in the order 261 * that they were added after builder configuration has been applied. Setting this 262 * value will replace any previously configured customizers. 263 * @param customizers the customizers to set 264 * @return a new builder instance 265 * @see #additionalCustomizers(WebServiceTemplateCustomizer...) 266 */ 267 public WebServiceTemplateBuilder customizers( 268 WebServiceTemplateCustomizer... customizers) { 269 Assert.notNull(customizers, "Customizers must not be null"); 270 return customizers(Arrays.asList(customizers)); 271 } 272 273 /** 274 * Set {@link WebServiceTemplateCustomizer WebServiceTemplateCustomizers} that should 275 * be applied to the {@link WebServiceTemplate}. Customizers are applied in the order 276 * that they were added after builder configuration has been applied. Setting this 277 * value will replace any previously configured customizers. 278 * @param customizers the customizers to set 279 * @return a new builder instance 280 * @see #additionalCustomizers(Collection) 281 */ 282 public WebServiceTemplateBuilder customizers( 283 Collection<? extends WebServiceTemplateCustomizer> customizers) { 284 Assert.notNull(customizers, "Customizers must not be null"); 285 return new WebServiceTemplateBuilder(this.detectHttpMessageSender, 286 this.interceptors, this.internalCustomizers, 287 append(Collections.<WebServiceTemplateCustomizer>emptySet(), customizers), 288 this.messageSenders, this.marshaller, this.unmarshaller, 289 this.destinationProvider, this.transformerFactoryClass, 290 this.messageFactory); 291 } 292 293 /** 294 * Add additional {@link WebServiceTemplateCustomizer WebServiceTemplateCustomizers} 295 * that should be applied to the {@link WebServiceTemplate}. Customizers are applied 296 * in the order that they were added after builder configuration has been applied. 297 * @param customizers the customizers to add 298 * @return a new builder instance 299 * @see #customizers(WebServiceTemplateCustomizer...) 300 */ 301 public WebServiceTemplateBuilder additionalCustomizers( 302 WebServiceTemplateCustomizer... customizers) { 303 Assert.notNull(customizers, "Customizers must not be null"); 304 return additionalCustomizers(Arrays.asList(customizers)); 305 } 306 307 /** 308 * Add additional {@link WebServiceTemplateCustomizer WebServiceTemplateCustomizers} 309 * that should be applied to the {@link WebServiceTemplate}. Customizers are applied 310 * in the order that they were added after builder configuration has been applied. 311 * @param customizers the customizers to add 312 * @return a new builder instance 313 * @see #customizers(Collection) 314 */ 315 public WebServiceTemplateBuilder additionalCustomizers( 316 Collection<? extends WebServiceTemplateCustomizer> customizers) { 317 Assert.notNull(customizers, "Customizers must not be null"); 318 return new WebServiceTemplateBuilder(this.detectHttpMessageSender, 319 this.interceptors, this.internalCustomizers, 320 append(this.customizers, customizers), this.messageSenders, 321 this.marshaller, this.unmarshaller, this.destinationProvider, 322 this.transformerFactoryClass, this.messageFactory); 323 } 324 325 /** 326 * Indicates whether the connection should be checked for fault indicators 327 * ({@code true}), or whether we should rely on the message only ({@code false}). 328 * @param checkConnectionForFault whether to check for fault indicators 329 * @return a new builder instance. 330 * @see WebServiceTemplate#setCheckConnectionForFault(boolean) 331 */ 332 public WebServiceTemplateBuilder setCheckConnectionForFault( 333 boolean checkConnectionForFault) { 334 return new WebServiceTemplateBuilder(this.detectHttpMessageSender, 335 this.interceptors, 336 append(this.internalCustomizers, 337 new CheckConnectionFaultCustomizer(checkConnectionForFault)), 338 this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, 339 this.destinationProvider, this.transformerFactoryClass, 340 this.messageFactory); 341 } 342 343 /** 344 * Indicates whether the connection should be checked for error indicators 345 * ({@code true}), or whether these should be ignored ({@code false}). 346 * @param checkConnectionForError whether to check for error indicators 347 * @return a new builder instance. 348 * @see WebServiceTemplate#setCheckConnectionForError(boolean) 349 */ 350 public WebServiceTemplateBuilder setCheckConnectionForError( 351 boolean checkConnectionForError) { 352 return new WebServiceTemplateBuilder(this.detectHttpMessageSender, 353 this.interceptors, 354 append(this.internalCustomizers, 355 new CheckConnectionForErrorCustomizer(checkConnectionForError)), 356 this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, 357 this.destinationProvider, this.transformerFactoryClass, 358 this.messageFactory); 359 } 360 361 /** 362 * Sets the {@link WebServiceMessageFactory} to use for creating messages. 363 * @param messageFactory the message factory to use for creating messages 364 * @return a new builder instance. 365 * @see WebServiceTemplate#setMessageFactory(WebServiceMessageFactory) 366 **/ 367 public WebServiceTemplateBuilder setWebServiceMessageFactory( 368 WebServiceMessageFactory messageFactory) { 369 Assert.notNull(messageFactory, "MessageFactory must not be null"); 370 return new WebServiceTemplateBuilder(this.detectHttpMessageSender, 371 this.interceptors, this.internalCustomizers, this.customizers, 372 this.messageSenders, this.marshaller, this.unmarshaller, 373 this.destinationProvider, this.transformerFactoryClass, messageFactory); 374 } 375 376 /** 377 * Set the {@link Unmarshaller} to use to deserialize messages. 378 * @param unmarshaller the message unmarshaller 379 * @return a new builder instance. 380 * @see WebServiceTemplate#setUnmarshaller(Unmarshaller) 381 **/ 382 public WebServiceTemplateBuilder setUnmarshaller(Unmarshaller unmarshaller) { 383 return new WebServiceTemplateBuilder(this.detectHttpMessageSender, 384 this.interceptors, this.internalCustomizers, this.customizers, 385 this.messageSenders, this.marshaller, unmarshaller, 386 this.destinationProvider, this.transformerFactoryClass, 387 this.messageFactory); 388 } 389 390 /** 391 * Set the {@link Marshaller} to use to serialize messages. 392 * @param marshaller the message marshaller 393 * @return a new builder instance. 394 * @see WebServiceTemplate#setMarshaller(Marshaller) 395 **/ 396 public WebServiceTemplateBuilder setMarshaller(Marshaller marshaller) { 397 return new WebServiceTemplateBuilder(this.detectHttpMessageSender, 398 this.interceptors, this.internalCustomizers, this.customizers, 399 this.messageSenders, marshaller, this.unmarshaller, 400 this.destinationProvider, this.transformerFactoryClass, 401 this.messageFactory); 402 } 403 404 /** 405 * Set the {@link FaultMessageResolver} to use. 406 * @param faultMessageResolver the fault message resolver to use 407 * @return a new builder instance. 408 * @see WebServiceTemplate#setFaultMessageResolver(FaultMessageResolver) 409 */ 410 public WebServiceTemplateBuilder setFaultMessageResolver( 411 FaultMessageResolver faultMessageResolver) { 412 return new WebServiceTemplateBuilder(this.detectHttpMessageSender, 413 this.interceptors, 414 append(this.internalCustomizers, 415 new FaultMessageResolverCustomizer(faultMessageResolver)), 416 this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, 417 this.destinationProvider, this.transformerFactoryClass, 418 this.messageFactory); 419 } 420 421 /** 422 * Set the {@link TransformerFactory} implementation to use. 423 * @param transformerFactoryClass the transformer factory implementation to use 424 * @return a new builder instance. 425 * @see WebServiceTemplate#setTransformerFactoryClass(Class) 426 */ 427 public WebServiceTemplateBuilder setTransformerFactoryClass( 428 Class<? extends TransformerFactory> transformerFactoryClass) { 429 return new WebServiceTemplateBuilder(this.detectHttpMessageSender, 430 this.interceptors, this.internalCustomizers, this.customizers, 431 this.messageSenders, this.marshaller, this.unmarshaller, 432 this.destinationProvider, transformerFactoryClass, this.messageFactory); 433 } 434 435 /** 436 * Set the default URI to be used on operations that do not have a URI parameter. 437 * Typically, either this property is set, or 438 * {@link #setDestinationProvider(DestinationProvider)}, but not both. 439 * @param defaultUri the destination provider URI to be used on operations that do not 440 * have a URI parameter. 441 * @return a new builder instance. 442 * @see #setDestinationProvider(DestinationProvider) 443 */ 444 public WebServiceTemplateBuilder setDefaultUri(String defaultUri) { 445 Assert.hasText(defaultUri, "DefaultUri must not be empty"); 446 return setDestinationProvider(() -> URI.create(defaultUri)); 447 } 448 449 /** 450 * Set the {@link DestinationProvider} to use. Typically, either this property is set, 451 * or {@link #setDefaultUri(String)}, but not both. 452 * @param destinationProvider the destination provider to be used on operations that 453 * do not have a URI parameter. 454 * @return a new builder instance. 455 * @see WebServiceTemplate#setDestinationProvider(DestinationProvider) 456 */ 457 public WebServiceTemplateBuilder setDestinationProvider( 458 DestinationProvider destinationProvider) { 459 Assert.notNull(destinationProvider, "DestinationProvider must not be null"); 460 return new WebServiceTemplateBuilder(this.detectHttpMessageSender, 461 this.interceptors, this.internalCustomizers, this.customizers, 462 this.messageSenders, this.marshaller, this.unmarshaller, 463 destinationProvider, this.transformerFactoryClass, this.messageFactory); 464 } 465 466 /** 467 * Build a new {@link WebServiceTemplate} instance and configure it using this 468 * builder. 469 * @return a configured {@link WebServiceTemplate} instance. 470 * @see #build(Class) 471 * @see #configure(WebServiceTemplate) 472 */ 473 public WebServiceTemplate build() { 474 return build(WebServiceTemplate.class); 475 } 476 477 /** 478 * Build a new {@link WebServiceTemplate} instance of the specified type and configure 479 * it using this builder. 480 * @param <T> the type of web service template 481 * @param webServiceTemplateClass the template type to create 482 * @return a configured {@link WebServiceTemplate} instance. 483 * @see WebServiceTemplateBuilder#build() 484 * @see #configure(WebServiceTemplate) 485 */ 486 public <T extends WebServiceTemplate> T build(Class<T> webServiceTemplateClass) { 487 Assert.notNull(webServiceTemplateClass, 488 "WebServiceTemplateClass must not be null"); 489 return configure(BeanUtils.instantiateClass(webServiceTemplateClass)); 490 } 491 492 /** 493 * Configure the provided {@link WebServiceTemplate} instance using this builder. 494 * @param <T> the type of web service template 495 * @param webServiceTemplate the {@link WebServiceTemplate} to configure 496 * @return the web service template instance 497 * @see #build() 498 * @see #build(Class) 499 */ 500 public <T extends WebServiceTemplate> T configure(T webServiceTemplate) { 501 Assert.notNull(webServiceTemplate, "WebServiceTemplate must not be null"); 502 configureMessageSenders(webServiceTemplate); 503 PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); 504 applyCustomizers(webServiceTemplate, this.internalCustomizers); 505 map.from(this.marshaller).to(webServiceTemplate::setMarshaller); 506 map.from(this.unmarshaller).to(webServiceTemplate::setUnmarshaller); 507 map.from(this.destinationProvider).to(webServiceTemplate::setDestinationProvider); 508 map.from(this.transformerFactoryClass) 509 .to(webServiceTemplate::setTransformerFactoryClass); 510 map.from(this.messageFactory).to(webServiceTemplate::setMessageFactory); 511 if (!CollectionUtils.isEmpty(this.interceptors)) { 512 Set<ClientInterceptor> merged = new LinkedHashSet<>(this.interceptors); 513 if (webServiceTemplate.getInterceptors() != null) { 514 merged.addAll(Arrays.asList(webServiceTemplate.getInterceptors())); 515 } 516 webServiceTemplate.setInterceptors(merged.toArray(new ClientInterceptor[0])); 517 } 518 applyCustomizers(webServiceTemplate, this.customizers); 519 return webServiceTemplate; 520 } 521 522 private void applyCustomizers(WebServiceTemplate webServiceTemplate, 523 Set<WebServiceTemplateCustomizer> customizers) { 524 if (!CollectionUtils.isEmpty(customizers)) { 525 for (WebServiceTemplateCustomizer internalCustomizer : customizers) { 526 internalCustomizer.customize(webServiceTemplate); 527 } 528 } 529 } 530 531 private <T extends WebServiceTemplate> void configureMessageSenders( 532 T webServiceTemplate) { 533 if (this.messageSenders.isOnlyAdditional() && this.detectHttpMessageSender) { 534 Set<WebServiceMessageSender> merged = append( 535 this.messageSenders.getMessageSenders(), 536 new HttpWebServiceMessageSenderBuilder().build()); 537 webServiceTemplate 538 .setMessageSenders(merged.toArray(new WebServiceMessageSender[0])); 539 } 540 else if (!CollectionUtils.isEmpty(this.messageSenders.getMessageSenders())) { 541 webServiceTemplate.setMessageSenders(this.messageSenders.getMessageSenders() 542 .toArray(new WebServiceMessageSender[0])); 543 } 544 } 545 546 private <T> Set<T> append(Set<T> set, T addition) { 547 return append(set, Collections.singleton(addition)); 548 } 549 550 private static <T> Set<T> append(Set<T> set, Collection<? extends T> additions) { 551 Set<T> result = new LinkedHashSet<>((set != null) ? set : Collections.emptySet()); 552 result.addAll((additions != null) ? additions : Collections.emptyList()); 553 return Collections.unmodifiableSet(result); 554 } 555 556 /** 557 * Collect user-defined {@link WebServiceMessageSender} and whether only additional 558 * message senders were added or not. 559 */ 560 private static class WebServiceMessageSenders { 561 562 private final boolean onlyAdditional; 563 564 private Set<WebServiceMessageSender> messageSenders; 565 566 WebServiceMessageSenders() { 567 this(true, Collections.emptySet()); 568 } 569 570 private WebServiceMessageSenders(boolean onlyAdditional, 571 Set<WebServiceMessageSender> messageSenders) { 572 this.onlyAdditional = onlyAdditional; 573 this.messageSenders = messageSenders; 574 } 575 576 public boolean isOnlyAdditional() { 577 return this.onlyAdditional; 578 } 579 580 public Set<WebServiceMessageSender> getMessageSenders() { 581 return this.messageSenders; 582 } 583 584 public WebServiceMessageSenders set( 585 Collection<? extends WebServiceMessageSender> messageSenders) { 586 return new WebServiceMessageSenders(false, 587 new LinkedHashSet<>(messageSenders)); 588 } 589 590 public WebServiceMessageSenders add( 591 Collection<? extends WebServiceMessageSender> messageSenders) { 592 return new WebServiceMessageSenders(this.onlyAdditional, 593 append(this.messageSenders, messageSenders)); 594 } 595 596 } 597 598 /** 599 * {@link WebServiceTemplateCustomizer} to set 600 * {@link WebServiceTemplate#checkConnectionForFault checkConnectionForFault }. 601 */ 602 private static final class CheckConnectionFaultCustomizer 603 implements WebServiceTemplateCustomizer { 604 605 private final boolean checkConnectionFault; 606 607 private CheckConnectionFaultCustomizer(boolean checkConnectionFault) { 608 this.checkConnectionFault = checkConnectionFault; 609 } 610 611 @Override 612 public void customize(WebServiceTemplate webServiceTemplate) { 613 webServiceTemplate.setCheckConnectionForFault(this.checkConnectionFault); 614 } 615 616 } 617 618 /** 619 * {@link WebServiceTemplateCustomizer} to set 620 * {@link WebServiceTemplate#checkConnectionForError checkConnectionForError }. 621 */ 622 private static final class CheckConnectionForErrorCustomizer 623 implements WebServiceTemplateCustomizer { 624 625 private final boolean checkConnectionForError; 626 627 private CheckConnectionForErrorCustomizer(boolean checkConnectionForError) { 628 this.checkConnectionForError = checkConnectionForError; 629 } 630 631 @Override 632 public void customize(WebServiceTemplate webServiceTemplate) { 633 webServiceTemplate.setCheckConnectionForError(this.checkConnectionForError); 634 } 635 636 } 637 638 /** 639 * {@link WebServiceTemplateCustomizer} to set 640 * {@link WebServiceTemplate#faultMessageResolver faultMessageResolver }. 641 */ 642 private static final class FaultMessageResolverCustomizer 643 implements WebServiceTemplateCustomizer { 644 645 private final FaultMessageResolver faultMessageResolver; 646 647 private FaultMessageResolverCustomizer( 648 FaultMessageResolver faultMessageResolver) { 649 this.faultMessageResolver = faultMessageResolver; 650 } 651 652 @Override 653 public void customize(WebServiceTemplate webServiceTemplate) { 654 webServiceTemplate.setFaultMessageResolver(this.faultMessageResolver); 655 } 656 657 } 658 659}