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.impl.cloud;
018
019import java.util.List;
020import java.util.concurrent.RejectedExecutionException;
021
022import org.apache.camel.CamelContext;
023import org.apache.camel.CamelContextAware;
024import org.apache.camel.cloud.ServiceChooser;
025import org.apache.camel.cloud.ServiceChooserAware;
026import org.apache.camel.cloud.ServiceDefinition;
027import org.apache.camel.cloud.ServiceDiscovery;
028import org.apache.camel.cloud.ServiceDiscoveryAware;
029import org.apache.camel.cloud.ServiceFilter;
030import org.apache.camel.cloud.ServiceFilterAware;
031import org.apache.camel.cloud.ServiceLoadBalancer;
032import org.apache.camel.cloud.ServiceLoadBalancerFunction;
033import org.apache.camel.support.ServiceSupport;
034import org.apache.camel.util.ObjectHelper;
035import org.apache.camel.util.ServiceHelper;
036import org.slf4j.Logger;
037import org.slf4j.LoggerFactory;
038
039public class DefaultServiceLoadBalancer
040        extends ServiceSupport
041        implements CamelContextAware, ServiceDiscoveryAware, ServiceChooserAware, ServiceFilterAware, ServiceLoadBalancer {
042
043    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultServiceLoadBalancer.class);
044
045    private CamelContext camelContext;
046    private ServiceDiscovery serviceDiscovery;
047    private ServiceChooser serviceChooser;
048    private ServiceFilter serviceFilter;
049
050    public DefaultServiceLoadBalancer() {
051    }
052
053    // *************************************
054    // Bean
055    // *************************************
056
057    @Override
058    public CamelContext getCamelContext() {
059        return camelContext;
060    }
061
062    @Override
063    public void setCamelContext(CamelContext camelContext) {
064        this.camelContext = camelContext;
065    }
066
067    @Override
068    public ServiceDiscovery getServiceDiscovery() {
069        return serviceDiscovery;
070    }
071
072    @Override
073    public void setServiceDiscovery(ServiceDiscovery serverDiscovery) {
074        this.serviceDiscovery = serverDiscovery;
075    }
076
077    @Override
078    public ServiceChooser getServiceChooser() {
079        return serviceChooser;
080    }
081
082    @Override
083    public void setServiceChooser(ServiceChooser serverChooser) {
084        this.serviceChooser = serverChooser;
085    }
086
087    @Override
088    public void setServiceFilter(ServiceFilter serviceFilter) {
089        this.serviceFilter = serviceFilter;
090    }
091
092    @Override
093    public ServiceFilter getServiceFilter() {
094        return serviceFilter;
095    }
096
097    // *************************************
098    // Lifecycle
099    // *************************************
100
101    @Override
102    protected void doStart() throws Exception {
103        ObjectHelper.notNull(camelContext, "camel context");
104        ObjectHelper.notNull(serviceDiscovery, "service discovery");
105        ObjectHelper.notNull(serviceChooser, "service chooser");
106        ObjectHelper.notNull(serviceFilter, "service serviceFilter");
107
108        LOGGER.info("ServiceCall is using default load balancer with service discovery type: {}, service filter type: {} and service chooser type: {}",
109            serviceDiscovery.getClass(),
110            serviceFilter.getClass(),
111            serviceChooser.getClass());
112
113        ServiceHelper.startService(serviceChooser);
114        ServiceHelper.startService(serviceDiscovery);
115    }
116
117    @Override
118    protected void doStop() throws Exception {
119        // Stop services if needed
120        ServiceHelper.stopService(serviceDiscovery);
121        ServiceHelper.stopService(serviceChooser);
122    }
123
124    // *************************************
125    // Load Balancer
126    // *************************************
127
128    @Override
129    public <T> T process(String serviceName, ServiceLoadBalancerFunction<T> function) throws Exception {
130        ServiceDefinition service;
131
132        List<ServiceDefinition> services = serviceDiscovery.getServices(serviceName);
133        if (services == null || services.isEmpty()) {
134            throw new RejectedExecutionException("No active services with name " + serviceName);
135        } else {
136            // filter services
137            services = serviceFilter.apply(services);
138            // let the client service chooser find which server to use
139            service = services.isEmpty() ? null : services.size() > 1 ? serviceChooser.choose(services) : services.get(0);
140            if (service == null) {
141                throw new RejectedExecutionException("No active services with name " + serviceName);
142            }
143        }
144
145        return function.apply(service);
146    }
147}