001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.model.cloud; 018 019import java.util.Optional; 020import java.util.function.Function; 021import java.util.function.Supplier; 022import javax.xml.bind.annotation.XmlAccessType; 023import javax.xml.bind.annotation.XmlAccessorType; 024import javax.xml.bind.annotation.XmlAttribute; 025import javax.xml.bind.annotation.XmlElement; 026import javax.xml.bind.annotation.XmlElements; 027import javax.xml.bind.annotation.XmlRootElement; 028import javax.xml.bind.annotation.XmlTransient; 029 030import org.apache.camel.CamelContext; 031import org.apache.camel.ExchangePattern; 032import org.apache.camel.Expression; 033import org.apache.camel.Processor; 034import org.apache.camel.builder.ExpressionClause; 035import org.apache.camel.cloud.ServiceChooser; 036import org.apache.camel.cloud.ServiceChooserAware; 037import org.apache.camel.cloud.ServiceDiscovery; 038import org.apache.camel.cloud.ServiceDiscoveryAware; 039import org.apache.camel.cloud.ServiceExpressionFactory; 040import org.apache.camel.cloud.ServiceFilter; 041import org.apache.camel.cloud.ServiceFilterAware; 042import org.apache.camel.cloud.ServiceLoadBalancer; 043import org.apache.camel.impl.cloud.DefaultServiceCallExpression; 044import org.apache.camel.impl.cloud.DefaultServiceCallProcessor; 045import org.apache.camel.impl.cloud.DefaultServiceLoadBalancer; 046import org.apache.camel.impl.cloud.HealthyServiceFilter; 047import org.apache.camel.impl.cloud.PassThroughServiceFilter; 048import org.apache.camel.impl.cloud.RandomServiceChooser; 049import org.apache.camel.impl.cloud.RoundRobinServiceChooser; 050import org.apache.camel.model.NoOutputDefinition; 051import org.apache.camel.spi.Metadata; 052import org.apache.camel.spi.RouteContext; 053import org.apache.camel.util.CamelContextHelper; 054import org.apache.camel.util.ObjectHelper; 055import org.apache.camel.util.function.Suppliers; 056 057import static org.apache.camel.util.CamelContextHelper.findByType; 058import static org.apache.camel.util.CamelContextHelper.lookup; 059 060/** 061 * To call remote services 062 */ 063@Metadata(label = "eip,routing") 064@XmlRootElement(name = "serviceCall") 065@XmlAccessorType(XmlAccessType.FIELD) 066public class ServiceCallDefinition extends NoOutputDefinition<ServiceCallDefinition> { 067 @XmlAttribute @Metadata(required = "true") 068 private String name; 069 @XmlAttribute 070 private String uri; 071 @XmlAttribute @Metadata(defaultValue = ServiceCallDefinitionConstants.DEFAULT_COMPONENT) 072 private String component; 073 @XmlAttribute 074 private ExchangePattern pattern; 075 @XmlAttribute 076 private String configurationRef; 077 @XmlAttribute 078 private String serviceDiscoveryRef; 079 @XmlTransient 080 private ServiceDiscovery serviceDiscovery; 081 @XmlAttribute 082 private String serviceFilterRef; 083 @XmlTransient 084 private ServiceFilter serviceFilter; 085 @XmlAttribute 086 private String serviceChooserRef; 087 @XmlTransient 088 private ServiceChooser serviceChooser; 089 @XmlAttribute 090 private String loadBalancerRef; 091 @XmlTransient 092 private ServiceLoadBalancer loadBalancer; 093 @XmlAttribute 094 private String expressionRef; 095 @XmlTransient 096 private Expression expression; 097 098 @XmlElements({ 099 @XmlElement(name = "cachingServiceDiscovery", type = CachingServiceCallServiceDiscoveryConfiguration.class), 100 @XmlElement(name = "aggregatingServiceDiscovery", type = AggregatingServiceCallServiceDiscoveryConfiguration.class), 101 @XmlElement(name = "combinedServiceDiscovery", type = CombinedServiceCallServiceDiscoveryConfiguration.class), 102 @XmlElement(name = "consulServiceDiscovery", type = ConsulServiceCallServiceDiscoveryConfiguration.class), 103 @XmlElement(name = "dnsServiceDiscovery", type = DnsServiceCallServiceDiscoveryConfiguration.class), 104 @XmlElement(name = "etcdServiceDiscovery", type = EtcdServiceCallServiceDiscoveryConfiguration.class), 105 @XmlElement(name = "kubernetesServiceDiscovery", type = KubernetesServiceCallServiceDiscoveryConfiguration.class), 106 @XmlElement(name = "staticServiceDiscovery", type = StaticServiceCallServiceDiscoveryConfiguration.class), 107 @XmlElement(name = "zookeeperServiceDiscovery", type = ZooKeeperServiceCallServiceDiscoveryConfiguration.class)} 108 ) 109 private ServiceCallServiceDiscoveryConfiguration serviceDiscoveryConfiguration; 110 111 @XmlElements({ 112 @XmlElement(name = "blacklistServiceFilter", type = BlacklistServiceCallServiceFilterConfiguration.class), 113 @XmlElement(name = "chainedServiceFilter", type = ChainedServiceCallServiceFilterConfiguration.class), 114 @XmlElement(name = "combinedServiceFilter", type = CombinedServiceCallServiceFilterConfiguration.class), 115 @XmlElement(name = "customServiceFilter", type = CustomServiceCallServiceFilterConfiguration.class), 116 @XmlElement(name = "healthyServiceFilter", type = HealthyServiceCallServiceFilterConfiguration.class), 117 @XmlElement(name = "passThroughServiceFilter", type = PassThroughServiceCallServiceFilterConfiguration.class)} 118 ) 119 private ServiceCallServiceFilterConfiguration serviceFilterConfiguration; 120 121 @XmlElements({ 122 @XmlElement(name = "ribbonLoadBalancer", type = RibbonServiceCallServiceLoadBalancerConfiguration.class), 123 @XmlElement(name = "defaultLoadBalancer", type = DefaultServiceCallServiceLoadBalancerConfiguration.class) } 124 ) 125 private ServiceCallServiceLoadBalancerConfiguration loadBalancerConfiguration; 126 127 @XmlElements({ 128 @XmlElement(name = "expressionConfiguration", type = ServiceCallExpressionConfiguration.class)} 129 ) 130 private ServiceCallExpressionConfiguration expressionConfiguration; 131 132 public ServiceCallDefinition() { 133 } 134 135 @Override 136 public String toString() { 137 return "ServiceCall[" + name + "]"; 138 } 139 140 @Override 141 public String getLabel() { 142 return "serviceCall"; 143 } 144 145 // ***************************** 146 // Properties 147 // ***************************** 148 149 public String getName() { 150 return name; 151 } 152 153 /** 154 * Sets the name of the service to use 155 */ 156 public void setName(String name) { 157 this.name = name; 158 } 159 160 public ExchangePattern getPattern() { 161 return pattern; 162 } 163 164 /** 165 * Sets the optional {@link ExchangePattern} used to invoke this endpoint 166 */ 167 public void setPattern(ExchangePattern pattern) { 168 this.pattern = pattern; 169 } 170 171 public String getConfigurationRef() { 172 return configurationRef; 173 } 174 175 /** 176 * Refers to a ServiceCall configuration to use 177 */ 178 public void setConfigurationRef(String configurationRef) { 179 this.configurationRef = configurationRef; 180 } 181 182 public String getUri() { 183 return uri; 184 } 185 186 /** 187 * The uri of the endpoint to send to. 188 * The uri can be dynamic computed using the {@link org.apache.camel.language.simple.SimpleLanguage} expression. 189 */ 190 public void setUri(String uri) { 191 this.uri = uri; 192 } 193 194 public String getComponent() { 195 return component; 196 } 197 198 /** 199 * The component to use. 200 */ 201 public void setComponent(String component) { 202 this.component = component; 203 } 204 205 public String getServiceDiscoveryRef() { 206 return serviceDiscoveryRef; 207 } 208 209 /** 210 * Sets a reference to a custom {@link ServiceDiscovery} to use. 211 */ 212 public void setServiceDiscoveryRef(String serviceDiscoveryRef) { 213 this.serviceDiscoveryRef = serviceDiscoveryRef; 214 } 215 216 public ServiceDiscovery getServiceDiscovery() { 217 return serviceDiscovery; 218 } 219 220 /** 221 * Sets a custom {@link ServiceDiscovery} to use. 222 */ 223 public void setServiceDiscovery(ServiceDiscovery serviceDiscovery) { 224 this.serviceDiscovery = serviceDiscovery; 225 } 226 227 public String getServiceFilterRef() { 228 return serviceFilterRef; 229 } 230 231 /** 232 * Sets a reference to a custom {@link ServiceFilter} to use. 233 */ 234 public void setServiceFilterRef(String serviceFilterRef) { 235 this.serviceFilterRef = serviceFilterRef; 236 } 237 238 public ServiceFilter getServiceFilter() { 239 return serviceFilter; 240 } 241 242 /** 243 * Sets a custom {@link ServiceFilter} to use. 244 */ 245 public void setServiceFilter(ServiceFilter serviceFilter) { 246 this.serviceFilter = serviceFilter; 247 } 248 249 public String getServiceChooserRef() { 250 return serviceChooserRef; 251 } 252 253 /** 254 * Sets a reference to a custom {@link ServiceChooser} to use. 255 */ 256 public void setServiceChooserRef(String serviceChooserRef) { 257 this.serviceChooserRef = serviceChooserRef; 258 } 259 260 public ServiceChooser getServiceChooser() { 261 return serviceChooser; 262 } 263 264 /** 265 * Sets a custom {@link ServiceChooser} to use. 266 */ 267 public void setServiceChooser(ServiceChooser serviceChooser) { 268 this.serviceChooser = serviceChooser; 269 } 270 271 public String getLoadBalancerRef() { 272 return loadBalancerRef; 273 } 274 275 /** 276 * Sets a reference to a custom {@link ServiceLoadBalancer} to use. 277 */ 278 public void setLoadBalancerRef(String loadBalancerRef) { 279 this.loadBalancerRef = loadBalancerRef; 280 } 281 282 public ServiceLoadBalancer getLoadBalancer() { 283 return loadBalancer; 284 } 285 286 /** 287 * Sets a custom {@link ServiceLoadBalancer} to use. 288 */ 289 public void setLoadBalancer(ServiceLoadBalancer loadBalancer) { 290 this.loadBalancer = loadBalancer; 291 } 292 293 public String getExpressionRef() { 294 return expressionRef; 295 } 296 297 /** 298 * Set a reference to a custom {@link Expression} to use. 299 */ 300 public void setExpressionRef(String expressionRef) { 301 this.expressionRef = expressionRef; 302 } 303 304 public Expression getExpression() { 305 return expression; 306 } 307 308 /** 309 * Set a custom {@link Expression} to use. 310 */ 311 public void setExpression(Expression expression) { 312 this.expression = expression; 313 } 314 315 public ServiceCallServiceDiscoveryConfiguration getServiceDiscoveryConfiguration() { 316 return serviceDiscoveryConfiguration; 317 } 318 319 /** 320 * Configures the ServiceDiscovery using the given configuration. 321 */ 322 public void setServiceDiscoveryConfiguration(ServiceCallServiceDiscoveryConfiguration serviceDiscoveryConfiguration) { 323 this.serviceDiscoveryConfiguration = serviceDiscoveryConfiguration; 324 } 325 326 public ServiceCallServiceFilterConfiguration getServiceFilterConfiguration() { 327 return serviceFilterConfiguration; 328 } 329 330 /** 331 * Configures the ServiceFilter using the given configuration. 332 */ 333 public void setServiceFilterConfiguration(ServiceCallServiceFilterConfiguration serviceFilterConfiguration) { 334 this.serviceFilterConfiguration = serviceFilterConfiguration; 335 } 336 337 public ServiceCallServiceLoadBalancerConfiguration getLoadBalancerConfiguration() { 338 return loadBalancerConfiguration; 339 } 340 341 /** 342 * Configures the LoadBalancer using the given configuration. 343 */ 344 public void setLoadBalancerConfiguration(ServiceCallServiceLoadBalancerConfiguration loadBalancerConfiguration) { 345 this.loadBalancerConfiguration = loadBalancerConfiguration; 346 } 347 348 public ServiceCallExpressionConfiguration getExpressionConfiguration() { 349 return expressionConfiguration; 350 } 351 352 /** 353 * Configures the Expression using the given configuration. 354 */ 355 public void setExpressionConfiguration(ServiceCallExpressionConfiguration expressionConfiguration) { 356 this.expressionConfiguration = expressionConfiguration; 357 } 358 359 // ***************************** 360 // Fluent API 361 // ***************************** 362 363 /** 364 * Sets the optional {@link ExchangePattern} used to invoke this endpoint 365 */ 366 public ServiceCallDefinition pattern(ExchangePattern pattern) { 367 setPattern(pattern); 368 return this; 369 } 370 371 /** 372 * Sets the name of the service to use 373 */ 374 public ServiceCallDefinition name(String name) { 375 setName(name); 376 return this; 377 } 378 379 /** 380 * Sets the uri of the service to use 381 */ 382 public ServiceCallDefinition uri(String uri) { 383 setUri(uri); 384 return this; 385 } 386 387 /** 388 * Sets the component to use 389 */ 390 public ServiceCallDefinition component(String component) { 391 setComponent(component); 392 return this; 393 } 394 395 /** 396 * Refers to a ServiceCall configuration to use 397 */ 398 public ServiceCallDefinition serviceCallConfiguration(String ref) { 399 configurationRef = ref; 400 return this; 401 } 402 403 /** 404 * Sets a reference to a custom {@link ServiceDiscovery} to use. 405 */ 406 public ServiceCallDefinition serviceDiscovery(String serviceDiscoveryRef) { 407 setServiceDiscoveryRef(serviceDiscoveryRef); 408 return this; 409 } 410 411 /** 412 * Sets a custom {@link ServiceDiscovery} to use. 413 */ 414 public ServiceCallDefinition serviceDiscovery(ServiceDiscovery serviceDiscovery) { 415 setServiceDiscovery(serviceDiscovery); 416 return this; 417 } 418 419 /** 420 * Sets a reference to a custom {@link ServiceFilter} to use. 421 */ 422 public ServiceCallDefinition serviceFilter(String serviceFilterRef) { 423 setServiceDiscoveryRef(serviceDiscoveryRef); 424 return this; 425 } 426 427 /** 428 * Sets a custom {@link ServiceFilter} to use. 429 */ 430 public ServiceCallDefinition serviceFilter(ServiceFilter serviceFilter) { 431 setServiceFilter(serviceFilter); 432 return this; 433 } 434 435 /** 436 * Sets a reference to a custom {@link ServiceChooser} to use. 437 */ 438 public ServiceCallDefinition serviceChooser(String serviceChooserRef) { 439 setServiceChooserRef(serviceChooserRef); 440 return this; 441 } 442 443 /** 444 * Sets a custom {@link ServiceChooser} to use. 445 */ 446 public ServiceCallDefinition serviceChooser(ServiceChooser serviceChooser) { 447 setServiceChooser(serviceChooser); 448 return this; 449 } 450 451 /** 452 * Sets a reference to a custom {@link ServiceLoadBalancer} to use. 453 */ 454 public ServiceCallDefinition loadBalancer(String loadBalancerRef) { 455 setLoadBalancerRef(loadBalancerRef); 456 return this; 457 } 458 459 /** 460 * Sets a custom {@link ServiceLoadBalancer} to use. 461 */ 462 public ServiceCallDefinition loadBalancer(ServiceLoadBalancer loadBalancer) { 463 setLoadBalancer(loadBalancer); 464 return this; 465 } 466 467 /** 468 * Sets a reference to a custom {@link Expression} to use. 469 */ 470 public ServiceCallDefinition expression(String expressionRef) { 471 setExpressionRef(loadBalancerRef); 472 return this; 473 } 474 475 /** 476 * Sets a custom {@link Expression} to use. 477 */ 478 public ServiceCallDefinition expression(Expression expression) { 479 setExpression(expression); 480 return this; 481 } 482 483 /** 484 * Sets a custom {@link Expression} to use through an expression builder clause. 485 * 486 * @return a expression builder clause to set the body 487 */ 488 public ExpressionClause<ServiceCallDefinition> expression() { 489 ExpressionClause<ServiceCallDefinition> clause = new ExpressionClause<>(this); 490 setExpression(clause); 491 492 return clause; 493 } 494 495 /** 496 * Configures the ServiceDiscovery using the given configuration. 497 */ 498 public ServiceCallDefinition serviceDiscoveryConfiguration(ServiceCallServiceDiscoveryConfiguration serviceDiscoveryConfiguration) { 499 setServiceDiscoveryConfiguration(serviceDiscoveryConfiguration); 500 return this; 501 } 502 503 /** 504 * Configures the ServiceFilter using the given configuration. 505 */ 506 public ServiceCallDefinition serviceFilterConfiguration(ServiceCallServiceFilterConfiguration serviceFilterConfiguration) { 507 setServiceFilterConfiguration(serviceFilterConfiguration); 508 return this; 509 } 510 511 /** 512 * Configures the LoadBalancer using the given configuration. 513 */ 514 public ServiceCallDefinition loadBalancerConfiguration(ServiceCallServiceLoadBalancerConfiguration loadBalancerConfiguration) { 515 setLoadBalancerConfiguration(loadBalancerConfiguration); 516 return this; 517 } 518 519 /** 520 * Configures the Expression using the given configuration. 521 */ 522 public ServiceCallDefinition expressionConfiguration(ServiceCallExpressionConfiguration expressionConfiguration) { 523 setExpressionConfiguration(expressionConfiguration); 524 return this; 525 } 526 527 // ***************************** 528 // Shortcuts - ServiceDiscovery 529 // ***************************** 530 531 public CachingServiceCallServiceDiscoveryConfiguration cachingServiceDiscovery() { 532 CachingServiceCallServiceDiscoveryConfiguration conf = new CachingServiceCallServiceDiscoveryConfiguration(this); 533 setServiceDiscoveryConfiguration(conf); 534 535 return conf; 536 } 537 538 public ConsulServiceCallServiceDiscoveryConfiguration consulServiceDiscovery() { 539 ConsulServiceCallServiceDiscoveryConfiguration conf = new ConsulServiceCallServiceDiscoveryConfiguration(this); 540 setServiceDiscoveryConfiguration(conf); 541 542 return conf; 543 } 544 545 public ServiceCallDefinition consulServiceDiscovery(String url) { 546 ConsulServiceCallServiceDiscoveryConfiguration conf = new ConsulServiceCallServiceDiscoveryConfiguration(this); 547 conf.setUrl(url); 548 549 setServiceDiscoveryConfiguration(conf); 550 551 return this; 552 } 553 554 public DnsServiceCallServiceDiscoveryConfiguration dnsServiceDiscovery() { 555 DnsServiceCallServiceDiscoveryConfiguration conf = new DnsServiceCallServiceDiscoveryConfiguration(this); 556 setServiceDiscoveryConfiguration(conf); 557 558 return conf; 559 } 560 561 public ServiceCallDefinition dnsServiceDiscovery(String domain) { 562 DnsServiceCallServiceDiscoveryConfiguration conf = new DnsServiceCallServiceDiscoveryConfiguration(this); 563 conf.setDomain(domain); 564 565 setServiceDiscoveryConfiguration(conf); 566 567 return this; 568 } 569 570 public ServiceCallDefinition dnsServiceDiscovery(String domain, String protocol) { 571 DnsServiceCallServiceDiscoveryConfiguration conf = new DnsServiceCallServiceDiscoveryConfiguration(this); 572 conf.setDomain(domain); 573 conf.setProto(protocol); 574 575 setServiceDiscoveryConfiguration(conf); 576 577 return this; 578 } 579 580 public EtcdServiceCallServiceDiscoveryConfiguration etcdServiceDiscovery() { 581 EtcdServiceCallServiceDiscoveryConfiguration conf = new EtcdServiceCallServiceDiscoveryConfiguration(this); 582 setServiceDiscoveryConfiguration(conf); 583 584 return conf; 585 } 586 587 public ServiceCallDefinition etcdServiceDiscovery(String uris) { 588 EtcdServiceCallServiceDiscoveryConfiguration conf = new EtcdServiceCallServiceDiscoveryConfiguration(this); 589 conf.setUris(uris); 590 591 setServiceDiscoveryConfiguration(conf); 592 593 return this; 594 } 595 596 public ServiceCallDefinition etcdServiceDiscovery(String uris, String servicePath) { 597 EtcdServiceCallServiceDiscoveryConfiguration conf = new EtcdServiceCallServiceDiscoveryConfiguration(this); 598 conf.setUris(uris); 599 conf.setServicePath(servicePath); 600 601 setServiceDiscoveryConfiguration(conf); 602 603 return this; 604 } 605 606 public KubernetesServiceCallServiceDiscoveryConfiguration kubernetesServiceDiscovery() { 607 KubernetesServiceCallServiceDiscoveryConfiguration conf = new KubernetesServiceCallServiceDiscoveryConfiguration(this); 608 setServiceDiscoveryConfiguration(conf); 609 610 return conf; 611 } 612 613 public KubernetesServiceCallServiceDiscoveryConfiguration kubernetesClientServiceDiscovery() { 614 KubernetesServiceCallServiceDiscoveryConfiguration conf = new KubernetesServiceCallServiceDiscoveryConfiguration(this); 615 conf.setLookup("client"); 616 617 setServiceDiscoveryConfiguration(conf); 618 619 return conf; 620 } 621 622 public ServiceCallDefinition kubernetesEnvServiceDiscovery() { 623 KubernetesServiceCallServiceDiscoveryConfiguration conf = new KubernetesServiceCallServiceDiscoveryConfiguration(this); 624 conf.setLookup("environment"); 625 626 setServiceDiscoveryConfiguration(conf); 627 628 return this; 629 } 630 631 public ServiceCallDefinition kubernetesDnsServiceDiscovery(String namespace, String domain) { 632 KubernetesServiceCallServiceDiscoveryConfiguration conf = new KubernetesServiceCallServiceDiscoveryConfiguration(this); 633 conf.setLookup("dns"); 634 conf.setNamespace(namespace); 635 conf.setDnsDomain(domain); 636 637 setServiceDiscoveryConfiguration(conf); 638 639 return this; 640 } 641 642 /** 643 * @deprecated As of version 2.22.0, replaced by {@link #combinedServiceDiscovery()} 644 */ 645 @Deprecated 646 public AggregatingServiceCallServiceDiscoveryConfiguration multiServiceDiscovery() { 647 AggregatingServiceCallServiceDiscoveryConfiguration conf = new AggregatingServiceCallServiceDiscoveryConfiguration(this); 648 setServiceDiscoveryConfiguration(conf); 649 650 return conf; 651 } 652 653 public CombinedServiceCallServiceDiscoveryConfiguration combinedServiceDiscovery() { 654 CombinedServiceCallServiceDiscoveryConfiguration conf = new CombinedServiceCallServiceDiscoveryConfiguration(this); 655 setServiceDiscoveryConfiguration(conf); 656 657 return conf; 658 } 659 660 public StaticServiceCallServiceDiscoveryConfiguration staticServiceDiscovery() { 661 StaticServiceCallServiceDiscoveryConfiguration conf = new StaticServiceCallServiceDiscoveryConfiguration(this); 662 setServiceDiscoveryConfiguration(conf); 663 664 return conf; 665 } 666 667 public ZooKeeperServiceCallServiceDiscoveryConfiguration zookeeperServiceDiscovery() { 668 ZooKeeperServiceCallServiceDiscoveryConfiguration conf = new ZooKeeperServiceCallServiceDiscoveryConfiguration(this); 669 setServiceDiscoveryConfiguration(conf); 670 671 return conf; 672 } 673 674 public ServiceCallDefinition zookeeperServiceDiscovery(String nodes, String basePath) { 675 ZooKeeperServiceCallServiceDiscoveryConfiguration conf = new ZooKeeperServiceCallServiceDiscoveryConfiguration(this); 676 conf.setNodes(nodes); 677 conf.setBasePath(basePath); 678 679 setServiceDiscoveryConfiguration(conf); 680 681 return this; 682 } 683 684 // ***************************** 685 // Shortcuts - ServiceFilter 686 // ***************************** 687 688 public ServiceCallDefinition healthyFilter() { 689 HealthyServiceCallServiceFilterConfiguration conf = new HealthyServiceCallServiceFilterConfiguration(this); 690 setServiceFilterConfiguration(conf); 691 692 return this; 693 } 694 695 public ServiceCallDefinition passThroughFilter() { 696 PassThroughServiceCallServiceFilterConfiguration conf = new PassThroughServiceCallServiceFilterConfiguration(this); 697 setServiceFilterConfiguration(conf); 698 699 return this; 700 } 701 702 /** 703 * @deprecated As of version 2.22.0, replaced by {@link #combinedFilter()} 704 */ 705 @Deprecated 706 public ChainedServiceCallServiceFilterConfiguration multiFilter() { 707 ChainedServiceCallServiceFilterConfiguration conf = new ChainedServiceCallServiceFilterConfiguration(this); 708 setServiceFilterConfiguration(conf); 709 710 return conf; 711 } 712 713 public CombinedServiceCallServiceFilterConfiguration combinedFilter() { 714 CombinedServiceCallServiceFilterConfiguration conf = new CombinedServiceCallServiceFilterConfiguration(this); 715 setServiceFilterConfiguration(conf); 716 717 return conf; 718 } 719 720 public BlacklistServiceCallServiceFilterConfiguration blacklistFilter() { 721 BlacklistServiceCallServiceFilterConfiguration conf = new BlacklistServiceCallServiceFilterConfiguration(); 722 setServiceFilterConfiguration(conf); 723 724 return conf; 725 } 726 727 public ServiceCallDefinition customFilter(String serviceFilter) { 728 CustomServiceCallServiceFilterConfiguration conf = new CustomServiceCallServiceFilterConfiguration(); 729 conf.setServiceFilterRef(serviceFilter); 730 731 setServiceFilterConfiguration(conf); 732 733 return this; 734 } 735 736 public ServiceCallDefinition customFilter(ServiceFilter serviceFilter) { 737 CustomServiceCallServiceFilterConfiguration conf = new CustomServiceCallServiceFilterConfiguration(); 738 conf.setServiceFilter(serviceFilter); 739 740 setServiceFilterConfiguration(conf); 741 742 return this; 743 } 744 745 // ***************************** 746 // Shortcuts - LoadBalancer 747 // ***************************** 748 749 public ServiceCallDefinition defaultLoadBalancer() { 750 DefaultServiceCallServiceLoadBalancerConfiguration conf = new DefaultServiceCallServiceLoadBalancerConfiguration(); 751 setLoadBalancerConfiguration(conf); 752 753 return this; 754 } 755 756 public ServiceCallDefinition ribbonLoadBalancer() { 757 RibbonServiceCallServiceLoadBalancerConfiguration conf = new RibbonServiceCallServiceLoadBalancerConfiguration(this); 758 setLoadBalancerConfiguration(conf); 759 760 return this; 761 } 762 763 public ServiceCallDefinition ribbonLoadBalancer(String clientName) { 764 RibbonServiceCallServiceLoadBalancerConfiguration conf = new RibbonServiceCallServiceLoadBalancerConfiguration(this); 765 conf.setClientName(clientName); 766 767 setLoadBalancerConfiguration(conf); 768 769 return this; 770 } 771 772 // ***************************** 773 // Processor Factory 774 // ***************************** 775 776 @Override 777 public Processor createProcessor(RouteContext routeContext) throws Exception { 778 final CamelContext camelContext = routeContext.getCamelContext(); 779 final ServiceDiscovery serviceDiscovery = retrieveServiceDiscovery(camelContext); 780 final ServiceFilter serviceFilter = retrieveServiceFilter(camelContext); 781 final ServiceChooser serviceChooser = retrieveServiceChooser(camelContext); 782 final ServiceLoadBalancer loadBalancer = retrieveLoadBalancer(camelContext); 783 784 ObjectHelper.trySetCamelContext(serviceDiscovery, camelContext); 785 ObjectHelper.trySetCamelContext(serviceFilter, camelContext); 786 ObjectHelper.trySetCamelContext(serviceChooser, camelContext); 787 ObjectHelper.trySetCamelContext(loadBalancer, camelContext); 788 789 if (loadBalancer instanceof ServiceDiscoveryAware) { 790 ((ServiceDiscoveryAware) loadBalancer).setServiceDiscovery(serviceDiscovery); 791 } 792 if (loadBalancer instanceof ServiceFilterAware) { 793 ((ServiceFilterAware) loadBalancer).setServiceFilter(serviceFilter); 794 } 795 if (loadBalancer instanceof ServiceChooserAware) { 796 ((ServiceChooserAware) loadBalancer).setServiceChooser(serviceChooser); 797 } 798 799 // The component is used to configure the default scheme to use (eg camel component name). 800 // The component configured on EIP takes precedence vs configured on configuration. 801 String endpointScheme = this.component; 802 if (endpointScheme == null) { 803 ServiceCallConfigurationDefinition conf = retrieveConfig(camelContext); 804 if (conf != null) { 805 endpointScheme = conf.getComponent(); 806 } 807 } 808 if (endpointScheme == null) { 809 ServiceCallConfigurationDefinition conf = retrieveDefaultConfig(camelContext); 810 if (conf != null) { 811 endpointScheme = conf.getComponent(); 812 } 813 } 814 815 // The uri is used to tweak the uri. 816 // The uri configured on EIP takes precedence vs configured on configuration. 817 String endpointUri = this.uri; 818 if (endpointUri == null) { 819 ServiceCallConfigurationDefinition conf = retrieveConfig(camelContext); 820 if (conf != null) { 821 endpointUri = conf.getUri(); 822 } 823 } 824 if (endpointUri == null) { 825 ServiceCallConfigurationDefinition conf = retrieveDefaultConfig(camelContext); 826 if (conf != null) { 827 endpointUri = conf.getUri(); 828 } 829 } 830 831 // Service name is mandatory 832 ObjectHelper.notNull(name, "Service name"); 833 834 endpointScheme = ObjectHelper.applyIfNotEmpty(endpointScheme, camelContext::resolvePropertyPlaceholders, () -> ServiceCallDefinitionConstants.DEFAULT_COMPONENT); 835 endpointUri = ObjectHelper.applyIfNotEmpty(endpointUri, camelContext::resolvePropertyPlaceholders, () -> null); 836 837 return new DefaultServiceCallProcessor( 838 camelContext, 839 camelContext.resolvePropertyPlaceholders(name), 840 endpointScheme, 841 endpointUri, 842 pattern, 843 loadBalancer, 844 retrieveExpression(camelContext, endpointScheme)); 845 } 846 847 // ***************************** 848 // Helpers 849 // ***************************** 850 851 private ServiceCallConfigurationDefinition retrieveDefaultConfig(CamelContext camelContext) { 852 // check if a default configuration is bound to the registry 853 ServiceCallConfigurationDefinition config = camelContext.getServiceCallConfiguration(null); 854 855 if (config == null) { 856 // Or if it is in the registry 857 config = lookup( 858 camelContext, 859 ServiceCallDefinitionConstants.DEFAULT_SERVICE_CALL_CONFIG_ID, 860 ServiceCallConfigurationDefinition.class); 861 } 862 863 if (config == null) { 864 // If no default is set either by searching by name or bound to the 865 // camel context, assume that if there is a single instance in the 866 // registry, that is the default one 867 config = findByType(camelContext, ServiceCallConfigurationDefinition.class); 868 } 869 870 return config; 871 } 872 873 private ServiceCallConfigurationDefinition retrieveConfig(CamelContext camelContext) { 874 ServiceCallConfigurationDefinition config = null; 875 if (configurationRef != null) { 876 // lookup in registry firstNotNull 877 config = lookup(camelContext, configurationRef, ServiceCallConfigurationDefinition.class); 878 if (config == null) { 879 // and fallback as service configuration 880 config = camelContext.getServiceCallConfiguration(configurationRef); 881 } 882 } 883 884 return config; 885 } 886 887 // ****************************************** 888 // ServiceDiscovery 889 // ****************************************** 890 891 private ServiceDiscovery retrieveServiceDiscovery(CamelContext camelContext, Function<CamelContext, ServiceCallConfigurationDefinition> function) throws Exception { 892 ServiceDiscovery answer = null; 893 894 ServiceCallConfigurationDefinition config = function.apply(camelContext); 895 if (config != null) { 896 if (config.getServiceDiscoveryConfiguration() != null) { 897 answer = config.getServiceDiscoveryConfiguration().newInstance(camelContext); 898 } else { 899 answer = retrieve( 900 ServiceDiscovery.class, 901 camelContext, 902 config::getServiceDiscovery, 903 config::getServiceDiscoveryRef 904 ); 905 } 906 } 907 908 return answer; 909 } 910 911 private ServiceDiscovery retrieveServiceDiscovery(CamelContext camelContext) throws Exception { 912 return Suppliers.firstNotNull( 913 () -> (serviceDiscoveryConfiguration != null) ? serviceDiscoveryConfiguration.newInstance(camelContext) : null, 914 // Local configuration 915 () -> retrieve(ServiceDiscovery.class, camelContext, this::getServiceDiscovery, this::getServiceDiscoveryRef), 916 // Linked configuration 917 () -> retrieveServiceDiscovery(camelContext, this::retrieveConfig), 918 // Default configuration 919 () -> retrieveServiceDiscovery(camelContext, this::retrieveDefaultConfig), 920 // Check if there is a single instance in the registry 921 () -> findByType(camelContext, ServiceDiscovery.class), 922 // From registry 923 () -> lookup(camelContext, ServiceCallDefinitionConstants.DEFAULT_SERVICE_DISCOVERY_ID, ServiceDiscovery.class) 924 ).orElseGet( 925 // Default, that's s little ugly but a load balancer may live without 926 // (i.e. the Ribbon one) so let's delegate the null check to the actual 927 // impl. 928 () -> null 929 ); 930 } 931 932 // ****************************************** 933 // ServiceFilter 934 // ****************************************** 935 936 private ServiceFilter retrieveServiceFilter(CamelContext camelContext, Function<CamelContext, ServiceCallConfigurationDefinition> function) throws Exception { 937 ServiceFilter answer = null; 938 939 ServiceCallConfigurationDefinition config = function.apply(camelContext); 940 if (config != null) { 941 if (config.getServiceFilterConfiguration() != null) { 942 answer = config.getServiceFilterConfiguration().newInstance(camelContext); 943 } else { 944 answer = retrieve( 945 ServiceFilter.class, 946 camelContext, 947 config::getServiceFilter, 948 config::getServiceFilterRef 949 ); 950 } 951 952 if (answer == null) { 953 String ref = config.getServiceFilterRef(); 954 if (ObjectHelper.equal("healthy", ref, true)) { 955 answer = new HealthyServiceFilter(); 956 } else if (ObjectHelper.equal("pass-through", ref, true)) { 957 answer = new PassThroughServiceFilter(); 958 } else if (ObjectHelper.equal("passthrough", ref, true)) { 959 answer = new PassThroughServiceFilter(); 960 } 961 } 962 } 963 964 return answer; 965 } 966 967 private ServiceFilter retrieveServiceFilter(CamelContext camelContext) throws Exception { 968 return Suppliers.firstNotNull( 969 () -> (serviceFilterConfiguration != null) ? serviceFilterConfiguration.newInstance(camelContext) : null, 970 // Local configuration 971 () -> retrieve(ServiceFilter.class, camelContext, this::getServiceFilter, this::getServiceFilterRef), 972 // Linked configuration 973 () -> retrieveServiceFilter(camelContext, this::retrieveConfig), 974 // Default configuration 975 () -> retrieveServiceFilter(camelContext, this::retrieveDefaultConfig), 976 // Check if there is a single instance in the registry 977 () -> findByType(camelContext, ServiceFilter.class), 978 // From registry 979 () -> lookup(camelContext, ServiceCallDefinitionConstants.DEFAULT_SERVICE_FILTER_ID, ServiceFilter.class) 980 ).orElseGet( 981 // Default 982 () -> new HealthyServiceFilter() 983 ); 984 } 985 986 // ****************************************** 987 // ServiceChooser 988 // ****************************************** 989 990 private ServiceChooser retrieveServiceChooser(CamelContext camelContext, Function<CamelContext, ServiceCallConfigurationDefinition> function) throws Exception { 991 ServiceChooser answer = null; 992 993 ServiceCallConfigurationDefinition config = function.apply(camelContext); 994 if (config != null) { 995 answer = retrieve( 996 ServiceChooser.class, 997 camelContext, 998 config::getServiceChooser, 999 config::getServiceChooserRef 1000 ); 1001 1002 if (answer == null) { 1003 String ref = config.getServiceChooserRef(); 1004 if (ObjectHelper.equal("roundrobin", ref, true)) { 1005 answer = new RoundRobinServiceChooser(); 1006 } else if (ObjectHelper.equal("round-robin", ref, true)) { 1007 answer = new RoundRobinServiceChooser(); 1008 } else if (ObjectHelper.equal("random", ref, true)) { 1009 answer = new RandomServiceChooser(); 1010 } 1011 } 1012 } 1013 1014 return answer; 1015 } 1016 1017 private ServiceChooser retrieveServiceChooser(CamelContext camelContext) throws Exception { 1018 return Suppliers.firstNotNull( 1019 // Local configuration 1020 () -> retrieve(ServiceChooser.class, camelContext, this::getServiceChooser, this::getServiceChooserRef), 1021 // Linked configuration 1022 () -> retrieveServiceChooser(camelContext, this::retrieveConfig), 1023 // Default configuration 1024 () -> retrieveServiceChooser(camelContext, this::retrieveDefaultConfig), 1025 // Check if there is a single instance in the registry 1026 () -> findByType(camelContext, ServiceChooser.class), 1027 // From registry 1028 () -> lookup(camelContext, ServiceCallDefinitionConstants.DEFAULT_SERVICE_CHOOSER_ID, ServiceChooser.class) 1029 ).orElseGet( 1030 // Default 1031 () -> new RoundRobinServiceChooser() 1032 ); 1033 } 1034 1035 // ****************************************** 1036 // LoadBalancer 1037 // ****************************************** 1038 1039 private ServiceLoadBalancer retrieveLoadBalancer(CamelContext camelContext, Function<CamelContext, ServiceCallConfigurationDefinition> function) throws Exception { 1040 ServiceLoadBalancer answer = null; 1041 1042 ServiceCallConfigurationDefinition config = function.apply(camelContext); 1043 if (config != null) { 1044 if (config.getLoadBalancerConfiguration() != null) { 1045 answer = config.getLoadBalancerConfiguration().newInstance(camelContext); 1046 } else { 1047 answer = retrieve( 1048 ServiceLoadBalancer.class, 1049 camelContext, 1050 config::getLoadBalancer, 1051 config::getLoadBalancerRef 1052 ); 1053 } 1054 } 1055 1056 return answer; 1057 } 1058 1059 private ServiceLoadBalancer retrieveLoadBalancer(CamelContext camelContext) throws Exception { 1060 return Suppliers.firstNotNull( 1061 () -> (loadBalancerConfiguration != null) ? loadBalancerConfiguration.newInstance(camelContext) : null, 1062 // Local configuration 1063 () -> retrieve(ServiceLoadBalancer.class, camelContext, this::getLoadBalancer, this::getLoadBalancerRef), 1064 // Linked configuration 1065 () -> retrieveLoadBalancer(camelContext, this::retrieveConfig), 1066 // Default configuration 1067 () -> retrieveLoadBalancer(camelContext, this::retrieveDefaultConfig), 1068 // Check if there is a single instance in the registry 1069 () -> findByType(camelContext, ServiceLoadBalancer.class), 1070 // From registry 1071 () -> lookup(camelContext, ServiceCallDefinitionConstants.DEFAULT_LOAD_BALANCER_ID, ServiceLoadBalancer.class) 1072 ).orElseGet( 1073 // Default 1074 () -> new DefaultServiceLoadBalancer() 1075 ); 1076 } 1077 1078 // ****************************************** 1079 // Expression 1080 // ****************************************** 1081 1082 private Expression retrieveExpression(CamelContext camelContext, Function<CamelContext, ServiceCallConfigurationDefinition> function) throws Exception { 1083 Expression answer = null; 1084 1085 ServiceCallConfigurationDefinition config = function.apply(camelContext); 1086 if (config != null) { 1087 if (config.getExpressionConfiguration() != null) { 1088 answer = config.getExpressionConfiguration().newInstance(camelContext); 1089 } else { 1090 answer = retrieve( 1091 Expression.class, 1092 camelContext, 1093 config::getExpression, 1094 config::getExpressionRef 1095 ); 1096 } 1097 } 1098 1099 return answer; 1100 } 1101 1102 private Expression retrieveExpression(CamelContext camelContext, String component) throws Exception { 1103 Optional<Expression> expression = Suppliers.firstNotNull( 1104 () -> (expressionConfiguration != null) ? expressionConfiguration.newInstance(camelContext) : null, 1105 // Local configuration 1106 () -> retrieve(Expression.class, camelContext, this::getExpression, this::getExpressionRef), 1107 // Linked configuration 1108 () -> retrieveExpression(camelContext, this::retrieveConfig), 1109 // Default configuration 1110 () -> retrieveExpression(camelContext, this::retrieveDefaultConfig), 1111 // From registry 1112 () -> lookup(camelContext, ServiceCallDefinitionConstants.DEFAULT_SERVICE_CALL_EXPRESSION_ID, Expression.class) 1113 ); 1114 1115 if (expression.isPresent()) { 1116 return expression.get(); 1117 } else { 1118 String lookupName = component + "-service-expression"; 1119 // First try to find the factory from the registry. 1120 ServiceExpressionFactory factory = CamelContextHelper.lookup(camelContext, lookupName, ServiceExpressionFactory.class); 1121 if (factory != null) { 1122 // If a factory is found in the registry do not re-configure it as 1123 // it should be pre-configured. 1124 return factory.newInstance(camelContext); 1125 } else { 1126 1127 Class<?> type = null; 1128 1129 try { 1130 // Then use Service factory. 1131 type = camelContext.getFactoryFinder(ServiceCallDefinitionConstants.RESOURCE_PATH).findClass(lookupName); 1132 } catch (Exception e) { 1133 } 1134 1135 if (ObjectHelper.isNotEmpty(type)) { 1136 if (ServiceExpressionFactory.class.isAssignableFrom(type)) { 1137 factory = (ServiceExpressionFactory) camelContext.getInjector().newInstance(type); 1138 } else { 1139 throw new IllegalArgumentException( 1140 "Resolving Expression: " + lookupName + " detected type conflict: Not a ServiceExpressionFactory implementation. Found: " + type.getName()); 1141 } 1142 } else { 1143 // If no factory is found, returns the default 1144 factory = context -> new DefaultServiceCallExpression(); 1145 } 1146 1147 return factory.newInstance(camelContext); 1148 } 1149 } 1150 } 1151 1152 // ************************************ 1153 // Helpers 1154 // ************************************ 1155 1156 private <T> T retrieve(Class<T> type, CamelContext camelContext, Supplier<T> instanceSupplier, Supplier<String> refSupplier) { 1157 T answer = null; 1158 if (instanceSupplier != null) { 1159 answer = instanceSupplier.get(); 1160 } 1161 1162 if (answer == null && refSupplier != null) { 1163 String ref = refSupplier.get(); 1164 if (ref != null) { 1165 answer = lookup(camelContext, ref, type); 1166 } 1167 } 1168 1169 return answer; 1170 } 1171}