Sorry

This feed does not validate.

In addition, interoperability with the widest range of feed readers could be improved by implementing the following recommendations.

Source: http://ryanjbaxter.com/feed.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  3. <channel>
  4. <title>ryanjbaxter.github.io</title>
  5. <description>Husband, Father, Software Engineer</description>
  6. <link>/</link>
  7. <atom:link href="/feed.xml" rel="self" type="application/rss+xml" />
  8. <item>
  9. <title>Retrying HTTP Requests In Spring Cloud Netflix</title>
  10. <description>&lt;p&gt;As I have talked about before, one of the key aspects of cloud native applications is resiliency.  In order to be robust and avoid all the potential problems that can come from running in  such a volatile environment like the cloud your application needs to be able to handle anything that can be thrown at it.  One of the more common operations a cloud native application will do is make HTTP requests to other applications.  These applications may be under your control as well or they could be third party apps, but in the end it doesn’t really matter who controls them, there is always the potential for failure when making any kind of network request.&lt;/p&gt;
  11.  
  12. &lt;p&gt;Cloud native apps should be able to deal with any kind of failure in a graceful manor.  Circuit breakers, which I have talked about &lt;a href=&quot;http://ryanjbaxter.com/2015/10/12/building-cloud-native-apps-with-spring-part-5/&quot;&gt;before&lt;/a&gt;, are one way of dealing with failures.  Before we get to the point of tripping a circuit breaker, we can try to be a smarter about the network requests we make.  Just because a network request fails once doesn’t mean we should give up and all hope is lost.&lt;/p&gt;
  13.  
  14. &lt;p&gt;Network requests can fail for a number of reasons.  Yes the service you may be making a request to may be down, which is probably the worst case scenario, but there are other reasons as well.  Maybe it is just the network itself having issues.  Maybe the service you are trying to make a request to is actually up but is temporarily unavailable.  Whatever the reason may be for the failure, it could be a short term issue.  If you were to make the same request shortly after the failure occurs it may succeed.  So in order to make our applications more resilient we can retry failed requests in the hope that subsequent requests might succeed.&lt;/p&gt;
  15.  
  16. &lt;p&gt;If you are familiar with Spring Cloud Netflix, there are a number ways to make HTTP requests.  The three main ways are using a &lt;a href=&quot;http://cloud.spring.io/spring-cloud-static/Camden.SR5/#_spring_resttemplate_as_a_load_balancer_client&quot;&gt;load balanced &lt;code class=&quot;highlighter-rouge&quot;&gt;RestTemplate&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;http://cloud.spring.io/spring-cloud-static/Camden.SR5/#spring-cloud-feign&quot;&gt;Feign&lt;/a&gt;, and &lt;a href=&quot;http://cloud.spring.io/spring-cloud-static/Camden.SR5/#_router_and_filter_zuul&quot;&gt;Zuul&lt;/a&gt;.  In Spring Cloud Brixton all three of these scenarios leveraged an HTTP client from Netflix that has built-in logic to retry failed requests.  However, this HTTP client was deprecated and we needed to come up with our own HTTP client to use.  Unfortunately when implementing the new HTTP client we did not originally include logic to retry failed requests.  As of &lt;a href=&quot;https://spring.io/blog/2017/03/10/spring-cloud-camden-sr6-is-available&quot;&gt;Spring Cloud Camden.SR6&lt;/a&gt; all three use cases now once again have logic to retry failed requests.&lt;/p&gt;
  17.  
  18. &lt;p&gt;To achieve this we leveraged &lt;a href=&quot;https://github.com/spring-projects/spring-retry&quot;&gt;Spring Retry&lt;/a&gt; as an easy way of implementing the retry logic.  Because we leverage Spring Retry, you must make sure Spring Retry is on the classpath of your application in order to enable the retry logic.  Without Spring Retry on the classpath you will find that failed requests will not be retried.&lt;/p&gt;
  19.  
  20. &lt;p&gt;You can control how many times a request is retried using standard Ribbon properties.
  21. To control how many times a request is retried on the same server you can adjust &lt;code class=&quot;highlighter-rouge&quot;&gt;sample-client.ribbon.MaxAutoRetries&lt;/code&gt;.  To control how many servers to try you can adjust &lt;code class=&quot;highlighter-rouge&quot;&gt;sample-client.ribbon.MaxAutoRetriesNextServer&lt;/code&gt;.  The total number of retries that are made will be equal to &lt;code class=&quot;highlighter-rouge&quot;&gt;sample-client.ribbon.MaxAutoRetries * sample-client.ribbon.MaxAutoRetriesNextServer&lt;/code&gt;.  You can also control whether just &lt;code class=&quot;highlighter-rouge&quot;&gt;GET&lt;/code&gt; requests will be retried or whether all requests will be retried by adjusting &lt;code class=&quot;highlighter-rouge&quot;&gt;sample-client.ribbon.OkToRetryOnAllOperations&lt;/code&gt;.  The above properties apply whether you are using a load balanced &lt;code class=&quot;highlighter-rouge&quot;&gt;RestTemplate&lt;/code&gt;, Feign, or Zuul.&lt;/p&gt;
  22.  
  23. &lt;p&gt;When using Zuul there are some additional properties you can configure to control retry functionality.  Setting &lt;code class=&quot;highlighter-rouge&quot;&gt;zuul.retryable&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;true&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;false&lt;/code&gt; will control whether all or none of the proxied requests will be retried.  By default it is set to &lt;code class=&quot;highlighter-rouge&quot;&gt;true&lt;/code&gt;.  You can also control retry functionality on a route by route basis by setting &lt;code class=&quot;highlighter-rouge&quot;&gt;zuul.routes.routename.retryable&lt;/code&gt;.&lt;/p&gt;
  24.  
  25. &lt;p&gt;If you have been sticking to using the deprecated Netflix &lt;code class=&quot;highlighter-rouge&quot;&gt;RestClient&lt;/code&gt; due to the lack of retry logic in the newer HTTP clients hopefully this will now allow you to switch to using the newer clients.  The retry logic we have added should work for both the Apache based HTTP clients of the OK HTTP clients, so you have your choice as to which one you want to use.&lt;/p&gt;
  26. </description>
  27. <pubDate>Wed, 15 Mar 2017 00:00:00 +0000</pubDate>
  28. <link>/cloud/spring%20cloud/spring/2017/03/15/retrying-http-requests-in-spring-cloud-netflix.html</link>
  29. <guid isPermaLink="true">/cloud/spring%20cloud/spring/2017/03/15/retrying-http-requests-in-spring-cloud-netflix.html</guid>
  30. </item>
  31. <item>
  32. <title>Evicting Instances From Eureka</title>
  33. <description>&lt;p&gt;Typically when you are using Spring Cloud Eureka for service discovery and you shut
  34. down an instance that is registered with the server that instance is removed from
  35. the registry.  However in some cases that might not be happen and instead the instance
  36. is just marked as being &lt;code class=&quot;highlighter-rouge&quot;&gt;DOWN&lt;/code&gt;.  If you look at your Eureka dashboard you will see
  37. something like this.&lt;/p&gt;
  38.  
  39. &lt;p&gt;&lt;img src=&quot;https://cloud.githubusercontent.com/assets/524254/18324140/dfc2f822-7508-11e6-85a8-090bc559d722.png&quot; alt=&quot;Eureka Dashboard&quot; /&gt;&lt;/p&gt;
  40.  
  41. &lt;p&gt;Notice one of the &lt;code class=&quot;highlighter-rouge&quot;&gt;RACES&lt;/code&gt; services is marked as down and the big red text above the table.
  42. You might run into this because by default if 85% of instances in Eureka are not sending
  43. heartbeats to the Eureka server than the server will not evict them.  When you see this,
  44. Eureka has entered what is called “self preservation mode”.  The good news is you
  45. should not be alarmed by this.  It is actually Eureka trying to be helpful and by not evicting
  46. instances that are not actually down.  For example, there could be some network issues
  47. preventing instances from sending heartbeat information.  Everything is still functioning
  48. correctly, so do you really want Eureka to start evicting instances?  Probably not.
  49. With any luck the network issues will resolve themselves and heartbeat information will
  50. eventually be received by the server.&lt;/p&gt;
  51.  
  52. &lt;p&gt;If for whatever reason you want to turn off self preservation mode you can set
  53. &lt;code class=&quot;highlighter-rouge&quot;&gt;eureka.server.enableSelfPreservation&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;false&lt;/code&gt;.  For a more in depth discussion
  54. on Eureka’s self preservation mode check out &lt;a href=&quot;http://stackoverflow.com/questions/33921557/understanding-spring-cloud-eureka-server-self-preservation-and-renew-threshold&quot;&gt;this question&lt;/a&gt;
  55. on Stack Overflow.&lt;/p&gt;
  56. </description>
  57. <pubDate>Thu, 05 Jan 2017 00:00:00 +0000</pubDate>
  58. <link>/cloud/spring%20cloud/spring/2017/01/05/eureka-eviction.html</link>
  59. <guid isPermaLink="true">/cloud/spring%20cloud/spring/2017/01/05/eureka-eviction.html</guid>
  60. </item>
  61. <item>
  62. <title>Retrying Requests With Spring Cloud Ribbon</title>
  63. <description>&lt;p&gt;Most applications today make HTTP requests to external services.  When using
  64. Spring Cloud one way to make these requests is to use what we call a
  65. “&lt;a href=&quot;http://cloud.spring.io/spring-cloud-static/spring-cloud.html#_spring_resttemplate_as_a_load_balancer_client&quot;&gt;load balanced &lt;code class=&quot;highlighter-rouge&quot;&gt;RestTemplate&lt;/code&gt;&lt;/a&gt;”.
  66. Creating a load balanced &lt;code class=&quot;highlighter-rouge&quot;&gt;RestTemplate&lt;/code&gt; is pretty strait forward.&lt;/p&gt;
  67.  
  68. &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@Configuration
  69. public class MyConfiguration {
  70.  
  71.    @LoadBalanced
  72.    @Bean
  73.    RestTemplate restTemplate() {
  74.        return new RestTemplate();
  75.    }
  76. }
  77.  
  78. public class MyClass {
  79.    @Autowired
  80.    private RestTemplate restTemplate;
  81.  
  82.    public String doOtherStuff() {
  83.        String results = restTemplate.getForObject(&quot;http://stores/stores&quot;, String.class);
  84.        return results;
  85.    }
  86. }
  87. &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
  88.  
  89. &lt;p&gt;The added &lt;code class=&quot;highlighter-rouge&quot;&gt;@LoadBalanced&lt;/code&gt; annotation allows you to take advantage of services registered
  90. with a discovery service, such as Eureka.  As you can see in the &lt;code class=&quot;highlighter-rouge&quot;&gt;doOtherStuff&lt;/code&gt; method
  91. we are making a request to the URL &lt;code class=&quot;highlighter-rouge&quot;&gt;http://stores/stores&lt;/code&gt;.  The hostname, &lt;code class=&quot;highlighter-rouge&quot;&gt;stores&lt;/code&gt;,
  92. is not actually a registered hostname, instead it is the name of the stores service
  93. registered with the discovery server.  The &lt;code class=&quot;highlighter-rouge&quot;&gt;RestTemplate&lt;/code&gt; in this case will replace
  94. the &lt;code class=&quot;highlighter-rouge&quot;&gt;stores&lt;/code&gt; hostname with the host name (or IP address) of the stores service.&lt;/p&gt;
  95.  
  96. &lt;p&gt;As we are all aware, making requests like this can be problematic.  For any number
  97. of reasons something may go wrong and the request could fail.  That is why, in robust
  98. applications, API requests like the one above may be retried when failures are encountered.  It might
  99. be the case that the service is completely down and we are never going to get a response.
  100. However it is equally as likely that the failure was due to some kind of fluke network issue
  101. and a subsequent request may succeed.  It could even be the case that a given instance of
  102. a service may be experiencing problems but there is another instance available that might be
  103. perfectly capable of handing our request.&lt;/p&gt;
  104.  
  105. &lt;p&gt;In Spring Cloud, if you used a load balanced &lt;code class=&quot;highlighter-rouge&quot;&gt;RestTemplate&lt;/code&gt; to make your API request and the request
  106. failed it was up to you, the developer, to retry the request.  As of &lt;code class=&quot;highlighter-rouge&quot;&gt;Camden.SR2&lt;/code&gt; we have introduced
  107. some retry handling into load balanced &lt;code class=&quot;highlighter-rouge&quot;&gt;RestTemplates&lt;/code&gt;.  We now take advantage of the awesome
  108. &lt;a href=&quot;https://github.com/spring-projects/spring-retry&quot;&gt;Spring Retry project&lt;/a&gt; to provide the retry
  109. logic.  You can use &lt;a href=&quot;http://cloud.spring.io/spring-cloud-static/Camden.SR2/#_retrying_failed_requests&quot;&gt;Ribbon properties&lt;/a&gt;
  110. to configure how many retry requests are made, and which requests are retried.&lt;/p&gt;
  111.  
  112. &lt;p&gt;In the future we will be using Spring Retry when making API requests with Feign as well
  113. as when requests are made through Zuul.&lt;/p&gt;
  114.  
  115. &lt;p&gt;Enjoy!&lt;/p&gt;
  116. </description>
  117. <pubDate>Fri, 04 Nov 2016 00:00:00 +0000</pubDate>
  118. <link>/cloud/spring%20cloud/spring/2016/11/04/ribbon-retry.html</link>
  119. <guid isPermaLink="true">/cloud/spring%20cloud/spring/2016/11/04/ribbon-retry.html</guid>
  120. </item>
  121. <item>
  122. <title>Providing Hystrix Fallbacks For Routes In Zuul</title>
  123. <description>&lt;p&gt;** NOTE: &lt;code class=&quot;highlighter-rouge&quot;&gt;ZuulFallbackProvider&lt;/code&gt; has been deprecated in Spring Cloud Edgware, use &lt;code class=&quot;highlighter-rouge&quot;&gt;FallbackProvider&lt;/code&gt; instead. **&lt;/p&gt;
  124.  
  125. &lt;p&gt;If you are a user of &lt;a href=&quot;https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#router-and-filter-zuul&quot;&gt;Zuul from Spring Cloud Netflix&lt;/a&gt;, than you likely know
  126. that all the routes you configure that use Ribbon are also wrapped in Hystrix
  127. commands.  This nice little feature provides a circuit breaker for all
  128. your proxied requests through Zuul.  When the circuit is tripped it can save
  129. the proxied service from becoming too overloaded and perhaps also save your app
  130. from appearing to be “slow”.&lt;/p&gt;
  131.  
  132. &lt;p&gt;If you have ever looked at &lt;a href=&quot;https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#circuit-breaker-hystrix-clients&quot;&gt;Hystrix&lt;/a&gt; before you know that you can generally
  133. provide a fallback for the circuit.  The fallback provides some default functionality
  134. for the circuit when the circuit is tripped.  For example, if you wrap a request
  135. to a service in a Hystrix Command and provide a fallback, than when the circuit
  136. is tripped and a request is made to the service the fallback will be invoked instead.
  137. What would the fallback return?  One logical response
  138. would be to return back a cached response.  This combination of circuit breaker +
  139. fallback allows for the downstream service to recover while still providing a somewhat
  140. meaningful response back to the calling service.&lt;/p&gt;
  141.  
  142. &lt;p&gt;Up until now it was not possible to provide a fallback when a circuit was tripped
  143. for a given route in Zuul.  The latest &lt;a href=&quot;http://projects.spring.io/spring-cloud/&quot;&gt;Camden snapshot builds&lt;/a&gt; now include a feature allowing
  144. you to specify fallbacks for your routes configured in Zuul.  (All releases prior
  145. to, and including &lt;code class=&quot;highlighter-rouge&quot;&gt;Camden.SR1&lt;/code&gt; do NOT include this functionality.)  It is very simple
  146. to provide a fallback for a route in Zuul.  All you have to do is provide a bean
  147. that implements &lt;code class=&quot;highlighter-rouge&quot;&gt;ZuulFallbackProvider&lt;/code&gt; in your app.  Within that bean you specify
  148. the route ID you want the fallback to apply to and provide a &lt;code class=&quot;highlighter-rouge&quot;&gt;ClientHttpResponse&lt;/code&gt;
  149. object to return when the fallback is invoked.  For more information see the
  150. &lt;a href=&quot;https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#providing-hystrix-fallbacks-for-routes&quot;&gt;Spring Cloud docs&lt;/a&gt;.  If you would like to see a working example check out the
  151. &lt;a href=&quot;https://github.com/spring-cloud-samples/zuul-server&quot;&gt;Zuul Server&lt;/a&gt; sample on GitHub.&lt;/p&gt;
  152. </description>
  153. <pubDate>Thu, 27 Oct 2016 00:00:00 +0000</pubDate>
  154. <link>/cloud/spring%20cloud/spring/2016/10/27/hystrix-fallbacks-with-zuul.html</link>
  155. <guid isPermaLink="true">/cloud/spring%20cloud/spring/2016/10/27/hystrix-fallbacks-with-zuul.html</guid>
  156. </item>
  157. <item>
  158. <title>Manual Creation Of Feign Clients In Spring Cloud</title>
  159. <description>&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2016/10/saying.png&quot; alt=&quot;Saying&quot; /&gt;&lt;/p&gt;
  160.  
  161. &lt;p&gt;Have you ever heard the saying above?  Sometimes it is true even when writing code.&lt;br /&gt;
  162. While Spring Cloud makes it extremely easy to &lt;a href=&quot;https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#how-to-include-feign&quot;&gt;create Feign Clients&lt;/a&gt;
  163. with its use of annotations,
  164. sometimes you just have to bite the bullet and create them yourselves.  I would
  165. say the 90% of the time, the combination of annotations and
  166. &lt;a href=&quot;https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#overriding-feign-defaults&quot;&gt;custom configuration&lt;/a&gt;
  167. will be good enough for most use cases.  Sometimes however, you run into use
  168. cases where that just won’t do.  In these cases it would be good to have full
  169. control over how you create your Feign clients.&lt;/p&gt;
  170.  
  171. &lt;p&gt;Recently I added some &lt;a href=&quot;https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#creating-feign-clients-manually&quot;&gt;documentation&lt;/a&gt;
  172. to the Spring Cloud docs that demonstrates
  173. exactly how you would do this.  Essentially you use the same APIs as you would
  174. if you were just using &lt;a href=&quot;https://github.com/OpenFeign/feign#basics&quot;&gt;vanilla Feign&lt;/a&gt;.
  175. Below is the example taken from the Spring Cloud docs.&lt;/p&gt;
  176.  
  177. &lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Import&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FeignClientsConfiguration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  178. &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FooController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  179.  
  180. &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FooClient&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fooClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  181.  
  182. &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FooClient&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adminClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  183.  
  184.    &lt;span class=&quot;nd&quot;&gt;@Autowired&lt;/span&gt;
  185. &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;FooController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
  186. &lt;span class=&quot;n&quot;&gt;ResponseEntityDecoder&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SpringEncoder&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Client&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  187. &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;fooClient&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Feign&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  188. &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;encoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  189. &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;decoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  190. &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;requestInterceptor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BasicAuthRequestInterceptor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
  191. &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FooClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;http://PROD-SVC&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  192. &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;adminClient&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Feign&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  193. &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;encoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  194. &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;decoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  195. &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;requestInterceptor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BasicAuthRequestInterceptor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;admin&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;admin&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
  196. &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FooClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;http://PROD-SVC&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  197.    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  198. &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  199. &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
  200.  
  201. &lt;p&gt;In this example we are creating two Feign Clients from the same interface,
  202. &lt;code class=&quot;highlighter-rouge&quot;&gt;FooClient.class&lt;/code&gt;, which are using two different request interceptors.
  203. Doing this with the &lt;code class=&quot;highlighter-rouge&quot;&gt;@FeignClient&lt;/code&gt; annotation plus configuration would not be possible,
  204. so in this case we need to create the clients using the Feign APIs.&lt;/p&gt;
  205.  
  206. &lt;p&gt;For a more in depth look at the code, check out
  207. &lt;a href=&quot;https://github.com/ryanjbaxter/manual-feign-demo&quot;&gt;this GitHub repo&lt;/a&gt;.&lt;/p&gt;
  208. </description>
  209. <pubDate>Thu, 20 Oct 2016 00:00:00 +0000</pubDate>
  210. <link>/cloud/spring%20cloud/spring/2016/10/20/manual-feign-clients.html</link>
  211. <guid isPermaLink="true">/cloud/spring%20cloud/spring/2016/10/20/manual-feign-clients.html</guid>
  212. </item>
  213. <item>
  214. <title>Tracing In Microservices With Spring Cloud Sleuth</title>
  215. <description>&lt;p&gt;One of the problems developers encounter as their microservice apps grow is tracing requests
  216. that propagate from one microservice to the next.  It can quite daunting to try
  217. and figure out how a requests travels through the app, especially when you may
  218. not have any insight into the implementation of the microservice you are calling.&lt;br /&gt;
  219. &lt;a href=&quot;https://cloud.spring.io/spring-cloud-sleuth/&quot;&gt;Spring Cloud Sleuth&lt;/a&gt; is meant to help with this exact problem.  It introduces unique
  220. IDs to your logging which are consistent between microservice calls which makes
  221. it possible to find how a single request travels from one microservice to the next.&lt;/p&gt;
  222.  
  223. &lt;p&gt;Spring Cloud Sleuth adds two types of IDs to your logging, one called a trace ID
  224. and the other called a span ID.  The span ID represents a basic unit of work,
  225. for example sending an HTTP request.  The trace ID contains a set of span IDs,
  226. forming a tree-like structure.  The trace ID will remain the same as one microservice
  227. calls the next.  Lets take a look at a simple example which uses
  228. Spring Cloud Sleuth to trace a request.&lt;/p&gt;
  229.  
  230. &lt;p&gt;Start out by going to &lt;a href=&quot;http://start.spring.io&quot;&gt;start.spring.io&lt;/a&gt; and create a new
  231. Spring Boot app that has a dependency on Sleuth (&lt;code class=&quot;highlighter-rouge&quot;&gt;spring-cloud-starter-slueth&lt;/code&gt;).
  232. Generate the project to download the code.  It is good practice to give your application
  233. a name and also necessary to have meaningful tracing from Sleuth.  Create a file called &lt;code class=&quot;highlighter-rouge&quot;&gt;bootstrap.yml&lt;/code&gt; in &lt;code class=&quot;highlighter-rouge&quot;&gt;src/main/resources&lt;/code&gt;.  Within that file
  234. add the property &lt;code class=&quot;highlighter-rouge&quot;&gt;spring.application.name&lt;/code&gt; and set it to whatever you would like to
  235. call your application.  The name you give your application will show up as part of the
  236. tracing produced by Sleuth.&lt;/p&gt;
  237.  
  238. &lt;p&gt;Now lets add some logging to your application so you can see what the tracing will
  239. look like.  Open the application file for your application (where the &lt;code class=&quot;highlighter-rouge&quot;&gt;main&lt;/code&gt; method is)
  240. and create a method called &lt;code class=&quot;highlighter-rouge&quot;&gt;home&lt;/code&gt; which returns a &lt;code class=&quot;highlighter-rouge&quot;&gt;String&lt;/code&gt;.&lt;/p&gt;
  241.  
  242. &lt;pre&gt;&lt;code class=&quot;language-Java&quot;&gt;public String home() {
  243.  return &quot;Hello World&quot;;
  244. }
  245. &lt;/code&gt;&lt;/pre&gt;
  246.  
  247. &lt;p&gt;Lets have this method called when you hit the root of your web app.  Add the
  248. &lt;code class=&quot;highlighter-rouge&quot;&gt;@RestController&lt;/code&gt; annotation at the class level, and then add &lt;code class=&quot;highlighter-rouge&quot;&gt;@RequestMapping(&quot;/&quot;)&lt;/code&gt;
  249. to your &lt;code class=&quot;highlighter-rouge&quot;&gt;home&lt;/code&gt; method.&lt;/p&gt;
  250.  
  251. &lt;pre&gt;&lt;code class=&quot;language-Java&quot;&gt;@SpringBootApplication
  252. @RestController
  253. public class SleuthSampleApplication {
  254. public static void main(String[] args) {
  255. SpringApplication.run(SleuthSampleApplication.class, args);
  256. }
  257.  
  258. @RequestMapping(&quot;/&quot;)
  259. public String home() {
  260. LOG.log(Level.INFO, &quot;you called home&quot;);
  261.    return &quot;Hello World&quot;;
  262. }
  263. }
  264. &lt;/code&gt;&lt;/pre&gt;
  265.  
  266. &lt;p&gt;If you start the app at this point and hit &lt;code class=&quot;highlighter-rouge&quot;&gt;http://localhost:8080&lt;/code&gt; you should see
  267. &lt;code class=&quot;highlighter-rouge&quot;&gt;Hello World&lt;/code&gt; returned.  Up until this point all we have is a basic Spring Boot app.
  268. Lets add some logging to our app to see the tracing information from Sleuth.&lt;/p&gt;
  269.  
  270. &lt;p&gt;Add the following variable to your application class.&lt;/p&gt;
  271.  
  272. &lt;pre&gt;&lt;code class=&quot;language-Java&quot;&gt;private static final Logger LOG = Logger.getLogger(SleuthSampleApplication.class.getName());
  273. &lt;/code&gt;&lt;/pre&gt;
  274.  
  275. &lt;p&gt;Make sure you change the application class name to whatever your application class name is.
  276. In your &lt;code class=&quot;highlighter-rouge&quot;&gt;home&lt;/code&gt; method add the following log statement.&lt;/p&gt;
  277.  
  278. &lt;pre&gt;&lt;code class=&quot;language-Java&quot;&gt;@RequestMapping(&quot;/&quot;)
  279. public String home() {
  280.  LOG.log(Level.INFO, &quot;you called home&quot;);
  281.  return &quot;Hello World&quot;;
  282. }
  283. &lt;/code&gt;&lt;/pre&gt;
  284.  
  285. &lt;p&gt;Now if you run the application and hit &lt;code class=&quot;highlighter-rouge&quot;&gt;http://localhost:8080&lt;/code&gt; you should see
  286. your logging statement printed in the console.&lt;/p&gt;
  287.  
  288. &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;2016-06-15 16:55:56.334  INFO &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;slueth-sample,44462edc42f2ae73,44462edc42f2ae73,false] 13978 &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;nio-8080-exec-1] com.example.SleuthSampleApplication      : calling home
  289. &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
  290.  
  291. &lt;p&gt;The portion of the log statement that Sleuth adds is &lt;code class=&quot;highlighter-rouge&quot;&gt;[slueth-sample,44462edc42f2ae73,44462edc42f2ae73,false]&lt;/code&gt;.
  292. What do all these values mean?  The first part is the application name (whatever you set &lt;code class=&quot;highlighter-rouge&quot;&gt;spring.application.name&lt;/code&gt; to in
  293.  &lt;code class=&quot;highlighter-rouge&quot;&gt;bootstrap.yml&lt;/code&gt;).  The second value is the trace id.  The third value is the span id.  Finally the last value
  294. indicates whether the span should be exported to Zipkin (more on Zipkin later).&lt;/p&gt;
  295.  
  296. &lt;p&gt;Besides adding additional tracing information to logging statements, Spring Cloud Sleuth
  297. also provides some important benefits when calling other microservices.  Remember the real
  298. problem here is not identifying logs within a single microservice but instead tracing
  299. a chain of requests across multiple microservices.  Microservices typically interact with each
  300. other synchronously using REST APIs and asynchronously via message hubs.  Sleuth can
  301. provide tracing information in either scenario but in this example we will take a look
  302. at how REST API calls work.  (Sleuth also supports other microservice communication
  303.  scenarios, see the &lt;a href=&quot;http://cloud.spring.io/spring-cloud-sleuth/spring-cloud-sleuth.html#_integrations&quot;&gt;documentation&lt;/a&gt; for more info.)&lt;/p&gt;
  304.  
  305. &lt;p&gt;A simple example to see how this works is to have our application call itself
  306. using a &lt;code class=&quot;highlighter-rouge&quot;&gt;RestTemplate&lt;/code&gt;.  Lets modify the code in our application class to do
  307. just that.&lt;/p&gt;
  308.  
  309. &lt;pre&gt;&lt;code class=&quot;language-Java&quot;&gt;private static final Logger LOG = Logger.getLogger(SleuthSampleApplication.class.getName());
  310.  
  311. @Autowired
  312. private RestTemplate restTemplate;
  313.  
  314. public static void main(String[] args) {
  315. SpringApplication.run(SleuthSampleApplication.class, args);
  316. }
  317.  
  318. @Bean
  319. public RestTemplate getRestTemplate() {
  320.    return new RestTemplate();
  321. }
  322.  
  323. @RequestMapping(&quot;/&quot;)
  324. public String home() {
  325. LOG.log(Level.INFO, &quot;you called home&quot;);
  326.    return &quot;Hello World&quot;;
  327. }
  328.  
  329. @RequestMapping(&quot;/callhome&quot;)
  330. public String callHome() {
  331. LOG.log(Level.INFO, &quot;calling home&quot;);
  332.    return restTemplate.getForObject(&quot;http://localhost:8080&quot;, String.class);
  333. }
  334. &lt;/code&gt;&lt;/pre&gt;
  335.  
  336. &lt;p&gt;Looking at the code above the first thing you might ask is “Why do we have a
  337. &lt;code class=&quot;highlighter-rouge&quot;&gt;RestTemplate&lt;/code&gt; bean?”  This is necessary because Spring Cloud Sleuth adds the
  338. trace id and span id via headers in the request.  The headers can then be used by
  339. other Spring Cloud Sleuth enabled microservices to trace the request.  In order to do this, the starter
  340. needs the &lt;code class=&quot;highlighter-rouge&quot;&gt;RestTemplate&lt;/code&gt; object you will be using.  By having a bean for our &lt;code class=&quot;highlighter-rouge&quot;&gt;RestTemplate&lt;/code&gt;
  341. it allows Spring Cloud Sleuth to use dependency injection to obtain that object
  342. and add the headers.&lt;/p&gt;
  343.  
  344. &lt;p&gt;We have also added a new method and endpoint called &lt;code class=&quot;highlighter-rouge&quot;&gt;callhome&lt;/code&gt; which just makes a request
  345. to the root of the app.&lt;/p&gt;
  346.  
  347. &lt;p&gt;If you run the app now and hit http://localhost:8080/callhome you will see 2 logging statements
  348. appear in the console that look like.&lt;/p&gt;
  349.  
  350. &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;2016-06-17 16:12:36.902  INFO &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;slueth-sample,432943172b958030,432943172b958030,false] 12157 &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;nio-8080-exec-2] com.example.SleuthSampleApplication      : calling home
  351. 2016-06-17 16:12:36.940  INFO &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;slueth-sample,432943172b958030,b4d88156bc6a49ec,false] 12157 &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;nio-8080-exec-3] com.example.SleuthSampleApplication      : you called home
  352. &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
  353.  
  354. &lt;p&gt;Notice in the logging statements that the trace ids are the same but the span ids are different.
  355. The trace ids are what is going to allow you to trace a request as it travels from one service
  356. to the next.  The span ids are different because we have two different “units of work” occurring,
  357. one for each request.&lt;/p&gt;
  358.  
  359. &lt;p&gt;If you open your browsers debug tools and look at the headers for the request
  360. to &lt;code class=&quot;highlighter-rouge&quot;&gt;/callhome&lt;/code&gt; you will see two headers returned in the response.&lt;/p&gt;
  361.  
  362. &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;X-B3-SpanId: fbf39ca6e571f294
  363. X-B3-TraceId: fbf39ca6e571f294
  364. &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
  365.  
  366. &lt;p&gt;These headers are what allows Sleuth to trace requests between microservices.&lt;/p&gt;
  367.  
  368. &lt;p&gt;While this is a very basic example you can easily imagine how this would work similarly
  369. if one Sleuth enabled app was calling another passing the trace and span ids in the headers.&lt;/p&gt;
  370.  
  371. &lt;p&gt;If you are using Feign from Spring Cloud Netflix, tracing information will also be added
  372. to those requests.  In addition Zuul from Spring Cloud Netflix will also forward along
  373. the trace and span headers through the proxy to other services.&lt;/p&gt;
  374.  
  375. &lt;h2 id=&quot;zipkin&quot;&gt;Zipkin&lt;/h2&gt;
  376.  
  377. &lt;p&gt;All this additional information in your logs is great but making sense of it all
  378. can be quite cumbersome.  Using something like the ELK stack to collect and analyze
  379. the logs from your microservices can be quite helpful.  By using the trace id
  380. you can easily search across all the collected logs and see how the request
  381. passed from one microservice to the next.&lt;/p&gt;
  382.  
  383. &lt;p&gt;However what if you want to see timing information?  You could certainly calculate
  384. how long a request took from one microservice to the next but that is quite a pain to do
  385. yourself.  The good news is that there is a project called &lt;a href=&quot;http://zipkin.io/&quot;&gt;Zipkin&lt;/a&gt; which can help us out.
  386. Spring Cloud Sleuth will send tracing information to any Zipkin server you point it
  387. to when you include the dependency &lt;code class=&quot;highlighter-rouge&quot;&gt;spring-cloud-sleuth-zipkin&lt;/code&gt; in your project.
  388. By default Sleuth assumes your Zipkin server is running at http://localhost:9411.  The location can be configured by setting
  389. &lt;code class=&quot;highlighter-rouge&quot;&gt;spring.zipkin.baseUrl&lt;/code&gt; in your application properties.&lt;/p&gt;
  390.  
  391. &lt;p&gt;We can use Zipkin to collect the tracing information from our simple example above.
  392. Go to &lt;a href=&quot;http://start.spring.io&quot;&gt;start.spring.io&lt;/a&gt; and create a new Boot project that has the
  393. &lt;code class=&quot;highlighter-rouge&quot;&gt;Zipkin UI&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Zipkin Server&lt;/code&gt; dependencies.  In the application properties file for this
  394. new project set &lt;code class=&quot;highlighter-rouge&quot;&gt;server.port&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;9411&lt;/code&gt;.  If you start this application and head to
  395. http://localhost:9411 you will see the Zipkin UI.  Of course there aren’t any applications
  396. sending information to the Zipkin server so there is nothing to show.&lt;/p&gt;
  397.  
  398. &lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2016/06/Screen Shot 2016-06-22 at 5.18.33 PM.png&quot; alt=&quot;Zipkin&quot; /&gt;&lt;/p&gt;
  399.  
  400. &lt;p&gt;Lets enable our sample Sleuth app from above to send tracing information to our Zipkin
  401. server.  Open the POM file and add&lt;/p&gt;
  402.  
  403. &lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
  404.    &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.cloud&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  405.    &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-cloud-sleuth-zipkin&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
  406. &lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
  407. &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
  408.  
  409. &lt;p&gt;In addition we need to tell our application how often we want to sample our logs to
  410. be exported to Zipkin.  Since this is a demo, lets tell our app that we want to sample
  411. everything.  We can do this by creating a bean for the &lt;code class=&quot;highlighter-rouge&quot;&gt;AlwaysSampler&lt;/code&gt;.  Add the following
  412. code to your application class.&lt;/p&gt;
  413.  
  414. &lt;pre&gt;&lt;code class=&quot;language-Java&quot;&gt;@Bean
  415. public AlwaysSampler defaultSampler() {
  416.  return new AlwaysSampler();
  417. }
  418. &lt;/code&gt;&lt;/pre&gt;
  419.  
  420. &lt;p&gt;Once you add the sampler bean, restart the application.  If you now hit
  421. http://localhost:8080/callhome in your browser you should notice that the export
  422. flag in the sleuth logging has changed from &lt;code class=&quot;highlighter-rouge&quot;&gt;false&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;true&lt;/code&gt;.&lt;/p&gt;
  423.  
  424. &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;2016-06-20 09:03:44.939  INFO &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;slueth-sample,380c24fd1e5f89df,380c24fd1e5f89df,true] 19263 &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;nio-8080-exec-1] com.example.SleuthSampleApplication      : calling home
  425. 2016-06-20 09:03:44.966  INFO &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;slueth-sample,380c24fd1e5f89df,fc50a65582b7b845,true] 19263 &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;nio-8080-exec-2] com.example.SleuthSampleApplication      : you called home
  426. &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
  427.  
  428. &lt;p&gt;This indicates that the tracing information is being sent to your Zipkin server.
  429. If you open another browser tab and go to http://localhost:9411 you should see the Zipkin
  430. UI.  From here you can query Zipkin to find the tracing information you are looking for.
  431. Make sure you set the date range correctly and click &lt;code class=&quot;highlighter-rouge&quot;&gt;Find Taces&lt;/code&gt;.  You should see
  432. tracing information for the &lt;code class=&quot;highlighter-rouge&quot;&gt;/callhome&lt;/code&gt; endpoint returned.  Clicking on it will show
  433. you all the details collected from the Sleuth logs including timing information for the
  434. request.&lt;/p&gt;
  435.  
  436. &lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2016/06/Screen Shot 2016-06-22 at 5.23.08 PM.png&quot; alt=&quot;Zipkin UI&quot; /&gt;
  437. &lt;img src=&quot;/wp-content/uploads/2016/06/Screen Shot 2016-06-22 at 5.24.36 PM.png&quot; alt=&quot;Request Details&quot; /&gt;&lt;/p&gt;
  438.  
  439. &lt;p&gt;If you want to learn more about Spring Cloud Sleuth, I suggest you read through
  440. the &lt;a href=&quot;http://cloud.spring.io/spring-cloud-sleuth/spring-cloud-sleuth.html&quot;&gt;documentation&lt;/a&gt;.
  441. There is lots of good information in the docs and it contains a ton of additional
  442. information for more complicated use cases.&lt;/p&gt;
  443. </description>
  444. <pubDate>Thu, 07 Jul 2016 00:00:00 +0000</pubDate>
  445. <link>/cloud/spring%20cloud/spring/2016/07/07/spring-cloud-sleuth.html</link>
  446. <guid isPermaLink="true">/cloud/spring%20cloud/spring/2016/07/07/spring-cloud-sleuth.html</guid>
  447. </item>
  448. <item>
  449. <title>It Was Time For A Change</title>
  450. <description>&lt;p&gt;Change is good…well thats what they say anyways ;)  After working for IBM for 8+ years, I have left the only company I have every worked for and have joined Pivotal.  I owe a lot to IBM.  I joined right out of college and I learnt so much during the 8 years I was there.  I worked on a lot of great projects, and was presented with so many great opportunities that took my career in directions I would have never imagined.  By far the part of IBM that has impacted me the most both personally and professionally were the people.  There are SO many talented people at IBM, and I was lucky to work with many of them.  They taught me how to be an engineer, how to survive in a company with 400k people, and what it takes to progress professionally.&lt;/p&gt;
  451.  
  452. &lt;p&gt;&lt;img src=&quot;https://upload.wikimedia.org/wikipedia/commons/b/bd/GoPivotal_logo.png&quot; alt=&quot;Pivotal&quot; /&gt;
  453. &lt;img src=&quot;https://avatars3.githubusercontent.com/u/8216893?v=3&amp;amp;s=200&quot; alt=&quot;Spring Cloud&quot; /&gt;&lt;/p&gt;
  454.  
  455. &lt;p&gt;Recently however an opportunity came up for me to join Pivotal and work on the Spring Cloud team.  If you are a regular reader of this blog, you have probably noticed that I have been a big fan of Spring and Spring Cloud, so when the opportunity to work on those technologies presented itself I could not pass it up.&lt;/p&gt;
  456.  
  457. &lt;p&gt;I am truly thankful for my 8+ years at IBM, and I am very excited to now be starting a new chapter in my career with Pivotal.&lt;/p&gt;
  458. </description>
  459. <pubDate>Fri, 01 Jul 2016 00:00:00 +0000</pubDate>
  460. <link>/spring/pivotal/2016/07/01/it-was-time-for-a-change.html</link>
  461. <guid isPermaLink="true">/spring/pivotal/2016/07/01/it-was-time-for-a-change.html</guid>
  462. </item>
  463. <item>
  464. <title>Bluemix Cloud Connectors For IBM Graph DB and Object Storage Services</title>
  465. <description>&lt;p&gt;As I have blogged about in the &lt;a href=&quot;http://ryanjbaxter.com/2015/03/02/bluemix-java-developers-your-life-just-got-a-little-easier/&quot;&gt;past&lt;/a&gt;, the Bluemix Cloud Connectors project is
  466. a Java library you can use to easily access service credentials and obtain high-level
  467. Java objects to work with various services in Bluemix.  Today I updated the project
  468. to add support for two new services in Bluemix, the &lt;a href=&quot;https://new-console.ng.bluemix.net/catalog/services/ibm-graph/&quot;&gt;IBM Graph DB service&lt;/a&gt;, and
  469. the &lt;a href=&quot;https://new-console.ng.bluemix.net/catalog/services/object-storage/&quot;&gt;Object Storage service&lt;/a&gt;.&lt;/p&gt;
  470.  
  471. &lt;p&gt;Right now, only the snapshot builds contain support for these services.  I will
  472. be pushing a build to the central Maven repository once I am confident the new
  473. code is stable.  See the &lt;a href=&quot;https://github.com/IBM-Bluemix/bluemix-cloud-connectors/blob/master/README.md#snapshot-builds&quot;&gt;README&lt;/a&gt; in the Bluemix Cloud Connectors project for information
  474. on where to find the snapshot builds.&lt;/p&gt;
  475.  
  476. &lt;p&gt;There are also a couple of differences in the way these services work compared to
  477. some of the other services in the project.  First, the IBM Graph DB service does
  478. not have a Java SDK so the Bluemix Cloud Connectors project cannot provide you with
  479. a high level Java object to work with in your code.  You can use the cloud connectors
  480. project to &lt;a href=&quot;https://github.com/IBM-Bluemix/bluemix-cloud-connectors#accessing-the-service-credentials-in-a-non-spring-app&quot;&gt;get the service credentials&lt;/a&gt; for the service so you can then make the
  481. necessary REST calls from your app.  Secondly, the Object Storage service requires
  482. additional information besides the normal username, password, and API URL typical
  483. services use.  When using the Object Storage service you also need the domain name
  484. and project for your service instance.  This does not pose much of an issue when running
  485. your app in Bluemix, however there is a “gotcha” when it comes to running your app
  486. locally.  In order to provide this information in a URL format for the local config, the
  487. Object Storage support expects it to be in the path parameters of the URL.  For more
  488. information about supporting these two new services please see the &lt;a href=&quot;https://github.com/IBM-Bluemix/bluemix-cloud-connectors/blob/master/README.md#supported-services&quot;&gt;README&lt;/a&gt;.&lt;/p&gt;
  489.  
  490. &lt;p&gt;As always feedback is welcome, feel free to leave comments below, or create
  491. &lt;a href=&quot;https://github.com/IBM-Bluemix/bluemix-cloud-connectors/issues&quot;&gt;issues&lt;/a&gt; in the project on GitHub.&lt;/p&gt;
  492. </description>
  493. <pubDate>Thu, 02 Jun 2016 00:00:00 +0000</pubDate>
  494. <link>/cloud/bluemix/spring/2016/06/02/new-cloud-connectors-graphdb-object-storage.html</link>
  495. <guid isPermaLink="true">/cloud/bluemix/spring/2016/06/02/new-cloud-connectors-graphdb-object-storage.html</guid>
  496. </item>
  497. <item>
  498. <title>Docker Compose and IBM Containers</title>
  499. <description>&lt;p&gt;Recently my colleague Chris Rosen published &lt;a href=&quot;https://developer.ibm.com/bluemix/2016/03/24/new-deployment-architecture-for-containers/?linkId=22660520&quot;&gt;this blog post&lt;/a&gt; about some new functionality
  500. coming to the IBM Containers service in Bluemix.  One of the new features that is
  501. now available is native &lt;a href=&quot;https://console.ng.bluemix.net/docs/containers/container_creating_ov.html#container_compose_ov&quot;&gt;Docker Compose support&lt;/a&gt;.  Docker Compose is a great tool to use if your application is split up into multiple containers.
  502. It takes care of a lot of the orchestration and configuration needed to be done between
  503. the various containers so that they can work seamlessly together.  You can read more about Docker Compose in the Docker
  504. &lt;a href=&quot;https://docs.docker.com/compose/&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
  505.  
  506. &lt;p&gt;As a demonstration of how to use Docker Compose with Bluemix I have gone ahead
  507. and added some &lt;a href=&quot;https://github.com/IBM-Bluemix/bluechatter#deploy-to-bluemix-with-docker-compose&quot;&gt;new instructions&lt;/a&gt;
  508. to the BlueChatter sample app README on how to deploy BlueChatter and the
  509. required Redis service using Docker Compose.  In just a few steps you can have
  510. both the BlueChatter web app and the Redis service deployed to Bluemix in their
  511. own containers.  Below is a video demonstrating how easy it is to do this, enjoy!&lt;/p&gt;
  512.  
  513. &lt;iframe width=&quot;1024&quot; height=&quot;768&quot; src=&quot;https://www.youtube.com/embed/igY-rA40yfY&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
  514. </description>
  515. <pubDate>Wed, 06 Apr 2016 00:00:00 +0000</pubDate>
  516. <link>/cloud/bluemix/docker/2016/04/06/bluemix-docker-compose.html</link>
  517. <guid isPermaLink="true">/cloud/bluemix/docker/2016/04/06/bluemix-docker-compose.html</guid>
  518. </item>
  519. <item>
  520. <title>Running OpenWhisk Actions From Node-RED</title>
  521. <description>&lt;p&gt;At IBM InterConnect 2016, IBM announced a new experimental compute runtime for Bluemix
  522. called &lt;a href=&quot;https://new-console.ng.bluemix.net/openwhisk/?cm_sp=bluemixblog-_-content-_-cta&amp;amp;cm_mc_uid=99069416036614567943703&amp;amp;cm_mc_sid_50200000=1458847907&quot;&gt;OpenWhisk&lt;/a&gt;.  What is OpenWhisk?&lt;/p&gt;
  523.  
  524. &lt;blockquote&gt;
  525.  &lt;p&gt;OpenWhisk is an event-driven compute platform that executes application logic in response to events or through direct
  526. invocations–from web/mobile apps or other endpoints.&lt;/p&gt;
  527. &lt;/blockquote&gt;
  528.  
  529. &lt;p&gt;If you are familiar with Amazon’s Lambda feature, it is very similar.  If you
  530. want to learn more about OpenWhisk there are number of resources to help you get started.  First is the &lt;a href=&quot;https://new-console.ng.bluemix.net/docs/openwhisk/index.html&quot;&gt;documentation on Bluemix&lt;/a&gt;.  The documentation provides a great explanation of the technology as well as
  531. some examples to get you started.  You can also read this
  532. &lt;a href=&quot;https://developer.ibm.com/bluemix/2016/02/25/bluemix-openwhisk-overview/&quot;&gt;blog post&lt;/a&gt;
  533. on the Bluemix developerWorks site for some high level information.  In addition, OpenWhisk
  534. is actually an open source technology, so the &lt;a href=&quot;https://github.com/openwhisk/openwhisk&quot;&gt;GitHub repo&lt;/a&gt;
  535. also has a bunch of useful information.&lt;/p&gt;
  536.  
  537. &lt;p&gt;At the core of OpenWhisk is this concept of &lt;a href=&quot;https://new-console.ng.bluemix.net/docs/openwhisk/openwhisk_actions.html&quot;&gt;actions&lt;/a&gt;.  Actions are the objects you
  538. run in response to events.  There are a number of ways to run them.  For example,
  539. they can be run via the &lt;a href=&quot;https://console.ng.bluemix.net/openwhisk/cli&quot;&gt;OpenWhisk CLI&lt;/a&gt;.&lt;/p&gt;
  540.  
  541. &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wsk action invoke hello-world &lt;span class=&quot;nt&quot;&gt;--blocking&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--result&lt;/span&gt;
  542. &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  543.    &lt;span class=&quot;s2&quot;&gt;&quot;payload&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;Hello, World!&quot;&lt;/span&gt;
  544. &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  545. &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
  546.  
  547. &lt;p&gt;There is also a &lt;a href=&quot;https://new-console.ng.bluemix.net/docs/openwhisk/openwhisk_mobile_sdk.html&quot;&gt;Swift API&lt;/a&gt;
  548. to run OpenWhisk actions.&lt;/p&gt;
  549.  
  550. &lt;pre&gt;&lt;code class=&quot;language-Swift&quot;&gt;// In this example, we are invoking an action to print a message to the OpenWhisk Console
  551. var params = Dictionary&amp;lt;String, String&amp;gt;()
  552. params[&quot;payload&quot;] = &quot;Hi from mobile&quot;
  553.  
  554. do {
  555.    try whisk.invokeAction(name: &quot;helloConsole&quot;, package: &quot;mypackage&quot;, namespace: &quot;mynamespace&quot;, parameters: params, hasResult: false, callback: {(reply, error) -&amp;gt; Void in
  556.        if let error = error {
  557.            //do something
  558.            print(&quot;Error invoking action \(error.localizedDescription)&quot;)
  559.        } else {
  560.            print(&quot;Action invoked!&quot;)
  561.        }
  562.  
  563.    })
  564. } catch {
  565.    print(&quot;Error \(error)&quot;)
  566. }
  567. &lt;/code&gt;&lt;/pre&gt;
  568.  
  569. &lt;p&gt;There
  570. is also a &lt;a href=&quot;https://new-console.ng.bluemix.net/apidocs/98&quot;&gt;REST API&lt;/a&gt; you can use which
  571. can be used from any runtime you might be using.  As I continue to explore OpenWhisk,
  572. I wanted to experiment with the REST API and decided an easy way to do this was with
  573. using &lt;a href=&quot;http://nodered.org&quot;&gt;Node-RED&lt;/a&gt;.  I have
  574. &lt;a href=&quot;http://ryanjbaxter.com/2015/01/13/sample-node-red-flow-using-websockets/&quot;&gt;already discussed&lt;/a&gt;
  575. how easy it is to invoke REST APIs from Node-RED,
  576. so using the OpenWhisk REST APIs with Node-RED should be super simple, and it was!&lt;/p&gt;
  577.  
  578. &lt;p&gt;Once you have some actions created (you can try this out with the samples from
  579. the documentation) you can invoke those actions using the &lt;a href=&quot;https://new-console.ng.bluemix.net/apidocs/98#invokeactionPOST&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;/invokeAction&lt;/code&gt; endpoint&lt;/a&gt;.
  580. Here is an example of the URL you would make the POST request to in order to do this.&lt;/p&gt;
  581.  
  582. &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;https://openwhisk.ng.bluemix.net/api/v1/namespaces/ET_Demo_org_demo/actions/language-profile?blocking=true&lt;/code&gt;&lt;/p&gt;
  583.  
  584. &lt;p&gt;To invoke your own action you will need to change the &lt;code class=&quot;highlighter-rouge&quot;&gt;namespaces&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;actions&lt;/code&gt; path parameters in the above URL.  Use your namespace and your action name instead.&lt;/p&gt;
  585.  
  586. &lt;p&gt;If your action takes parameters, than the POST body would be a JSON object containing
  587. those parameters.  For example&lt;/p&gt;
  588.  
  589. &lt;pre&gt;&lt;code class=&quot;language-JSON&quot;&gt;{
  590.  &quot;twitter&quot;: &quot;ryajbaxter&quot;,
  591.  &quot;github&quot;: &quot;ryanjbaxter&quot;
  592. }
  593. &lt;/code&gt;&lt;/pre&gt;
  594.  
  595. &lt;p&gt;Finally you will need to authenticate with the OpenWhisk service in order to make the request.
  596. Unfortunately, right now OpenWhisk on Bluemix does not have the concept of API Keys
  597. and Tokens for use by applications so you need to use your own credentials.  To retrieve your Bluemix OpenWhisk credentials
  598. you can run a OpenWhisk CLI command.&lt;/p&gt;
  599.  
  600. &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wsk property get &lt;span class=&quot;nt&quot;&gt;--auth&lt;/span&gt;
  601. &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
  602.  
  603. &lt;p&gt;If you want to get a base 64 encoded version of your credentials suitable to include
  604. in an HTTP request you can run&lt;/p&gt;
  605.  
  606. &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wsk property get &lt;span class=&quot;nt&quot;&gt;--auth&lt;/span&gt; | awk &lt;span class=&quot;s1&quot;&gt;'{printf(&quot;%s&quot;, $3)}'&lt;/span&gt; | base64
  607. &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
  608.  
  609. &lt;p&gt;The output of the above command can be included in the &lt;code class=&quot;highlighter-rouge&quot;&gt;Authorization&lt;/code&gt; header in your
  610. HTTP request.&lt;/p&gt;
  611.  
  612. &lt;p&gt;Putting this all together you could invoke this action using the REST API by issuing
  613. this cURL command&lt;/p&gt;
  614.  
  615. &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-X&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;GET&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://openwhisk.ng.bluemix.net/api/v1/namespaces/ET_Demo_org_demo/actions/language-profile?blocking=true&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  616. &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Authorization: Basic &amp;lt;base64 encoded credentials&amp;gt;&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  617. &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Type: application/json&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  618. &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;{&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;twitter&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ryajbaxter&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;github&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ryanjbaxter&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;}&quot;&lt;/span&gt;
  619. &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
  620.  
  621. &lt;p&gt;OK, so what about Node-RED?  Well now that we know how to invoke an action using
  622. the OpenWhisk REST API we can easily invoke that action via a Node-RED flow as well.
  623. The http request node in Node-RED makes calling any HTTP endpoint extremely easy.
  624. Lets take a look at a simple flow that replicates the cURL command above.&lt;/p&gt;
  625.  
  626. &lt;p&gt;In your Node-RED instance drag and drop and http request node from the function section
  627. onto your sheet.  Once you have the node on your sheet double click it to open the configuration
  628. properties.  In the Method drop down select POST.  In the URL field enter the URL to invoke
  629. your OpenWhisk task.  Once you have done that you can click OK to close the configuration
  630. dialog.&lt;/p&gt;
  631.  
  632. &lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2016/03/Screen Shot 2016-03-25 at 12.31.09 PM.png&quot; alt=&quot;HTTP Request&quot; /&gt;&lt;/p&gt;
  633.  
  634. &lt;p&gt;You will also need to set the &lt;code class=&quot;highlighter-rouge&quot;&gt;Authorization&lt;/code&gt; header on the request the http request node
  635. makes.  The documentation specifies that you can set headers on the request by setting
  636. &lt;code class=&quot;highlighter-rouge&quot;&gt;msg.headers&lt;/code&gt; on the incoming msg object.  To set the &lt;code class=&quot;highlighter-rouge&quot;&gt;msg.headers&lt;/code&gt; property we can
  637. use a function node.  Drag and drop a function node from the function section to your sheet.
  638. Double click the function node to open the editor and add the following code.&lt;/p&gt;
  639.  
  640. &lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;headers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  641.      &lt;span class=&quot;s2&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Basic &amp;lt;base 64 encoded credentials&amp;gt;&quot;&lt;/span&gt;  
  642.    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  643. &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  644. &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
  645.  
  646. &lt;p&gt;Just make sure you replace &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;base64 encoed credentials&amp;gt;&lt;/code&gt; with the result of running
  647. &lt;code class=&quot;highlighter-rouge&quot;&gt;$ wsk property get --auth | awk '{printf(&quot;%s&quot;, $3)}' | base64&lt;/code&gt;.&lt;/p&gt;
  648.  
  649. &lt;p&gt;If you need to pass parameters to your action you will need to provide a POST body to
  650. the http request node.  The documentation for the http request node specifies that this can be done
  651. by setting the &lt;code class=&quot;highlighter-rouge&quot;&gt;payload&lt;/code&gt; property on the &lt;code class=&quot;highlighter-rouge&quot;&gt;msg&lt;/code&gt; object that is passed to the node.  To
  652. set the &lt;code class=&quot;highlighter-rouge&quot;&gt;payload&lt;/code&gt; property we can add some additional code to our function node.
  653. In addition, since we are passing a POST body we need to set the &lt;code class=&quot;highlighter-rouge&quot;&gt;Content-Type&lt;/code&gt; header to
  654. &lt;code class=&quot;highlighter-rouge&quot;&gt;application/json&lt;/code&gt;.  If you don’t
  655. need to pass any parameters to your action than you can skip this step.&lt;/p&gt;
  656.  
  657. &lt;p&gt;Double click the function node to open the editor.  You can add your parameters simply by
  658. setting &lt;code class=&quot;highlighter-rouge&quot;&gt;msg.payload&lt;/code&gt;, for example&lt;/p&gt;
  659.  
  660. &lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;headers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  661.  &lt;span class=&quot;s2&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Basic &amp;lt;base 64 encoded credentials&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  662.  &lt;span class=&quot;s2&quot;&gt;&quot;Content-Type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;application/json&quot;&lt;/span&gt;  
  663. &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  664. &lt;span class=&quot;nx&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;payload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  665.  &lt;span class=&quot;s2&quot;&gt;&quot;twitter&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ryanjbaxter&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  666.  &lt;span class=&quot;s2&quot;&gt;&quot;github&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ryanjbaxter&quot;&lt;/span&gt;
  667. &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  668. &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  669. &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
  670.  
  671. &lt;p&gt;Connect the function node to the http request node.&lt;/p&gt;
  672.  
  673. &lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2016/03/Screen Shot 2016-03-25 at 11.51.54 AM.png&quot; alt=&quot;Function and HTTP Request&quot; /&gt;&lt;/p&gt;
  674.  
  675. &lt;p&gt;We will want to see
  676. the output of our HTTP request, so drag and drop a debug node to your sheet and connect
  677. the http request node to the debug node.&lt;/p&gt;
  678.  
  679. &lt;p&gt;Finally, we need a way of kicking off the flow, so drag and drop an inject node
  680. to the sheet and connect it to the function node.  If you deploy this flow and
  681. click the inject button it should invoke the action in OpenWhisk on Bluemix!  That’s
  682. it, four nodes and you are able to invoke OpenWhisk actions from Node-RED.&lt;/p&gt;
  683.  
  684. &lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2016/03/Screen Shot 2016-03-25 at 12.02.02 PM.png&quot; alt=&quot;Complete Flow&quot; /&gt;&lt;/p&gt;
  685.  
  686. &lt;p&gt;You can easily start to build upon this flow to take advantage of other features in
  687. Node-RED as well.  For example, you can invoke an action as the result of making
  688. an HTTP request to your own endpoint you setup in Node-RED.  Or you can invoke an action
  689. as the result of an event published to an MQTT topic you are subscribed to.&lt;/p&gt;
  690.  
  691. &lt;h3 id=&quot;update&quot;&gt;Update&lt;/h3&gt;
  692.  
  693. &lt;p&gt;After I initially posted this blog post someone on Twitter pointed out to me that there were
  694. actually &lt;a href=&quot;http://flows.nodered.org/node/node-red-node-openwhisk&quot;&gt;nodes for Node-RED&lt;/a&gt;
  695. for running OpenWhisk actions and tasks!&lt;/p&gt;
  696.  
  697. &lt;blockquote class=&quot;twitter-tweet&quot; data-partner=&quot;tweetdeck&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/ryanjbaxter&quot;&gt;@ryanjbaxter&lt;/a&gt; Nice post. And/or you could use the Openwhisk node directly - &lt;a href=&quot;https://t.co/aB8fMSyGbK&quot;&gt;https://t.co/aB8fMSyGbK&lt;/a&gt; &lt;a href=&quot;https://twitter.com/NodeRED&quot;&gt;@NodeRED&lt;/a&gt;&lt;/p&gt;&amp;mdash; Dave CJ (@ceejay) &lt;a href=&quot;https://twitter.com/ceejay/status/714495301638295552&quot;&gt;March 28, 2016&lt;/a&gt;&lt;/blockquote&gt;
  698. &lt;script async=&quot;&quot; src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
  699.  
  700. &lt;p&gt;After a little investigation I found out that these nodes were already available in
  701. the &lt;a href=&quot;https://console.ng.bluemix.net/catalog/starters/node-red-starter/&quot;&gt;Node-RED community boilerplate&lt;/a&gt;
  702. on Bluemix!  Under the covers I am sure they are probably using the REST APIs I mention
  703. in the post below but they encapsulate everything.&lt;/p&gt;
  704.  
  705. &lt;p&gt;As far as using them, the only tricky part is getting the auth token for the configuration
  706. node.  To do that just run &lt;code class=&quot;highlighter-rouge&quot;&gt;wsk property get --auth&lt;/code&gt;.  Copy the resulting token into
  707. the OpenWhisk configuration node and you should be all set.&lt;/p&gt;
  708.  
  709. &lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2016/03/Screen Shot 2016-03-28 at 5.04.57 PM.png&quot; alt=&quot;OpenWhisk Config&quot; /&gt;&lt;/p&gt;
  710. </description>
  711. <pubDate>Thu, 24 Mar 2016 00:00:00 +0000</pubDate>
  712. <link>/cloud/bluemix/2016/03/24/running-whisk-actions-from-node-red.html</link>
  713. <guid isPermaLink="true">/cloud/bluemix/2016/03/24/running-whisk-actions-from-node-red.html</guid>
  714. </item>
  715. </channel>
  716. </rss>
  717.  
Copyright © 2002-9 Sam Ruby, Mark Pilgrim, Joseph Walton, and Phil Ringnalda