remove the list of serviceIds and add ServiceListInitializer
This commit is contained in:
@@ -1,24 +0,0 @@
|
||||
package org.springframework.cloud.client;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* TODO: move org.springframework.cloud.client to a spring-cloud-common project
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
@ConditionalOnExpression("${spring.cloud.client.enabled:true}")
|
||||
public class ClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ClientProperties.class)
|
||||
public ClientProperties clientProperties() {
|
||||
return new ClientProperties();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package org.springframework.cloud.client;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties("spring.cloud.client")
|
||||
public class ClientProperties {
|
||||
private List<String> serviceIds;
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import static com.netflix.config.ConfigurationManager.APPLICATION_PROPERTIES;
|
||||
import static com.netflix.config.ConfigurationManager.ENV_CONFIG_NAME;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 7/3/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Configuration
|
||||
public class ArchaiusAutoConfiguration {
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 6/27/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class ConfigurableEnvironmentConfiguration extends AbstractConfiguration {
|
||||
ConfigurableEnvironment environment;
|
||||
|
||||
@@ -19,7 +19,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.client.ClientProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@@ -47,10 +46,4 @@ public class EurekaClientAutoConfiguration {
|
||||
public EurekaInstanceConfigBean eurekaInstanceConfigBean() {
|
||||
return new EurekaInstanceConfigBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(EurekaRibbonInitializer.class)
|
||||
public EurekaRibbonInitializer eurekaRibbonInitializer(ClientProperties clientProperties) {
|
||||
return new EurekaRibbonInitializer(clientProperties);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
package org.springframework.cloud.netflix.eureka;
|
||||
|
||||
import com.netflix.config.ConfigurationManager;
|
||||
import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList;
|
||||
import org.springframework.cloud.client.ClientProperties;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class EurekaRibbonInitializer {
|
||||
|
||||
public EurekaRibbonInitializer(ClientProperties clientProperties) {
|
||||
if (clientProperties.getServiceIds() != null) {
|
||||
for (String serviceId : clientProperties.getServiceIds()) {
|
||||
setServiceListClassAndVIP(serviceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setServiceListClassAndVIP(String serviceId) {
|
||||
setProp(serviceId, "NIWSServerListClassName", DiscoveryEnabledNIWSServerList.class.getName());
|
||||
setProp(serviceId, "DeploymentContextBasedVipAddresses", serviceId); //FIXME: what should this be?
|
||||
}
|
||||
|
||||
private static void setProp(String serviceId, String suffix, String value) {
|
||||
ConfigurationManager.getConfigInstance().setProperty(serviceId + ".ribbon." + suffix, value);
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 7/3/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureAfter(ArchaiusAutoConfiguration.class)
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 6/27/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class FeignBase {
|
||||
public static final boolean romePresent =
|
||||
|
||||
@@ -7,19 +7,23 @@ import feign.codec.Decoder;
|
||||
import feign.codec.Encoder;
|
||||
import feign.ribbon.LoadBalancingTarget;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.netflix.ribbon.ServerListInitializer;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.cloud.netflix.archaius.ConfigurableEnvironmentConfiguration;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 7/3/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Configuration
|
||||
public class FeignConfigurer {
|
||||
@Autowired
|
||||
ConfigurableEnvironmentConfiguration envConfig; //FIXME: howto enforce this?
|
||||
|
||||
@Autowired
|
||||
ServerListInitializer serverListInitializer;
|
||||
|
||||
@Autowired
|
||||
Decoder decoder;
|
||||
|
||||
@@ -48,6 +52,7 @@ public class FeignConfigurer {
|
||||
|
||||
protected <T> T loadBalance(Feign.Builder builder, Class<T> type, String schemeName) {
|
||||
String name = URI.create(schemeName).getHost();
|
||||
serverListInitializer.initialize(name);
|
||||
return builder.target(LoadBalancingTarget.create(type, schemeName));
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import feign.codec.DecodeException;
|
||||
import feign.codec.Decoder;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 6/26/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class SpringDecoder extends FeignBase implements Decoder {
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 6/26/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class SpringEncoder extends FeignBase implements Encoder {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SpringEncoder.class);
|
||||
|
||||
@@ -13,7 +13,7 @@ import feign.Contract;
|
||||
import feign.MethodMetadata;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 6/27/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class SpringMvcContract extends Contract.BaseContract {
|
||||
static final String ACCEPT = "Accept";
|
||||
|
||||
@@ -7,7 +7,7 @@ import org.springframework.core.Ordered;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 6/19/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
@@ -28,7 +28,7 @@ import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsPoller;
|
||||
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsPoller.MetricsAsJsonPollerListener;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 6/19/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Configuration
|
||||
public class HystrixConfiguration implements ImportAware {
|
||||
|
||||
@@ -5,7 +5,7 @@ import org.springframework.context.annotation.AdviceModeImportSelector;
|
||||
import org.springframework.context.annotation.AutoProxyRegistrar;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 6/19/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class HystrixConfigurationSelector extends AdviceModeImportSelector<EnableHystrix> {
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.springframework.cloud.netflix.hystrix;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 6/19/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public interface HystrixConfigurer {
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package org.springframework.cloud.netflix.ribbon;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaRibbonInitializer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
@@ -21,10 +19,6 @@ import java.util.List;
|
||||
@AutoConfigureAfter(EurekaClientAutoConfiguration.class)
|
||||
public class RibbonAutoConfiguration {
|
||||
|
||||
//TODO: why doesn't @AutoConfigureAfter(EurekaClientAutoConfiguration.class) do what the following does for order?
|
||||
@Autowired
|
||||
EurekaRibbonInitializer eurekaRibbonInitializer;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(RestTemplate.class)
|
||||
public RestTemplate restTemplate(RibbonInterceptor ribbonInterceptor) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.springframework.cloud.netflix.ribbon;
|
||||
import com.netflix.client.ClientFactory;
|
||||
import com.netflix.loadbalancer.ILoadBalancer;
|
||||
import com.netflix.loadbalancer.Server;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
|
||||
@@ -10,8 +11,12 @@ import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class RibbonLoadBalancerClient implements LoadBalancerClient {
|
||||
@Autowired
|
||||
private ServerListInitializer serverListInitializer;
|
||||
|
||||
@Override
|
||||
public ServiceInstance choose(String serviceId) {
|
||||
serverListInitializer.initialize(serviceId);
|
||||
ILoadBalancer loadBalancer = ClientFactory.getNamedLoadBalancer(serviceId);
|
||||
Server server = loadBalancer.chooseServer(null);
|
||||
if (server == null) {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.springframework.cloud.netflix.ribbon;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public interface ServerListInitializer {
|
||||
public void initialize(String serviceId);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.springframework.cloud.netflix.ribbon.eureka;
|
||||
|
||||
import com.netflix.config.ConfigurationManager;
|
||||
import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList;
|
||||
import org.springframework.cloud.netflix.ribbon.ServerListInitializer;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class EurekaRibbonInitializer implements ServerListInitializer {
|
||||
|
||||
@Override
|
||||
public void initialize(String serviceId) {
|
||||
//TODO: should this look more like hibernate spring boot props?
|
||||
setProp(serviceId, "NIWSServerListClassName", DiscoveryEnabledNIWSServerList.class.getName());
|
||||
setProp(serviceId, "DeploymentContextBasedVipAddresses", serviceId); //FIXME: what should this be?
|
||||
}
|
||||
|
||||
protected void setProp(String serviceId, String suffix, String value) {
|
||||
//how to set the namespace properly?
|
||||
String namespace = "ribbon";
|
||||
ConfigurationManager.getConfigInstance().setProperty(serviceId + "."+ namespace +"." + suffix, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.netflix.ribbon.eureka;
|
||||
|
||||
import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.ribbon.ServerListInitializer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
@ConditionalOnClass(DiscoveryEnabledNIWSServerList.class)
|
||||
@ConditionalOnExpression("${ribbon.eureka.enabled:true}")
|
||||
@AutoConfigureBefore(RibbonAutoConfiguration.class)
|
||||
public class RibbonEurekaAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ServerListInitializer.class)
|
||||
public ServerListInitializer serverListInitializer() {
|
||||
return new EurekaRibbonInitializer();
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 7/10/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class Routes {
|
||||
private static final Logger logger = LoggerFactory.getLogger(Routes.class);
|
||||
|
||||
@@ -4,7 +4,7 @@ import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 8/5/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties("zuul.proxy")
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.springframework.cloud.netflix.zuul.filters.route;
|
||||
|
||||
import static org.springframework.cloud.netflix.eureka.EurekaRibbonInitializer.setServiceListClassAndVIP;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
@@ -18,7 +16,9 @@ import org.apache.commons.io.IOUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.actuate.trace.TraceRepository;
|
||||
import org.springframework.cloud.netflix.ribbon.ServerListInitializer;
|
||||
import org.springframework.cloud.netflix.zuul.RibbonCommand;
|
||||
import org.springframework.cloud.netflix.zuul.SpringFilter;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.netflix.client.ClientException;
|
||||
@@ -27,13 +27,12 @@ import com.netflix.client.http.HttpRequest.Verb;
|
||||
import com.netflix.client.http.HttpResponse;
|
||||
import com.netflix.hystrix.exception.HystrixRuntimeException;
|
||||
import com.netflix.niws.client.http.RestClient;
|
||||
import com.netflix.zuul.ZuulFilter;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
import com.netflix.zuul.exception.ZuulException;
|
||||
import com.netflix.zuul.util.HTTPRequestUtils;
|
||||
import com.sun.jersey.core.util.MultivaluedMapImpl;
|
||||
|
||||
public class RibbonRoutingFilter extends ZuulFilter {
|
||||
public class RibbonRoutingFilter extends SpringFilter {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(RibbonRoutingFilter.class);
|
||||
|
||||
@@ -72,8 +71,8 @@ public class RibbonRoutingFilter extends ZuulFilter {
|
||||
|
||||
String serviceId = (String) context.get("serviceId");
|
||||
|
||||
// TODO: can this be set be default? or an implementation of an interface?
|
||||
setServiceListClassAndVIP(serviceId);
|
||||
//TODO: should this be an interface or just config?
|
||||
getBean(ServerListInitializer.class).initialize(serviceId);
|
||||
|
||||
RestClient restClient = (RestClient) ClientFactory.getNamedClient(serviceId);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.cloud.client.ClientAutoConfiguration,\
|
||||
org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration,\
|
||||
org.springframework.cloud.netflix.feign.FeignAutoConfiguration,\
|
||||
org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration,\
|
||||
org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration,\
|
||||
org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,\
|
||||
org.springframework.cloud.netflix.servo.ServoMetricsAutoConfiguration
|
||||
@@ -20,7 +20,7 @@ import java.net.URI;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 7/29/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Controller
|
||||
public class EurekaController {
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.lang.annotation.Target;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 6/19/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.util.List;
|
||||
import static com.netflix.turbine.monitor.cluster.AggregateClusterMonitor.AggregatorClusterMonitorConsole;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 7/14/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class SpringAggregatorFactory implements ClusterMonitorFactory<AggDataFromCluster> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SpringAggregatorFactory.class);
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.netflix.turbine.monitor.cluster.ObservationCriteria;
|
||||
import com.netflix.turbine.monitor.instance.InstanceUrlClosure;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 7/14/14.
|
||||
* @author Spencer Gibb
|
||||
* TODO: convert to ConfigurationProperties (how to do per-cluster configuration?)
|
||||
*/
|
||||
public class SpringClusterMonitor extends AggregateClusterMonitor {
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
/**
|
||||
* Created by sgibb on 7/11/14.
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Configuration
|
||||
@EnableEurekaClient
|
||||
|
||||
@@ -99,16 +99,6 @@ public class StoreIntegration {
|
||||
|
||||
== Declarative REST Client: Feign
|
||||
|
||||
Example application.yml:
|
||||
|
||||
```
|
||||
spring:
|
||||
cloud:
|
||||
client:
|
||||
serviceIds:
|
||||
- stores
|
||||
```
|
||||
|
||||
Example spring boot app
|
||||
```
|
||||
@Configuration
|
||||
@@ -142,16 +132,6 @@ public interface StoreClient {
|
||||
|
||||
== Client Side Load Balancer: Ribbon
|
||||
|
||||
Example application.yml:
|
||||
|
||||
```
|
||||
spring:
|
||||
cloud:
|
||||
client:
|
||||
serviceIds:
|
||||
- stores
|
||||
```
|
||||
|
||||
Usage of `LoadBalancerClient` directly:
|
||||
|
||||
```
|
||||
@@ -160,7 +140,6 @@ public class MyClass {
|
||||
private LoadBalancerClient loadBalancer;
|
||||
|
||||
public void doStuff() {
|
||||
//"stores" in choose() must match a service in spring.cloud.client.serviceIds
|
||||
ServiceInstance instance = loadBalancer.choose("stores");
|
||||
URI storesUri = URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort()));
|
||||
// ... do something with the URI
|
||||
@@ -168,7 +147,7 @@ public class MyClass {
|
||||
}
|
||||
```
|
||||
|
||||
Indirect usage via `RestTemplate`. Notice the `stores` hostname part, must match a service id in spring.cloud.client.serviceIds:
|
||||
Indirect usage via `RestTemplate`.
|
||||
|
||||
```
|
||||
public class MyClass {
|
||||
|
||||
Reference in New Issue
Block a user