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