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