Java tutorial
/* Copyright (c) 2016 * by Bjnd Health, Inc., Boston, MA * * This software is furnished under a license and may be used only in * accordance with the terms of such license. This software may not be * provided or otherwise made available to any other party. No title to * nor ownership of the software is hereby transferred. * * This software is the intellectual property of Bjnd Health, Inc., * and is protected by the copyright laws of the United States of America. * All rights reserved internationally. * */ package com.bjond.soa; import java.net.URLEncoder; import java.nio.charset.Charset; import java.util.List; import com.bjond.soa.proxy.IRestService; import com.google.inject.AbstractModule; import com.google.inject.Scopes; import com.netflix.appinfo.EurekaInstanceConfig; import com.netflix.appinfo.InstanceInfo; import com.netflix.appinfo.providers.MyDataCenterInstanceConfigProvider; import com.netflix.client.config.CommonClientConfigKey; import com.netflix.config.ConfigurationManager; import com.netflix.discovery.EurekaClient; import com.netflix.discovery.guice.EurekaModule; import com.netflix.governator.InjectorBuilder; import com.netflix.governator.LifecycleInjector; import com.netflix.ribbon.ClientOptions; import com.netflix.ribbon.Ribbon; import com.netflix.ribbon.RibbonResponse; import com.netflix.ribbon.http.HttpRequestTemplate; import com.netflix.ribbon.http.HttpResourceGroup; import com.netflix.ribbon.proxy.ProxyLifeCycle; import io.netty.buffer.ByteBuf; /** <p> Uses Ribbon to ping a service. </p> * * <a href="mailto:Stephen.Agneta@bjondinc.com">Steve 'Crash' Agneta</a> * */ //@Slf4j public class RibbonPing { public static void main(String[] args) throws Exception { System.out.println("RibbonPing has been invoked printf"); ///////////////////////////////////////////////////////////////////////// // Eureka Registry Incantation // ///////////////////////////////////////////////////////////////////////// final LifecycleInjector injector = InjectorBuilder.fromModule(new EurekaModule()) .overrideWith(new AbstractModule() { @Override protected void configure() { // the default impl of EurekaInstanceConfig is CloudInstanceConfig, which we only want in an AWS // environment. Here we override that by binding MyDataCenterInstanceConfig to EurekaInstanceConfig. bind(EurekaInstanceConfig.class).toProvider(MyDataCenterInstanceConfigProvider.class) .in(Scopes.SINGLETON); } }).createInjector(); // this is the vip address for the example service to talk to as defined in conf/sample-eureka-service.properties final String vipAddress = "sampleservice.mydomain.net"; final EurekaClient eurekaClient = injector.getInstance(EurekaClient.class); // This is the line that gathers the list of N number of service URL's for vipAddress. final List<InstanceInfo> listOfInstanceInfo = eurekaClient.getInstancesByVipAddress(vipAddress, false); final InstanceInfo nextServerInfo = listOfInstanceInfo.get(0); // I happen to know there is only one for this test thus I cheat here. System.out.println("Found an instance of example service to talk to from eureka: " + nextServerInfo.getVIPAddress() + ":" + nextServerInfo.getPort()); System.out.println("healthCheckUrl: " + nextServerInfo.getHealthCheckUrl()); System.out.println("override: " + nextServerInfo.getOverriddenStatus()); System.out.println("hostname: " + nextServerInfo.getHostName()); System.out.println("InstanceInfo: " + nextServerInfo.toString()); System.out.println("List<InstanceInfo>: " + listOfInstanceInfo.toString()); System.out.println("RibbonPing has made contact with the Eureka Server"); ///////////////////////////////////////////////////////////////////////// // Programmatic Configuration // ///////////////////////////////////////////////////////////////////////// // The printed properties should correspond to the values set within eureka-client.properties file. final String vipAddressContext = (String) ConfigurationManager.getConfigInstance() .getProperty("IRestService.ribbon.DeploymentContextBasedVipAddresses"); System.out.println("vipAddressContext: " + vipAddressContext); final String sNIWSServerListClassName = (String) ConfigurationManager.getConfigInstance() .getProperty("IRestService.ribbon.NIWSServerListClassName"); System.out.println("NIWSServerListClassName: " + sNIWSServerListClassName); // Let's set the retries for teh IRestService ribbon interface specifically. ConfigurationManager.getConfigInstance() .setProperty("IRestService.ribbon.DeploymentContextBasedVipAddresses." + CommonClientConfigKey.MaxAutoRetriesNextServer, "3"); ///////////////////////////////////////////////////////////////////////// // Proxy Connection // ///////////////////////////////////////////////////////////////////////// final IRestService restService = Ribbon.from(IRestService.class); ByteBuf buffer = restService.ping().execute(); byte[] bytes = new byte[buffer.readableBytes()]; buffer.readBytes(bytes); System.out.println("AS ARRAY: " + new String(bytes, "UTF-8")); System.out.println("Made a ping invocation successfully."); // Send an argument. NOTE that you must escape this for query parameters buffer = restService.echo(URLEncoder.encode("hello world", "UTF-8")).execute(); bytes = new byte[buffer.readableBytes()]; buffer.readBytes(bytes); System.out.println("AS ARRAY: " + new String(bytes, "UTF-8")); System.out.println("Made a ping invocation successfully."); // You can use query params in POST per usual. buffer = restService.echoPost(URLEncoder.encode("hello POST world", "UTF-8")).execute(); bytes = new byte[buffer.readableBytes()]; buffer.readBytes(bytes); System.out.println("AS ARRAY: " + new String(bytes, "UTF-8")); System.out.println("Made a ping invocation successfully."); ///////////////////////////////////////////////////////////////////////// // HttpResourceGroup // ///////////////////////////////////////////////////////////////////////// // Make an invocation using HTTPResourceGroup. // In other words how to perform REST invocations without an annotated proxy. // I would need to construct a list of these if I wanted to round robin a number of servers. // The server list is a comma seperated list for additional servers such as: "localhost:8080,localhost:8088" final String server = String.format("http://%s:%s", nextServerInfo.getHostName(), nextServerInfo.getPort()); final HttpResourceGroup httpResourceGroup = Ribbon.createHttpResourceGroup(vipAddress, ClientOptions.create().withMaxAutoRetriesNextServer(3).withConfigurationBasedServerList(server)); @SuppressWarnings("unchecked") final HttpRequestTemplate<ByteBuf> pingByTemplate = httpResourceGroup .newTemplateBuilder("ping", ByteBuf.class).withMethod("GET") .withUriTemplate("/bjond-resteasy-poc/services/poc/ping").build(); RibbonResponse<ByteBuf> result = pingByTemplate.requestBuilder().build().withMetadata().execute(); ByteBuf buf = result.content(); String value = buf.toString(Charset.forName("UTF-8")); System.out.println("Result: " + value); @SuppressWarnings("unchecked") final HttpRequestTemplate<ByteBuf> echoByTemplate = httpResourceGroup .newTemplateBuilder("echo", ByteBuf.class).withMethod("GET") .withUriTemplate("/bjond-resteasy-poc/services/poc/echo?value={value}").build(); result = echoByTemplate.requestBuilder() .withRequestProperty("value", URLEncoder.encode("hello template world", "UTF-8")).build() .withMetadata().execute(); buf = result.content(); value = buf.toString(Charset.forName("UTF-8")); // this toString() trick only works here. Does not work with annotated proxies. Why? System.out.println("Result: " + value); ///////////////////////////////////////////////////////////////////////// // shutdown // ///////////////////////////////////////////////////////////////////////// ((ProxyLifeCycle) restService).shutdown(); eurekaClient.shutdown(); injector.shutdown(); ConfigurationManager.getConfigInstance().clear(); System.out.println("Shutting down"); // there is some daemon thread presumably in eureka-client I can't find. System.exit(0); } }