{"id":93453,"date":"2019-06-24T09:21:11","date_gmt":"2019-06-24T06:21:11","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=93453"},"modified":"2019-07-01T12:33:19","modified_gmt":"2019-07-01T09:33:19","slug":"java-microservices-spring-boot-spring-cloud","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2019\/06\/java-microservices-spring-boot-spring-cloud.html","title":{"rendered":"Java Microservices with Spring Boot and Spring Cloud"},"content":{"rendered":"<p><span style=\"font-size: 20px;\"><b>Friends don\u2019t let friends write user auth. Tired of managing your own users?<\/b>  <a href=\"https:\/\/developer.okta.com\/signup\/?utm_campaign=text_website_all_multiple_dev_dev_java-microservices-spring-boot-spring-cloud_null&amp;utm_source=jcg&amp;utm_medium=cpc\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">Try Okta\u2019s API and Java SDKs today. Authenticate, manage, and secure users in any application within minutes.<\/a><\/span><\/p>\n<p>Java is a great language to use when developing a microservice architecture. In fact, some of the biggest names in our industry use it. Have you ever heard of Netflix, Amazon, or Google? What about eBay, Twitter, and LinkedIn? Yes, major companies handling incredible traffic are doing it with Java.<\/p>\n<p>Implementing a microservices architecture in Java isn\u2019t for everyone. For that matter, implementing microservices, in general, isn\u2019t often needed. Most companies do it to scale their people, not their systems. If you\u2019re going to scale your people, hiring Java developers is one of the best ways to do it. After all, there are more developers fluent in Java than most other languages &#8211; though JavaScript seems to be catching up quickly!<\/p>\n<p>The Java ecosystem has some well-established patterns for developing microservice architectures. If you\u2019re familiar with Spring, you\u2019ll feel right at home developing with Spring Boot and Spring Cloud. Since that\u2019s one of the quickest ways to get started, I figured I\u2019d walk you through a quick tutorial.<\/p>\n<h2 class=\"wp-block-heading\" id=\"create-java-microservices-with-spring-cloud-and-spring-boot\">Create Java Microservices with Spring Cloud and Spring Boot<\/h2>\n<p>In most of my tutorials, I show you how to build everything from scratch. Today I\u2019d like to take a different approach and step through a pre-built example with you. Hopefully, this will be a bit shorter and easier to understand.<\/p>\n<p>You can start by cloning the&nbsp;<a href=\"https:\/\/github.com\/oktadeveloper\/java-microservices-examples\">@oktadeveloper\/java-microservices-examples<\/a>&nbsp;repository.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">git clone https:\/\/github.com\/oktadeveloper\/java-microservices-examples.git\ncd java-microservices-examples\/spring-boot+cloud\n<\/pre>\n<p>In the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">spring-boot+cloud<\/code>&nbsp;directory, there are three projects:<\/p>\n<ul class=\"wp-block-list\">\n<li><strong>discovery-service<\/strong>: a Netflix Eureka server, used for service discovery.<\/li>\n<li><strong>car-service<\/strong>: a simple Car Service that uses Spring Data REST to serve up a REST API of cars.<\/li>\n<li><strong>api-gateway<\/strong>: an API gateway that has a&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/cool-cars<\/code>&nbsp;endpoint that talks to the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">car-service<\/code>&nbsp;and filters out cars that aren\u2019t cool (in my opinion, of course).<\/li>\n<\/ul>\n<p>I created all of these applications using&nbsp;<a href=\"https:\/\/start.spring.io\/\">start.spring.io\u2019s<\/a>&nbsp;REST API and&nbsp;<a href=\"https:\/\/httpie.org\/\">HTTPie<\/a>.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">http https:\/\/start.spring.io\/starter.zip javaVersion==11 \\\n  artifactId==discovery-service name==eureka-service \\\n  dependencies==cloud-eureka-server baseDir==discovery-service | tar -xzvf -\n\nhttp https:\/\/start.spring.io\/starter.zip \\\n  artifactId==car-service name==car-service baseDir==car-service \\\n  dependencies==actuator,cloud-eureka,data-jpa,h2,data-rest,web,devtools,lombok | tar -xzvf -\n\nhttp https:\/\/start.spring.io\/starter.zip \\\n  artifactId==api-gateway name==api-gateway baseDir==api-gateway \\\n  dependencies==cloud-eureka,cloud-feign,data-rest,web,cloud-hystrix,lombok | tar -xzvf -\n<\/pre>\n<h3 class=\"wp-block-heading\" id=\"spring-microservices-with-java-11\">Spring Microservices with Java 11+<\/h3>\n<p>To make the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">discovery-service<\/code>&nbsp;run on Java 11, I had to add a dependency on JAXB<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:xml\">&lt;dependency&gt;\n    &lt;groupId&gt;org.glassfish.jaxb&lt;\/groupId&gt;\n    &lt;artifactId&gt;jaxb-runtime&lt;\/artifactId&gt;\n&lt;\/dependency&gt;\n<\/pre>\n<p>The other two applications worked fine out-of-the-box on Java 11 with no changes in dependencies.<\/p>\n<h2 class=\"wp-block-heading\" id=\"java-service-discovery-with-netflix-eureka\">Java Service Discovery with Netflix Eureka<\/h2>\n<p>The&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">discovery-service<\/code>&nbsp;is configured the same as you would most Eureka servers. It as an&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@EnableEurekaServer<\/code>&nbsp;annotation on its main class and properties that set its port and turn off discovery.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">server.port=8761\neureka.client.register-with-eureka=false\n<\/pre>\n<p>The&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">car-service<\/code>&nbsp;and&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">api-gateway<\/code>&nbsp;projects are configured in a similar fashion. Both have a unique name defined and&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">car-service<\/code>&nbsp;is configured to run on port&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">8090<\/code>&nbsp;so it doesn\u2019t conflict with&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">8080<\/code>.<br \/><em>car-service\/src\/main\/resources\/application.properties<\/em><\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">server.port=8090\nspring.application.name=car-service\n<\/pre>\n<p><em>api-gateway\/src\/main\/resources\/application.properties<\/em><\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">spring.application.name=api-gateway<\/pre>\n<p>The main class in both projects is annotated with&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@EnableDiscoveryClient<\/code>.<\/p>\n<h2 class=\"wp-block-heading\" id=\"build-a-java-microservice-with-spring-data-rest\">Build a Java Microservice with Spring Data REST<\/h2>\n<p>The&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">car-service<\/code>&nbsp;provides a REST API that lets you CRUD (Create, Read, Update, and Delete) cars. It creates a default set of cars when the application loads using an&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">ApplicationRunner<\/code>&nbsp;bean.<br \/><em>car-service\/src\/main\/java\/com\/example\/carservice\/CarServiceApplication.java<\/em><\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.example.carservice;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.NonNull;\nimport org.springframework.boot.ApplicationRunner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.data.rest.core.annotation.RepositoryRestResource;\n\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\nimport java.util.stream.Stream;\n\n@EnableDiscoveryClient\n@SpringBootApplication\npublic class CarServiceApplication {\n\n    public static void main(String[] args) {\n        SpringApplication.run(CarServiceApplication.class, args);\n    }\n\n    @Bean\n    ApplicationRunner init(CarRepository repository) {\n        return args -&gt; {\n            Stream.of(\"Ferrari\", \"Jaguar\", \"Porsche\", \"Lamborghini\", \"Bugatti\",\n                    \"AMC Gremlin\", \"Triumph Stag\", \"Ford Pinto\", \"Yugo GV\").forEach(name -&gt; {\n                repository.save(new Car(name));\n            });\n            repository.findAll().forEach(System.out::println);\n        };\n    }\n}\n\n@Data\n@NoArgsConstructor\n@Entity\nclass Car {\n\n    public Car(String name) {\n        this.name = name;\n    }\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    @NonNull\n    private String name;\n}\n\n@RepositoryRestResource\ninterface CarRepository extends JpaRepository&lt;Car, Long&gt; {\n}\n<\/pre>\n<h3 class=\"wp-block-heading\" id=\"spring-cloud-feign-and-hystrix-in-an-api-gateway\">Spring Cloud + Feign and Hystrix in an API Gateway<\/h3>\n<p><a href=\"https:\/\/github.com\/OpenFeign\/feign\">Feign<\/a>&nbsp;makes writing Java HTTP clients easier. Spring Cloud makes it possible to create a Feign client with just a few lines of code.&nbsp;<a href=\"https:\/\/github.com\/Netflix\/Hystrix\">Hystrix<\/a>&nbsp;makes it possible to add failover capabilities to your Feign clients so they\u2019re more resilient.<\/p>\n<p>The&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">api-gateway<\/code>&nbsp;uses Feign and Hystrix to talk to the downstream&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">car-service<\/code>&nbsp;and failover to a&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">fallback()<\/code>&nbsp;method if it\u2019s unavailable. It also exposes a&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/cool-cars<\/code>&nbsp;endpoint that filters out cars you might not want to own.<br \/><em>api-gateway\/src\/main\/java\/com\/example\/apigateway\/ApiGatewayApplication.java<\/em><\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.example.apigateway;\n\nimport com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;\nimport lombok.Data;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.netflix.zuul.EnableZuulProxy;\nimport org.springframework.cloud.openfeign.EnableFeignClients;\nimport org.springframework.cloud.openfeign.FeignClient;\nimport org.springframework.hateoas.Resources;\nimport org.springframework.web.bind.annotation.CrossOrigin;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.stream.Collectors;\n\n@EnableFeignClients\n@EnableCircuitBreaker\n@EnableDiscoveryClient\n@EnableZuulProxy\n@SpringBootApplication\npublic class ApiGatewayApplication {\n\n    public static void main(String[] args) {\n        SpringApplication.run(ApiGatewayApplication.class, args);\n    }\n}\n\n@Data\nclass Car {\n    private String name;\n}\n\n@FeignClient(\"car-service\")\ninterface CarClient {\n\n    @GetMapping(\"\/cars\")\n    @CrossOrigin\n    Resources&lt;Car&gt; readCars();\n}\n\n@RestController\nclass CoolCarController {\n\n    private final CarClient carClient;\n\n    public CoolCarController(CarClient carClient) {\n        this.carClient = carClient;\n    }\n\n    private Collection&lt;Car&gt; fallback() {\n        return new ArrayList&lt;&gt;();\n    }\n\n    @GetMapping(\"\/cool-cars\")\n    @CrossOrigin\n    @HystrixCommand(fallbackMethod = \"fallback\")\n    public Collection&lt;Car&gt; goodCars() {\n        return carClient.readCars()\n                .getContent()\n                .stream()\n                .filter(this::isCool)\n                .collect(Collectors.toList());\n    }\n\n    private boolean isCool(Car car) {\n        return !car.getName().equals(\"AMC Gremlin\") &amp;&amp;\n                !car.getName().equals(\"Triumph Stag\") &amp;&amp;\n                !car.getName().equals(\"Ford Pinto\") &amp;&amp;\n                !car.getName().equals(\"Yugo GV\");\n    }\n}\n<\/pre>\n<h2 class=\"wp-block-heading\" id=\"run-a-java-microservices-architecture\">Run a Java Microservices Architecture<\/h2>\n<p>If you run all of these services with&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.\/mvnw<\/code>&nbsp;in separate terminal windows, you can navigate to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\"><a class=\"bare\" href=\"http:\/\/localhost:8761\/\">http:\/\/localhost:8761<\/a><\/code>&nbsp;and see they\u2019ve registered with Eureka.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/eureka-server-1024x702.png\" alt=\"Java Microservices\" class=\"wp-image-93456\" width=\"768\" height=\"527\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/eureka-server-1024x702.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/eureka-server-300x206.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/eureka-server-768x527.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/eureka-server.png 1600w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/><\/figure>\n<\/div>\n<p>If you navigate to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\"><a class=\"bare\" href=\"http:\/\/localhost:8080\/cool-bars\">http:\/\/localhost:8080\/cool-bars<\/a><\/code>&nbsp;in your browser, you\u2019ll be redirected to Okta. What the?<\/p>\n<h2 class=\"wp-block-heading\" id=\"secure-java-microservices-with-oauth-2-0-and-oidc\">Secure Java Microservices with OAuth 2.0 and OIDC<\/h2>\n<p>I\u2019ve already configured security in this microservices architecture using OAuth 2.0 and OIDC. What\u2019s the difference between the two? OIDC is an extension to OAuth 2.0 that provides identity. It also provides discovery so all the different OAuth 2.0 endpoints can be discovered from a single URL (called an&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">issuer<\/code>).<\/p>\n<p>How did I configure security for all these microservices? I\u2019m glad you asked!<\/p>\n<p>I added Okta\u2019s Spring Boot starter to the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">pom.xml<\/code>&nbsp;in&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">api-gateway<\/code>&nbsp;and&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">car-service<\/code>:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:xml\">&lt;dependency&gt;\n    &lt;groupId&gt;com.okta.spring&lt;\/groupId&gt;\n    &lt;artifactId&gt;okta-spring-boot-starter&lt;\/artifactId&gt;\n    &lt;version&gt;1.2.0&lt;\/version&gt;\n&lt;\/dependency&gt;\n<\/pre>\n<p>Then I created a new OIDC app in Okta, configured with authorization code flow. You\u2019ll need to complete the following steps if you want to see everything in action.<\/p>\n<h3 class=\"wp-block-heading\" id=\"create-a-web-application-in-okta\">Create a Web Application in Okta<\/h3>\n<p>Log in to your Okta Developer account (or&nbsp;<a href=\"https:\/\/developer.okta.com\/signup\/?utm_campaign=text_website_all_multiple_dev_dev_java-microservices-spring-boot-spring-cloud_null&amp;utm_source=jcg&amp;utm_medium=cpc\">sign up<\/a>&nbsp;if you don\u2019t have an account).<\/p>\n<ol class=\"wp-block-list\">\n<li>From the&nbsp;<strong>Applications<\/strong>&nbsp;page, choose&nbsp;<strong>Add Application<\/strong>.<\/li>\n<li>On the Create New Application page, select&nbsp;<strong>Web<\/strong>.<\/li>\n<li>Give your app a memorable name, add&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\"><a class=\"bare\" href=\"http:\/\/localhost:8080\/login\/oauth2\/code\/okta\">http:\/\/localhost:8080\/login\/oauth2\/code\/okta<\/a><\/code>&nbsp;as a Login redirect URI, select&nbsp;<strong>Refresh Token<\/strong>&nbsp;(in addition to&nbsp;<strong>Authorization Code<\/strong>), and click&nbsp;<strong>Done<\/strong>.<\/li>\n<\/ol>\n<p>Copy the issuer (found under&nbsp;<strong>API<\/strong>&nbsp;&gt;&nbsp;<strong>Authorization Servers<\/strong>), client ID, and client secret into&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">application.properties<\/code>&nbsp;for both projects.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">okta.oauth2.issuer=$issuer\nokta.oauth2.client-id=$clientId\nokta.oauth2.client-secret=$clientSecret\n<\/pre>\n<p>The Java code in the section below already exists, but I figured I\u2019d explain it so you know what\u2019s going on.<\/p>\n<h3 class=\"wp-block-heading\" id=\"configure-spring-security-for-oauth-2-0-login-and-resource-server\">Configure Spring Security for OAuth 2.0 Login and Resource Server<\/h3>\n<p>In&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">ApiGatewayApplication.java<\/code>, I added Spring Security configuration to enable OAuth 2.0 login and enable the gateway as a resource server.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">@Configuration\nstatic class OktaOAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {\n\n    @Override\n    protected void configure(HttpSecurity http) throws Exception {\n        \/\/ @formatter:off\n        http\n            .authorizeRequests().anyRequest().authenticated()\n                .and()\n            .oauth2Login()\n                .and()\n            .oauth2ResourceServer().jwt();\n        \/\/ @formatter:on\n    }\n}\n<\/pre>\n<p>The resource server configuration is not used in this example, but I added in case you wanted to hook up a mobile app or SPA to this gateway. If you\u2019re using a SPA, you\u2019ll also need to add a bean to configure CORS.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">@Bean\npublic FilterRegistrationBean&lt;CorsFilter&gt; simpleCorsFilter() {\n    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();\n    CorsConfiguration config = new CorsConfiguration();\n    config.setAllowCredentials(true);\n    config.setAllowedOrigins(Collections.singletonList(\"*\"));\n    config.setAllowedMethods(Collections.singletonList(\"*\"));\n    config.setAllowedHeaders(Collections.singletonList(\"*\"));\n    source.registerCorsConfiguration(\"\/**\", config);\n    FilterRegistrationBean&lt;CorsFilter&gt; bean = new FilterRegistrationBean&lt;&gt;(new CorsFilter(source));\n    bean.setOrder(Ordered.HIGHEST_PRECEDENCE);\n    return bean;\n}\n<\/pre>\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p> If you do use a CORS filter like this one, I recommend you change the origins, methods, and headers to be more specific, increasing security. <\/p>\n<\/blockquote>\n<p>The&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">CarServiceApplication.java<\/code>&nbsp;is only configured as a resource server since it\u2019s not expected to be accessed directly.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">@Configuration\nstatic class OktaOAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {\n\n    @Override\n    protected void configure(HttpSecurity http) throws Exception {\n        \/\/ @formatter:off\n        http\n            .authorizeRequests().anyRequest().authenticated()\n                .and()\n            .oauth2ResourceServer().jwt();\n        \/\/ @formatter:on\n    }\n}\n<\/pre>\n<p>To make it possible for the API gateway to access the Car Service, I created a&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">UserFeignClientInterceptor.java<\/code>&nbsp;in the API gateway project.<br \/>&gt;<em>api-gateway\/src\/main\/java\/com\/example\/apigateway\/UserFeignClientInterceptor.java<\/em><\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.example.apigateway;\n\nimport feign.RequestInterceptor;\nimport feign.RequestTemplate;\nimport org.springframework.security.core.Authentication;\nimport org.springframework.security.core.context.SecurityContextHolder;\nimport org.springframework.security.oauth2.client.OAuth2AuthorizedClient;\nimport org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;\nimport org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;\nimport org.springframework.security.oauth2.core.OAuth2AccessToken;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class UserFeignClientInterceptor implements RequestInterceptor {\n    private static final String AUTHORIZATION_HEADER = \"Authorization\";\n    private static final String BEARER_TOKEN_TYPE = \"Bearer\";\n    private final OAuth2AuthorizedClientService clientService;\n\n    public UserFeignClientInterceptor(OAuth2AuthorizedClientService clientService) {\n        this.clientService = clientService;\n    }\n\n    @Override\n    public void apply(RequestTemplate template) {\n        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();\n        OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;\n        OAuth2AuthorizedClient client = clientService.loadAuthorizedClient(\n                oauthToken.getAuthorizedClientRegistrationId(),\n                oauthToken.getName());\n\n        OAuth2AccessToken accessToken = client.getAccessToken();\n        template.header(AUTHORIZATION_HEADER, String.format(\"%s %s\", BEARER_TOKEN_TYPE, accessToken.getTokenValue()));\n    }\n}\n<\/pre>\n<p>I configured it as a&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">RequestInterceptor<\/code>&nbsp;in&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">ApiGatewayApplication.java<\/code>:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">@Bean\npublic RequestInterceptor getUserFeignClientInterceptor(OAuth2AuthorizedClientService clientService) {\n    return new UserFeignClientInterceptor(clientService);\n}\n<\/pre>\n<p>And, I added two properties in&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">api-gateway\/src\/main\/resources\/application.properties<\/code>&nbsp;so Feign is Spring Security-aware.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">feign.hystrix.enabled=true\nhystrix.shareSecurityContext=true\n<\/pre>\n<h2 class=\"wp-block-heading\" id=\"see-java-microservices-running-with-security-enabled\">See Java Microservices Running with Security Enabled<\/h2>\n<p>Run all of the applications with&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.\/mvnw<\/code>&nbsp;in separate terminal windows, or in your IDE if you prefer.<\/p>\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p> To make it simpler to run in an IDE, there is an aggregator&nbsp;<code>pom.xml<\/code>&nbsp;in the root directory. If you\u2019d installed&nbsp;<a href=\"https:\/\/emmanuelbernard.com\/blog\/2017\/02\/27\/start-intellij-idea-command-line\/\">IntelliJ IDEA\u2019s command line launcher<\/a>, you just need to run&nbsp;<code>idea pom.xml<\/code>. <\/p>\n<\/blockquote>\n<p>Navigate to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\"><a class=\"bare\" href=\"http:\/\/localhost:8080\/cool-cars\">http:\/\/localhost:8080\/cool-cars<\/a><\/code>&nbsp;and you\u2019ll be redirected to Okta to log in.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/okta-login-1-1024x702.png\" alt=\"Java Microservices\" class=\"wp-image-93457\" width=\"768\" height=\"527\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/okta-login-1-1024x702.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/okta-login-1-300x206.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/okta-login-1-768x527.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/okta-login-1.png 1600w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/><\/figure>\n<\/div>\n<p>Enter the username and password for your Okta developer account and you should see a list of cool cars.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/cool-cars-1024x421.png\" alt=\"Java Microservices\" class=\"wp-image-93458\" width=\"768\" height=\"316\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/cool-cars-1024x421.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/cool-cars-300x123.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/cool-cars-768x316.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/cool-cars.png 1600w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/><\/figure>\n<\/div>\n<p>If you made it this far and got the examples apps running, congratulations! You\u2019re super cool! \ud83d\ude0e<\/p>\n<h2 class=\"wp-block-heading\" id=\"use-netflix-zuul-and-spring-cloud-to-proxy-routes\">Use Netflix Zuul and Spring Cloud to Proxy Routes<\/h2>\n<p>Another handy feature you might like in your microservices architecture is&nbsp;<a href=\"https:\/\/github.com\/Netflix\/zuul\">Netflix Zuul<\/a>. Zuul is a gateway service that provides dynamic routing, monitoring, resiliency, and more.<\/p>\n<p>To add Zuul, I added it as a dependency to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">api-gateway\/pom.xml<\/code>:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:xml\">&lt;dependency&gt;\n    &lt;groupId&gt;org.springframework.cloud&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-cloud-starter-netflix-zuul&lt;\/artifactId&gt;\n&lt;\/dependency&gt;\n<\/pre>\n<p>Then I added&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@EnableZuulProxy<\/code>&nbsp;to the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">ApiGatewayApplication<\/code>&nbsp;class.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">import org.springframework.cloud.netflix.zuul.EnableZuulProxy;\n\n@EnableZuulProxy\n@SpringBootApplication\npublic class ApiGatewayApplication {\n    ...\n}\n<\/pre>\n<p>To pass the access token to proxied routes, I created an&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">AuthorizationHeaderFilter<\/code>&nbsp;class that extends&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">ZuulFilter<\/code>.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.example.apigateway;\n\nimport com.netflix.zuul.ZuulFilter;\nimport com.netflix.zuul.context.RequestContext;\nimport org.springframework.core.Ordered;\nimport org.springframework.security.core.Authentication;\nimport org.springframework.security.core.context.SecurityContextHolder;\nimport org.springframework.security.oauth2.client.OAuth2AuthorizedClient;\nimport org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;\nimport org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;\nimport org.springframework.security.oauth2.core.OAuth2AccessToken;\nimport org.springframework.security.oauth2.core.oidc.OidcUserInfo;\n\nimport java.util.Optional;\n\nimport static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;\n\npublic class AuthorizationHeaderFilter extends ZuulFilter {\n\n    private final OAuth2AuthorizedClientService clientService;\n\n    public AuthorizationHeaderFilter(OAuth2AuthorizedClientService clientService) {\n        this.clientService = clientService;\n    }\n\n    @Override\n    public String filterType() {\n        return PRE_TYPE;\n    }\n\n    @Override\n    public int filterOrder() {\n        return Ordered.LOWEST_PRECEDENCE;\n    }\n\n    @Override\n    public boolean shouldFilter() {\n        return true;\n    }\n\n    @Override\n    public Object run() {\n        RequestContext ctx = RequestContext.getCurrentContext();\n        Optional&lt;String&gt; authorizationHeader = getAuthorizationHeader();\n        authorizationHeader.ifPresent(s -&gt; ctx.addZuulRequestHeader(\"Authorization\", s));\n        return null;\n    }\n\n    private Optional&lt;String&gt; getAuthorizationHeader() {\n        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();\n        OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;\n        OAuth2AuthorizedClient client = clientService.loadAuthorizedClient(\n                oauthToken.getAuthorizedClientRegistrationId(),\n                oauthToken.getName());\n\n        OAuth2AccessToken accessToken = client.getAccessToken();\n\n        if (accessToken == null) {\n            return Optional.empty();\n        } else {\n            String tokenType = accessToken.getTokenType().getValue();\n            String authorizationHeaderValue = String.format(\"%s %s\", tokenType, accessToken.getTokenValue());\n            return Optional.of(authorizationHeaderValue);\n        }\n    }\n}\n<\/pre>\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p> You might notice that there\u2019s code in the&nbsp;<code>getAuthorizationHeader()<\/code>&nbsp;method that\u2019s very similar to the code that\u2019s in&nbsp;<code>UserFeignClientInterceptor<\/code>. Since it\u2019s only a few lines, I opted not to move these to a utility class. The Feign interceptor is for the&nbsp;<code>@FeignClient<\/code>, while the Zuul filter is for Zuul-proxied requests. <\/p>\n<\/blockquote>\n<p>To make Spring Boot and Zuul aware of this filter, I registered it as a bean in the main application class.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">public AuthorizationHeaderFilter authHeaderFilter(OAuth2AuthorizedClientService clientService) {\n    return new AuthorizationHeaderFilter(clientService);\n}\n<\/pre>\n<p>To proxy requests from the API Gateway to the Car Service, I added routes to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">api-gateway\/src\/main\/resources\/application.properties<\/code>.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">zuul.routes.car-service.path=\/cars\nzuul.routes.car-service.url=http:\/\/localhost:8090\n\nzuul.routes.home.path=\/home\nzuul.routes.home.url=http:\/\/localhost:8090\n\nzuul.sensitive-headers=Cookie,Set-Cookie<\/pre>\n<p>I added a&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">HomeController<\/code>&nbsp;to the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">car-service<\/code>&nbsp;project for the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/home<\/code>&nbsp;route.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.example.carservice;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.security.Principal;\n\n@RestController\npublic class HomeController {\n\n    private final static Logger log = LoggerFactory.getLogger(HomeController.class);\n\n    @GetMapping(\"\/home\")\n    public String howdy(Principal principal) {\n        String username = principal.getName();\n        JwtAuthenticationToken token = (JwtAuthenticationToken) principal;\n        log.info(\"claims: \" + token.getTokenAttributes());\n        return \"Hello, \" + username;\n    }\n}\n<\/pre>\n<h3 class=\"wp-block-heading\" id=\"confirm-your-zuul-routes-work\">Confirm Your Zuul Routes Work<\/h3>\n<p>Since these changes are already in the project you cloned, you should be able to view&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\"><a class=\"bare\" href=\"https:\/\/localhost:8080\/cars\">https:\/\/localhost:8080\/cars<\/a><\/code>&nbsp;and&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\"><a class=\"bare\" href=\"http:\/\/localhost:8080\/home\">http:\/\/localhost:8080\/home<\/a><\/code>&nbsp;in your browser.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/zuul-home-1024x504.png\" alt=\"Java Microservices\" class=\"wp-image-93459\" width=\"768\" height=\"378\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/zuul-home-1024x504.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/zuul-home-300x148.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/zuul-home-768x378.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/06\/zuul-home.png 1600w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/><\/figure>\n<\/div>\n<h2 class=\"wp-block-heading\" id=\"what-about-spring-cloud-config\">What About Spring Cloud Config?<\/h2>\n<p>One of the things you might\u2019ve noticed in this example is you had to configure the OIDC properties in each application. This could be a real pain if you had 500 microservices. Yes, you could define them as environment variables and this would solve the problem. However, if you have different microservices stacks using different OIDC client IDs, this approach will be difficult.<\/p>\n<p><a href=\"https:\/\/spring.io\/projects\/spring-cloud-config\">Spring Cloud Config<\/a>&nbsp;is a project that provides externalized configuration for distributed systems. Rather than adding it to this example, I\u2019ll cover it in a&nbsp;<a href=\"https:\/\/developer.okta.com\/blog\/2019\/05\/23\/java-microservices-spring-cloud-config\">future tutorial<\/a>.<\/p>\n<h2 class=\"wp-block-heading\" id=\"what-about-kotlin\">What About Kotlin?<\/h2>\n<p>I wrote this post with Java because it\u2019s the most popular language in the Java ecosystem. However,&nbsp;<a href=\"https:\/\/redmonk.com\/sogrady\/2019\/03\/20\/language-rankings-1-19\/\">Kotlin is on the rise<\/a>, according to RedMonk\u2019s programming language rankings from January 2019.<\/p>\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>For this quarter, at least, Kotlin grew substantially while all three of its fellow JVM-based counterparts declined. Kotlin jumped so far, in fact, that it finally broke into the Top 20 at #20 and leapfrogged Clojure (#24) and Groovy (#24) while doing so. It\u2019s still well behind Scala (#13), but Kotlin\u2019s growth has been second only to Swift in this history of these rankings so it will be interesting to see what lies ahead in the next run or two.<\/p>\n<\/blockquote>\n<p>Spring has excellent support for Kotlin, and you can choose it as a language on start.spring.io. If you\u2019d like to see us write more posts using Kotlin, please let us know in the comments!<\/p>\n<h2 class=\"wp-block-heading\" id=\"known-issues-with-refresh-tokens\">Known Issues with Refresh Tokens<\/h2>\n<p>By default, Okta\u2019s access tokens expire after one hour. This is expected, and short-lived access tokens are recommended when using OAuth 2.0. Refresh tokens typically live a lot longer\u2009\u2014\u2009think days or months\u2009\u2014\u2009and can be used to get new access tokens. This should happen automatically when using Okta\u2019s Spring Boot starter, but it does not.<\/p>\n<p>I configured my Okta org so its access tokens expire in five minutes. You can do this by going to&nbsp;<strong>API<\/strong>&nbsp;&gt;&nbsp;<strong>Authorization Servers<\/strong>&nbsp;&gt;&nbsp;<strong>Access Policies<\/strong>, click on the&nbsp;<strong>Default Policy<\/strong>, and edit its rule. Then change the access token lifetime from 1 hour to 5 minutes.<\/p>\n<p>Hit&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\"><a class=\"bare\" href=\"http:\/\/localhost:8080\/cool-cars\">http:\/\/localhost:8080\/cool-cars<\/a><\/code>&nbsp;in your browser and you\u2019ll be redirected to Okta to login. Log in and you should see a JSON string of cars.<\/p>\n<p>Go do something else for more than 5 minutes.<\/p>\n<p>Come back, refresh your browser and you\u2019ll see&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">[]<\/code>&nbsp;instead of all the cars.<\/p>\n<p>I\u2019m still working on a solution to this and will update this post once I find one. If you happen to know of a solution, please let me know!<\/p>\n<p><strong>Update:<\/strong>&nbsp;Spring Security 5.1 doesn\u2019t yet automatically refresh the OAuth access token. It should be&nbsp;<a href=\"https:\/\/github.com\/spring-projects\/spring-security\/issues\/6811\">available in Spring Security 5.2<\/a>.<\/p>\n<h2 class=\"wp-block-heading\" id=\"have-more-fun-with-spring-boot-spring-cloud-and-microservices\">Have More Fun with Spring Boot, Spring Cloud, and Microservices<\/h2>\n<p>I hope you liked this tour of how to build Java microservice architectures with Spring Boot and Spring Cloud. You learned how to build everything with minimal code, then configure it to be secure with Spring Security, OAuth 2.0, and Okta.<\/p>\n<p>You can find all the code shown in this tutorial&nbsp;<a href=\"https:\/\/github.com\/oktadeveloper\/java-microservices-examples\">on GitHub<\/a>.<\/p>\n<p>We\u2019re big fans of Spring Boot, Spring Cloud, and microservices on this blog. Here are several other posts you might find interesting:<\/p>\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2019\/05\/23\/java-microservices-spring-cloud-config?utm_campaign=text_website_all_multiple_dev_dev_java-microservices-spring-boot-spring-cloud_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Java Microservices with Spring Cloud Config and JHipster<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2019\/05\/13\/angular-8-spring-boot-2?utm_campaign=text_website_all_multiple_dev_dev_java-microservices-spring-boot-spring-cloud_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Angular 8 + Spring Boot 2.2: Build a CRUD App Today!<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2019\/05\/15\/spring-boot-login-options?utm_campaign=text_website_all_multiple_dev_dev_java-microservices-spring-boot-spring-cloud_null&amp;utm_source=jcg&amp;utm_medium=cpc\">A Quick Guide to Spring Boot Login Options<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2019\/04\/01\/spring-boot-microservices-with-kubernetes?utm_campaign=text_website_all_multiple_dev_dev_java-microservices-spring-boot-spring-cloud_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Build a Microservice Architecture with Spring Boot and Kubernetes<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2019\/03\/07\/spring-microservices-https-oauth2?utm_campaign=text_website_all_multiple_dev_dev_java-microservices-spring-boot-spring-cloud_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Secure Service-to-Service Spring Microservices with HTTPS and OAuth 2.0<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2019\/02\/28\/spring-microservices-docker?utm_campaign=text_website_all_multiple_dev_dev_java-microservices-spring-boot-spring-cloud_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Build Spring Microservices and Dockerize Them for Production<\/a><\/li>\n<\/ul>\n<p>Please follow us&nbsp;<a href=\"https:\/\/twitter.com\/oktadev\">on Twitter @oktadev<\/a>&nbsp;and subscribe to&nbsp;<a href=\"https:\/\/www.youtube.com\/c\/oktadev\">our YouTube channel<\/a>&nbsp;for more Spring Boot and microservices knowledge.<\/p>\n<p><a href=\"https:\/\/developer.okta.com\/blog\/2019\/05\/22\/java-microservices-spring-boot-spring-cloud?utm_campaign=text_website_all_multiple_dev_dev_java-microservices-spring-boot-spring-cloud_null&amp;utm_source=jcg&amp;utm_medium=cpc\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">&#8220;Java Microservices with Spring Boot and Spring Cloud&#8221;<\/a>&nbsp;was originally published on the Okta developer blog on May 22 2019<\/p>\n<p><span style=\"font-size: 20px;\"><b>Friends don\u2019t let friends write user auth. Tired of managing your own users?<\/b>  <a href=\"https:\/\/developer.okta.com\/signup\/?utm_campaign=text_website_all_multiple_dev_dev_java-microservices-spring-boot-spring-cloud_null&amp;utm_source=jcg&amp;utm_medium=cpc\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">Try Okta\u2019s API and Java SDKs today. Authenticate, manage, and secure users in any application within minutes.<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Friends don\u2019t let friends write user auth. Tired of managing your own users? Try Okta\u2019s API and Java SDKs today. Authenticate, manage, and secure users in any application within minutes. Java is a great language to use when developing a microservice architecture. In fact, some of the biggest names in our industry use it. Have &hellip;<\/p>\n","protected":false},"author":13127,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[960,30,854],"class_list":["post-93453","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-microservices","tag-spring","tag-spring-boot"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Java Microservices with Spring Boot and Spring Cloud - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Interested to learn about Java Microservices? Check our article explaining how to Implement a microservices architecture in Java with spring boot and cloud\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/developer.okta.com\/blog\/2019\/05\/22\/java-microservices-spring-boot-spring-cloud\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Java Microservices with Spring Boot and Spring Cloud - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Interested to learn about Java Microservices? Check our article explaining how to Implement a microservices architecture in Java with spring boot and cloud\" \/>\n<meta property=\"og:url\" content=\"https:\/\/developer.okta.com\/blog\/2019\/05\/22\/java-microservices-spring-boot-spring-cloud\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2019-06-24T06:21:11+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-07-01T09:33:19+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Matt Raible\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@mraible\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Matt Raible\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"17 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/22\\\/java-microservices-spring-boot-spring-cloud#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/06\\\/java-microservices-spring-boot-spring-cloud.html\"},\"author\":{\"name\":\"Matt Raible\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/54edd49deb980d7706e2af51514c3f7f\"},\"headline\":\"Java Microservices with Spring Boot and Spring Cloud\",\"datePublished\":\"2019-06-24T06:21:11+00:00\",\"dateModified\":\"2019-07-01T09:33:19+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/06\\\/java-microservices-spring-boot-spring-cloud.html\"},\"wordCount\":2096,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/22\\\/java-microservices-spring-boot-spring-cloud#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"Microservices\",\"Spring\",\"Spring Boot\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/22\\\/java-microservices-spring-boot-spring-cloud#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/06\\\/java-microservices-spring-boot-spring-cloud.html\",\"url\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/22\\\/java-microservices-spring-boot-spring-cloud\",\"name\":\"Java Microservices with Spring Boot and Spring Cloud - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/22\\\/java-microservices-spring-boot-spring-cloud#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/22\\\/java-microservices-spring-boot-spring-cloud#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2019-06-24T06:21:11+00:00\",\"dateModified\":\"2019-07-01T09:33:19+00:00\",\"description\":\"Interested to learn about Java Microservices? Check our article explaining how to Implement a microservices architecture in Java with spring boot and cloud\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/22\\\/java-microservices-spring-boot-spring-cloud#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/22\\\/java-microservices-spring-boot-spring-cloud\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/22\\\/java-microservices-spring-boot-spring-cloud#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"spring-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/05\\\/22\\\/java-microservices-spring-boot-spring-cloud#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Java Microservices with Spring Boot and Spring Cloud\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/54edd49deb980d7706e2af51514c3f7f\",\"name\":\"Matt Raible\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/753d82443e50aed1ed2746573af191fe3e45c277ff3bd29873012a1b614355a7?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/753d82443e50aed1ed2746573af191fe3e45c277ff3bd29873012a1b614355a7?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/753d82443e50aed1ed2746573af191fe3e45c277ff3bd29873012a1b614355a7?s=96&d=mm&r=g\",\"caption\":\"Matt Raible\"},\"description\":\"Java Champion and Developer Advocate @okta with a passion for skiing, mtn biking, VWs, &amp; good beer.\",\"sameAs\":[\"https:\\\/\\\/developer.okta.com\",\"https:\\\/\\\/x.com\\\/mraible\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/matt-raible\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Java Microservices with Spring Boot and Spring Cloud - Java Code Geeks","description":"Interested to learn about Java Microservices? Check our article explaining how to Implement a microservices architecture in Java with spring boot and cloud","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/developer.okta.com\/blog\/2019\/05\/22\/java-microservices-spring-boot-spring-cloud","og_locale":"en_US","og_type":"article","og_title":"Java Microservices with Spring Boot and Spring Cloud - Java Code Geeks","og_description":"Interested to learn about Java Microservices? Check our article explaining how to Implement a microservices architecture in Java with spring boot and cloud","og_url":"https:\/\/developer.okta.com\/blog\/2019\/05\/22\/java-microservices-spring-boot-spring-cloud","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2019-06-24T06:21:11+00:00","article_modified_time":"2019-07-01T09:33:19+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","type":"image\/jpeg"}],"author":"Matt Raible","twitter_card":"summary_large_image","twitter_creator":"@mraible","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Matt Raible","Est. reading time":"17 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/developer.okta.com\/blog\/2019\/05\/22\/java-microservices-spring-boot-spring-cloud#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/06\/java-microservices-spring-boot-spring-cloud.html"},"author":{"name":"Matt Raible","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/54edd49deb980d7706e2af51514c3f7f"},"headline":"Java Microservices with Spring Boot and Spring Cloud","datePublished":"2019-06-24T06:21:11+00:00","dateModified":"2019-07-01T09:33:19+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/06\/java-microservices-spring-boot-spring-cloud.html"},"wordCount":2096,"commentCount":1,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/developer.okta.com\/blog\/2019\/05\/22\/java-microservices-spring-boot-spring-cloud#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["Microservices","Spring","Spring Boot"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/developer.okta.com\/blog\/2019\/05\/22\/java-microservices-spring-boot-spring-cloud#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2019\/06\/java-microservices-spring-boot-spring-cloud.html","url":"https:\/\/developer.okta.com\/blog\/2019\/05\/22\/java-microservices-spring-boot-spring-cloud","name":"Java Microservices with Spring Boot and Spring Cloud - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/developer.okta.com\/blog\/2019\/05\/22\/java-microservices-spring-boot-spring-cloud#primaryimage"},"image":{"@id":"https:\/\/developer.okta.com\/blog\/2019\/05\/22\/java-microservices-spring-boot-spring-cloud#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2019-06-24T06:21:11+00:00","dateModified":"2019-07-01T09:33:19+00:00","description":"Interested to learn about Java Microservices? Check our article explaining how to Implement a microservices architecture in Java with spring boot and cloud","breadcrumb":{"@id":"https:\/\/developer.okta.com\/blog\/2019\/05\/22\/java-microservices-spring-boot-spring-cloud#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/developer.okta.com\/blog\/2019\/05\/22\/java-microservices-spring-boot-spring-cloud"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/developer.okta.com\/blog\/2019\/05\/22\/java-microservices-spring-boot-spring-cloud#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","width":150,"height":150,"caption":"spring-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/developer.okta.com\/blog\/2019\/05\/22\/java-microservices-spring-boot-spring-cloud#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Java Microservices with Spring Boot and Spring Cloud"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/54edd49deb980d7706e2af51514c3f7f","name":"Matt Raible","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/753d82443e50aed1ed2746573af191fe3e45c277ff3bd29873012a1b614355a7?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/753d82443e50aed1ed2746573af191fe3e45c277ff3bd29873012a1b614355a7?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/753d82443e50aed1ed2746573af191fe3e45c277ff3bd29873012a1b614355a7?s=96&d=mm&r=g","caption":"Matt Raible"},"description":"Java Champion and Developer Advocate @okta with a passion for skiing, mtn biking, VWs, &amp; good beer.","sameAs":["https:\/\/developer.okta.com","https:\/\/x.com\/mraible"],"url":"https:\/\/www.javacodegeeks.com\/author\/matt-raible"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/93453","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/13127"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=93453"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/93453\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/240"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=93453"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=93453"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=93453"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}