{"id":828,"date":"2020-03-30T04:00:00","date_gmt":"2020-03-30T04:00:00","guid":{"rendered":"http:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-4-dba10da3d834\/"},"modified":"2021-02-04T01:45:05","modified_gmt":"2021-02-04T01:45:05","slug":"simple-spring-boot-service-to-kubernetes-application-step-4-dba10da3d834","status":"publish","type":"post","link":"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-4-dba10da3d834\/","title":{"rendered":"Create a REST Controller"},"content":{"rendered":"\n<p class=\"graf graf--p graf-after--h3 graf--trailing\" id=\"b0fb\">In this article we\u2019re going to take the service layer we created in the last step and add a REST interface to it. We\u2019re going to follow the hexagonal design principles we previously discussed and add a <em class=\"markup--em markup--p-em\">functional <\/em>or <em class=\"markup--em markup--p-em\">component <\/em>test and explain how those test work and why they\u2019re important.<\/p>\n\n\n\n<h3 class=\"graf graf--h3 graf--leading wp-block-heading\" id=\"cc90\">Create the Controller and&nbsp;DTO<\/h3>\n\n\n\n<h4 class=\"graf graf--h4 graf-after--h3 wp-block-heading\" id=\"49bd\">Create the&nbsp;DTO<\/h4>\n\n\n\n<p class=\"graf graf--p graf-after--h4\" id=\"faf0\">Create a package called <code class=\"markup--code markup--p-code\">com.brianrook.medium.customer.controller.dto<\/code>. Create a class called <code class=\"markup--code markup--p-code\">CustomerDTO <\/code>and add this content:<\/p>\n\n\n\n<pre id=\"8077\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>package com.brianrook.medium.customer.controller.dto;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@Builder\n@NoArgsConstructor\n@AllArgsConstructor\npublic class CustomerDTO {\n    private Long customerId;\n    @NotBlank\n    @Size(min = 0, max = 100)\n    private String firstName;\n    @NotBlank\n    @Size(min = 0, max = 100)\n    private String lastName;\n    @Pattern(regexp=\"\\\\(\\\\d{3}\\\\)\\\\d{3}-\\\\d{4}\", message = \"Phone number must match the pattern (###)###-####\")\n    @Size(max = 20)\n    private String phoneNumber;\n    @Email\n    @Size(max = 150)\n    private String email;\n}<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote graf graf--blockquote graf-after--pre is-layout-flow wp-block-quote-is-layout-flow\" id=\"e1e7\"><p>You can see here that we\u2019ve added javax validation annotations to the DTO. This will signal to spring to trap and return 400 on invalid data.<\/p><\/blockquote>\n\n\n\n<h4 class=\"graf graf--h4 graf-after--blockquote wp-block-heading\" id=\"4b96\">Service Configuration<\/h4>\n\n\n\n<p class=\"graf graf--p graf-after--h4\" id=\"1d0a\">We also need to add some configuration. In <code class=\"markup--code markup--p-code\">src\/main\/resources<\/code> create an <code class=\"markup--code markup--p-code\">application.yaml<\/code> (if it doesn\u2019t exist. Delete any application.properties or bootstrap.properties)<\/p>\n\n\n\n<pre id=\"1fd6\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>server:\n  port: 10000\nspring:\n  application:\n    name: customer\n  jackson:\n    deserialization:\n      FAIL_ON_UNKNOWN_PROPERTIES: false<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote graf graf--blockquote graf-after--pre is-layout-flow wp-block-quote-is-layout-flow\" id=\"3c58\"><p>Here we\u2019re going to tell spring to start up on port 10000 refer to this service as customer and also setup the jackson deserializer to ignore any fields that are either not sent or don\u2019t map to fields in our DTO.<\/p><\/blockquote>\n\n\n\n<h4 class=\"graf graf--h4 graf-after--blockquote wp-block-heading\" id=\"8c1d\">Create the Controller<\/h4>\n\n\n\n<p class=\"graf graf--p graf-after--h4\" id=\"4c26\">Create a class called <code class=\"markup--code markup--p-code\">CustomerController <\/code>in <code class=\"markup--code markup--p-code\">com.brianrook.medium.customer.controller<\/code>. Add this content:<\/p>\n\n\n\n<pre id=\"80c1\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>package com.brianrook.medium.customer.controller;\n\nimport com.brianrook.medium.customer.controller.dto.CustomerDTO;\nimport com.brianrook.medium.customer.service.CustomerService;\nimport com.brianrook.medium.customer.service.model.Customer;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\n\nimport java.net.URISyntaxException;\n\n@Controller\n@RequestMapping(value = \"\/customer\")\n@Slf4j\npublic class CustomerController {\n    @Autowired\n    private CustomerService customerService;\n\n    @PostMapping(value = \"\/\",\n            consumes = MediaType.<em class=\"markup--em markup--pre-em\">APPLICATION_JSON_VALUE<\/em>,\n            produces = MediaType.<em class=\"markup--em markup--pre-em\">APPLICATION_JSON_VALUE<\/em>)\n    public ResponseEntity&lt;CustomerDTO&gt; saveCustomer(\n            @RequestBody @Valid CustomerDTO customerDTO) throws URISyntaxException {\n        Customer customer = CustomerDTOMapper.INSTANCE.customerDTOToCustomer(customerDTO);\n\n        Customer savedCustomer = customerService.saveCustomer(customer);\n\n        CustomerDTO savedCustomerDTO = CustomerDTOMapper.INSTANCE.customerToCustomerDTO(savedCustomer);\n        return new ResponseEntity&lt;CustomerDTO&gt;(savedCustomerDTO, HttpStatus.<em class=\"markup--em markup--pre-em\">CREATED<\/em>);\n    }\n}<\/code><\/pre>\n\n\n\n<h4 class=\"graf graf--h4 graf-after--pre wp-block-heading\" id=\"fab9\">Create DTO&nbsp;Mapper<\/h4>\n\n\n\n<p class=\"graf graf--p graf-after--h4\" id=\"ea96\">This isn\u2019t going to compile yet, because we need to create a mapper for the DTO to the model object. Lets create a new package in <code class=\"markup--code markup--p-code\">com.brianrook.medium.customer.controller.mapper<\/code> and add an interface called <code class=\"markup--code markup--p-code\">CustomerDTOMapper<\/code> into that package with this content:<\/p>\n\n\n\n<pre id=\"0e4d\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>package com.brianrook.medium.customer.controller.mapper;\n\nimport com.brianrook.medium.customer.controller.dto.CustomerDTO;\nimport com.brianrook.medium.customer.service.model.Customer;\nimport org.mapstruct.Mapper;\nimport org.mapstruct.factory.Mappers;\n\n@Mapper\npublic interface CustomerDTOMapper {\n    CustomerDTOMapper <em class=\"markup--em markup--pre-em\">INSTANCE <\/em>= Mappers.<em class=\"markup--em markup--pre-em\">getMapper<\/em>(CustomerDTOMapper.class);\n\n    CustomerDTO customerToCustomerDTO(Customer customer);\n\n    Customer customerDTOToCustomer(CustomerDTO customerEntity);\n}<\/code><\/pre>\n\n\n\n<p class=\"graf graf--p graf-after--pre\" id=\"86e8\">Import that class into the controller and make sure it compiles.<\/p>\n\n\n\n<h4 class=\"graf graf--h4 graf-after--p wp-block-heading\" id=\"dd3e\">Give it a Floor&nbsp;Run<\/h4>\n\n\n\n<p class=\"graf graf--p graf-after--h4\" id=\"cbde\">Lets start the application and test it with postman. Right click on MediumCustomerApplication, choose <code class=\"markup--code markup--p-code\">Run \u2018MediumCustomer\u2026main()<\/code> and confirm that you can see the application startup succesfully:<\/p>\n\n\n\n<pre id=\"6eea\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>2020-03-28 13:28:28.773  INFO &#91;customer,,,] 20504 --- &#91;  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 10000 (http) with context path ''\n2020-03-28 13:28:29.081  INFO &#91;customer,,,] 20504 --- &#91;  restartedMain] c.b.m.c.MediumCustomerApplication        : Started MediumCustomerApplication in 9.781 seconds (JVM running for 10.525)<\/code><\/pre>\n\n\n\n<p class=\"graf graf--p graf-after--pre\" id=\"9bf7\">You can use postman to make a post. Here\u2019s the request:<\/p>\n\n\n\n<pre id=\"bee7\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>POST \/customer\/ HTTP\/1.1\nHost: localhost:10000\nContent-Type: application\/json<\/code><\/pre>\n\n\n\n<pre id=\"07b6\" class=\"wp-block-code graf graf--pre graf-after--pre\"><code>{\n \"firstName\": \"Brian\",\n \"lastName\":  \"Rook\",\n \"phoneNumber\": \"(303)555-1212\",\n \"email\": \"<a class=\"markup--anchor markup--pre-anchor\" href=\"mailto:testuser@test.com\" target=\"_blank\" rel=\"nofollow noopener\" data-href=\"mailto:testuser@test.com\">testuser@test.com<\/a>\"\n}<\/code><\/pre>\n\n\n\n<p class=\"graf graf--p graf-after--pre\" id=\"4a20\">which should respond with:<\/p>\n\n\n\n<pre id=\"c45c\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>201 Created\n{\n\"customerId\": 1,\n\"firstName\": \"Brian\",\n\"lastName\": \"Rook\",\n\"phoneNumber\": \"(303)555-1212\",\n\"email\": \"testuser@test.com\"\n}<\/code><\/pre>\n\n\n\n<h3 class=\"graf graf--h3 graf-after--pre wp-block-heading\" id=\"2679\">Write a Functional Test<\/h3>\n\n\n\n<p class=\"graf graf--p graf-after--h3\" id=\"f7ca\">In the test directory create a new java package for <code class=\"markup--code markup--p-code\">com.brianrook.medium.customer.controller<\/code>. In that package create a class called <code class=\"markup--code markup--p-code\">CustomerControllerTest<\/code>. Add this content:<\/p>\n\n\n\n<pre id=\"f1b5\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>@Autowired\nprivate OrganizerDAO organizerDAO;\n@LocalServerPort\nint randomServerPort;\n\n\nString organizerPath = \"\/organizer\/\";\n\n@BeforeEach\npublic void setUp(){\n    organizerDAO.deleteAll();\n}\n\n@Test\npublic void testAddCustomerSuccess() throws URISyntaxException\n{\n    RestTemplate restTemplate = new RestTemplate();\n    String baseUrl = \"http:\/\/localhost:\"+randomServerPort+organizerPath;\n    URI uri = new URI(baseUrl);\n    OrganizerDTO organizerDTO = OrganizerDTO.<em class=\"markup--em markup--pre-em\">builder<\/em>()\n            .firstName(\"test\")\n            .lastName(\"user\")\n            .email(\"test.user@docketdynamics.com\")\n            .phoneNumber(\"(123)654-7890\")\n            .build();\n\n    HttpHeaders headers = new HttpHeaders();\n    headers.set(HttpHeaders.<em class=\"markup--em markup--pre-em\">CONTENT_TYPE<\/em>, MediaType.<em class=\"markup--em markup--pre-em\">APPLICATION_JSON_VALUE<\/em>);\n\n    HttpEntity&lt;OrganizerDTO&gt; request = new HttpEntity&lt;&gt;(organizerDTO, headers);\n\n    ResponseEntity&lt;OrganizerDTO&gt; result = restTemplate.postForEntity(uri, request, OrganizerDTO.class);\n\n    \/\/Verify request succeed\n    Assertions.<em class=\"markup--em markup--pre-em\">assertEquals<\/em>(201, result.getStatusCodeValue());\n    Long newOrganizerId = result.getBody().getOrganizerId();\n    Assertions.<em class=\"markup--em markup--pre-em\">assertTrue<\/em>(newOrganizerId!=null &amp;&amp; newOrganizerId&gt;0);\n\n    \/\/verify the state of the database\n    Optional&lt;CustomerEntity&gt; storedEntityOptional = customerDAO.findById(newCustomerId);\n<em class=\"markup--em markup--pre-em\">assertTrue<\/em>(storedEntityOptional.isPresent());\n}<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote graf graf--blockquote graf-after--pre is-layout-flow wp-block-quote-is-layout-flow\" id=\"6e30\"><p>In this test we\u2019re telling spring to start up an application context. In that context: start up our web container on a random port. Then we\u2019re making a restTemplate that will make a request to our endpoint (create customer). We then verify the response is correct, but we also make sure that the database has the record we expect.<\/p><\/blockquote>\n\n\n\n<p class=\"graf graf--p graf-after--blockquote\" id=\"610a\">Now we can run the test and get a success. However, we should also run code coverage at this point. In the test configuration window, go to the <code class=\"markup--code markup--p-code\">Code Coverage<\/code> tab and change the <code class=\"markup--code markup--p-code\">packages to include in coverage data<\/code> to reflect our entire package.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/02\/1hsSTmSLWelEN6sg7EwGWgA.png?w=960\" alt=\"\" data-recalc-dims=\"1\"\/><\/figure>\n\n\n\n<p class=\"graf graf--p graf-after--figure\" id=\"dcb5\">Run the tests again with coverage enabled and review the report. You should see that the only code that wasn\u2019t covered was some of the Lombok constructors (because we used them in our tests). We\u2019ll fix this later when we add code coverage to our maven build process.<\/p>\n\n\n\n<h3 class=\"graf graf--h3 graf-after--p wp-block-heading\" id=\"48e8\">Why Functional Testing is Better than Integration Testing<\/h3>\n\n\n\n<p class=\"graf graf--p graf-after--h3\" id=\"9748\">In previous projects, on different teams, we used a different paradigm of writing tests for each class which involved writing lots of mock objects. There are several problems with these types of tests:<\/p>\n\n\n\n<ul class=\"postList wp-block-list\"><li id=\"c3ea\" class=\"graf graf--li graf-after--p\">You write a lot more tests<\/li><li id=\"69d3\" class=\"graf graf--li graf-after--li\">They chain you to your current design\/implementation<\/li><li id=\"d297\" class=\"graf graf--li graf-after--li\">The mocks introduce uncertainty around expected behavior vs actual behavior<\/li><\/ul>\n\n\n\n<p class=\"graf graf--p graf-after--li\" id=\"a80f\">Although writing lots of tests is tedious, its not the biggest drain to productivity. In reality, being chained to your current design and the uncertainty of the behavior introduces A LOT of risk to your development effort. For example, introducing a new field in the database would mean making the change to the database and the DAO. Then updating the mock that is used for the service test and then updating the service test. This cascade of changes is a huge drag on your development effort. This doesn\u2019t even cover the concerns related to adding a feature and finding out the tests break. Now you have to decipher the old tests, their mocks as well as the actual service code. It becomes a nightmare.<\/p>\n\n\n\n<p class=\"graf graf--p graf-after--p\" id=\"fe73\">Functional tests reduce the number of tests you need and can achieve the same amount of code coverage. Additionally, they are driven by testing behavior and not implementation. This means that you can change your internal design all you want. As long as the \u2018edges\u2019 of your system don\u2019t change your tests will still pass.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/02\/1hsSTmSLWelEN6sg7EwGWgA.png?w=960\" alt=\"\" data-recalc-dims=\"1\"\/><\/figure>\n\n\n\n<p class=\"graf graf--p graf-after--figure\" id=\"64e5\">Since there are no dependencies outside of our application (we\u2019re not using a real database or external rest client), we can run this type of test at maven build time as a \u2018unit\u2019 test.<\/p>\n\n\n\n<p class=\"graf graf--p graf-after--p\" id=\"8fdd\">Functional testing gives us a high level of confidence about the behavior of our system, it gives us a high level of code coverage, we don\u2019t spend a lot of time writing tests, we have flexibility to change our system\u2026 the advantages are numerous.<\/p>\n\n\n\n<h3 class=\"graf graf--h3 graf-after--p wp-block-heading\" id=\"55f3\">Build and&nbsp;Commit<\/h3>\n\n\n\n<p class=\"graf graf--p graf-after--h3\" id=\"4d7f\">Lets go ahead and verify our application works and then push up our changes.<\/p>\n\n\n\n<pre id=\"af4c\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>git checkout -b controller\nmvn clean install\ngit add .\ngit commit -m \"controller and tests\"\ngit push<\/code><\/pre>\n\n\n\n<pre id=\"6516\" class=\"wp-block-code graf graf--pre graf-after--pre\"><code>git checkout master\ngit merge controller\ngit push<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<div class=\"entry-summary\">\nIn this article we\u2019re going to take the service layer we created&hellip;\n<\/div>\n<div class=\"link-more\"><a href=\"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-4-dba10da3d834\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &ldquo;Create a REST Controller&rdquo;<\/span>&hellip;<\/a><\/div>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[41],"tags":[58,60,29,48,47,50,57,42,43,59,54],"course":[40],"class_list":["post-828","post","type-post","status-publish","format-standard","hentry","category-software-development","tag-component-test","tag-functional-testing","tag-git","tag-lombok","tag-mapstruct","tag-maven","tag-rest","tag-spring","tag-spring-boot","tag-unit-test","tag-unit-testing","course-spring-with-kubernetes","entry"],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":1153,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/01\/02\/cloud-kube-simple-rest-endpoint-and-test\/","url_meta":{"origin":828,"position":0},"title":"Cloud Kube | Simple REST Endpoint and Test","author":"Bullyrook","date":"January 2, 2022","format":false,"excerpt":"In the previous article we created the skeleton repo and project. In this article we'll be building a very basic endpoint and component test. Although I do hate hello world examples my intent is to get us to a point where we can focus on the build and deploy path.\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-11.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":1395,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/03\/12\/kube-cloud-pt6-update-to-consumer-contract\/","url_meta":{"origin":828,"position":1},"title":"Kube Cloud Pt6 | Break the Contract from a Consumer Change","author":"Bullyrook","date":"March 12, 2022","format":false,"excerpt":"We're going to go back to cloud-application at this point and update our client to expect a field that isn't being currently provided (message generated date). This should break our contract test and prevent us from deploying, but there's some updates we need to make to support this. Add the\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/03\/image-25.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/03\/image-25.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/03\/image-25.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":1258,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/02\/13\/kube-cloud-pt3-rest-interaction\/","url_meta":{"origin":828,"position":2},"title":"Kube Cloud Pt3 | REST Interaction","author":"Bullyrook","date":"February 13, 2022","format":false,"excerpt":"Now that we've got a new service, we're going to make it discoverable via kubernetes and call it from the cloud application service. Enable Kubernetes Features Let's start a new branch in our cloud_application project $ git checkout -b kube Switched to a new branch 'kube' Edit the pom.xml and\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":1081,"url":"https:\/\/bullyrooks.com\/index.php\/2021\/07\/24\/spring-boot-lambda-api-implementation\/","url_meta":{"origin":828,"position":3},"title":"Spring Boot Lambda API Implementation","author":"Bullyrook","date":"July 24, 2021","format":false,"excerpt":"We've got a 'working' lambda now, but we can't actually use it anywhere. The easiest thing to do at this point is add an API Gateway trigger to our function as a new lambda. This will require a little bit of work to make an API Gateway adapter to our\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-10.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-10.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-10.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":1242,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/02\/13\/kube-cloud-pt3-synchronous-service-interaction\/","url_meta":{"origin":828,"position":4},"title":"Kube Cloud Pt3 | Synchronous Service Interaction","author":"Bullyrook","date":"February 13, 2022","format":false,"excerpt":"In this course I'm going to show you how to make another spring boot microservice (message-generator), deploy it with our first service (cloud-application). I'll show how cloud-application service can discover message-generator via kubernetes services, call an endpoint in message-generator with a feign based REST client as well as how to\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-45.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-45.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-45.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-45.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-45.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":1161,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/01\/02\/cloud-kube-build-pipeline-initialization\/","url_meta":{"origin":828,"position":5},"title":"Cloud Kube | Build Pipeline Initialization","author":"Bullyrook","date":"January 2, 2022","format":false,"excerpt":"Now that we have a service we're going to start building our pipeline so that as we add functionality to the application we can incorporate any build needs into the pipeline. Initialize Github Actions Create a new directory from the root of the project called .github\/workflows\/ create a file called\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-16.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-16.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-16.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-16.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-16.png?resize=1400%2C800&ssl=1 4x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/828","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/comments?post=828"}],"version-history":[{"count":3,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/828\/revisions"}],"predecessor-version":[{"id":883,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/828\/revisions\/883"}],"wp:attachment":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/media?parent=828"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/categories?post=828"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/tags?post=828"},{"taxonomy":"course","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/course?post=828"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}