{"id":819,"date":"2020-03-30T03:00:00","date_gmt":"2020-03-30T03:00:00","guid":{"rendered":"http:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-3-f03bdfe30ceb\/"},"modified":"2021-02-04T01:42:05","modified_gmt":"2021-02-04T01:42:05","slug":"simple-spring-boot-service-to-kubernetes-application-step-3-f03bdfe30ceb","status":"publish","type":"post","link":"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-3-f03bdfe30ceb\/","title":{"rendered":"Building a Service Layer"},"content":{"rendered":"\n<p id=\"8ad0\">In this stage we\u2019re going to build out the <em class=\"markup--em markup--p-em\">service <\/em>or <em class=\"markup--em markup--p-em\">logical <\/em>layer of our microservice. I\u2019ll explain adapter and port or hexagonal architecture and covering the usage of mapstruct.<\/p>\n\n\n\n<h3 class=\"graf graf--h3 graf--leading wp-block-heading\" id=\"c8a4\">Service Design<\/h3>\n\n\n\n<p class=\"graf graf--p graf-after--h3\" id=\"0605\">Ports and adapter or hexagonal design is a <a class=\"markup--anchor markup--p-anchor\" href=\"https:\/\/www.thinktocode.com\/2018\/07\/19\/ports-and-adapters-architecture\/\" target=\"_blank\" rel=\"noopener\" data-href=\"https:\/\/www.thinktocode.com\/2018\/07\/19\/ports-and-adapters-architecture\/\">well<\/a> <a class=\"markup--anchor markup--p-anchor\" href=\"https:\/\/softwarecampament.wordpress.com\/portsadapters\/\" target=\"_blank\" rel=\"noopener\" data-href=\"https:\/\/softwarecampament.wordpress.com\/portsadapters\/\">discussed<\/a> <a class=\"markup--anchor markup--p-anchor\" href=\"https:\/\/spin.atomicobject.com\/2013\/02\/23\/ports-adapters-software-architecture\/\" target=\"_blank\" rel=\"noopener\" data-href=\"https:\/\/spin.atomicobject.com\/2013\/02\/23\/ports-adapters-software-architecture\/\">concept<\/a>, so I\u2019m not going to go into the pro and con of the design. Amazingly, the concepts work at the class, service or enterprise application scale. Additionally, spring\u2019s use of interfaces makes implementing hexagonal architecture extremely easy. I\u2019ll explain quickly the design of our service before we go much further and show how hexagonal design will be applied.<\/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\/1VVz0b00lkWYIgZRdtldFCw.png?w=960\" alt=\"\" data-recalc-dims=\"1\"\/><\/figure>\n\n\n\n<p class=\"graf graf--p graf-after--figure\" id=\"b157\">Ideally, we would like our service layer to only \u2018talk\u2019 in the concept of a model object. As we push the REST and DB concepts to the edges we will maintain a different structure, even though they may look exactly the same. The reason for this is that our java beans tend to get loaded up with annotations that are specific to the port or adapter that they function with.<\/p>\n\n\n\n<p class=\"graf graf--p graf-after--p\" id=\"49a2\">For example, our <code class=\"markup--code markup--p-code\">CustomerEntity<\/code> object is currently loaded up with spring data annotations used for mapping to the database fields. These are only relevant for the DB interaction (completely useless at the rest endpoint). Additionally, loading up our model with annotations for every port or adapter makes the model object difficult to read, maintain and evolve.<\/p>\n\n\n\n<p class=\"graf graf--p graf-after--p graf--trailing\" id=\"53b3\">However, this does come at a cost, in that we need to map our model object to the structures used by the ports and adapters. Mapping or translating is not to be taken lightly as this becomes a very risky portion of our application in terms of its evolution (but actually helps with service governance, which we will cover later). Additionally, writing bean mappers is tedious. So we\u2019re introducing tedious and error prone code, how do we mitigate that? We can use mapstruct framework to do the heavy lifting.<\/p>\n\n\n\n<h3 class=\"graf graf--h3 graf--leading wp-block-heading\" id=\"59c0\">Introducing Mapstruct<\/h3>\n\n\n\n<p class=\"graf graf--p graf-after--h3 graf--trailing\" id=\"7a21\">Mapstruct is a framework that is designed for mapping data between beans. It is very useful for handing simple cases, but it is also powerful enough to handle complex or custom mapping. Take a look at the <a class=\"markup--anchor markup--p-anchor\" href=\"https:\/\/mapstruct.org\/documentation\/stable\/reference\/html\/\" target=\"_blank\" rel=\"noopener\" data-href=\"https:\/\/mapstruct.org\/documentation\/stable\/reference\/html\/\">documentation <\/a>and <a class=\"markup--anchor markup--p-anchor\" href=\"https:\/\/www.baeldung.com\/mapstruct\" target=\"_blank\" rel=\"noopener\" data-href=\"https:\/\/www.baeldung.com\/mapstruct\">examples<\/a>.<\/p>\n\n\n\n<h3 class=\"graf graf--h3 graf--leading wp-block-heading\" id=\"76f8\">Using Mapstruct<\/h3>\n\n\n\n<h4 class=\"graf graf--h4 graf-after--h3 wp-block-heading\" id=\"2a8e\">Create the&nbsp;Model<\/h4>\n\n\n\n<p class=\"graf graf--p graf-after--h4\" id=\"d662\">Lets start by creating our model object in <code class=\"markup--code markup--p-code\">com.brianrook.medium.customer.service.model<\/code>. Create a java class called <code class=\"markup--code markup--p-code\">Customer <\/code>and add this content:<\/p>\n\n\n\n<pre id=\"d039\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>package com.brianrook.medium.customer.service.model;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@Builder\n@NoArgsConstructor\n@AllArgsConstructor\npublic class Customer {\n    private Long customerId;\n    private String firstName;\n    private String lastName;\n    private String phoneNumber;\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=\"b76f\"><p>This looks exactly like the <code class=\"markup--code markup--blockquote-code\">CustomerEntity <\/code>without the persistence annotations, right? It sure does. I actually copy\/pasted most of that class into this class and removed the annotations. But that\u2019s the point: now my model object doesn\u2019t have those persistence annotations in it and is more useful because of that.<\/p><\/blockquote>\n\n\n\n<h4 class=\"graf graf--h4 graf-after--blockquote wp-block-heading\" id=\"7f96\">Create the&nbsp;Mapper<\/h4>\n\n\n\n<p class=\"graf graf--p graf-after--h4\" id=\"78e1\">Create a package called <code class=\"markup--code markup--p-code\">com.brianrook.medium.customer.dao.mapper<\/code>. In that package create a java interface called <code class=\"markup--code markup--p-code\">CustomerEntityMapper<\/code>. In that interface add this content:<\/p>\n\n\n\n<pre id=\"88ec\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>package com.brianrook.medium.customer.dao.mapper;\n\nimport com.brianrook.medium.customer.dao.entity.CustomerEntity;\nimport com.brianrook.medium.customer.service.model.Customer;\nimport org.mapstruct.Mapper;\nimport org.mapstruct.factory.Mappers;\n\n@Mapper\npublic interface CustomerEntityMapper {\n    CustomerEntityMapper <em class=\"markup--em markup--pre-em\">INSTANCE <\/em>= Mappers.<em class=\"markup--em markup--pre-em\">getMapper<\/em>(CustomerEntityMapper.class);\n\n    CustomerEntity customerToCustomerEntity(Customer customer);\n    Customer customerEntityToCustomer(CustomerEntity customerEntity);\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=\"88b8\"><p>This is a very simple mapper because the field names in the classes are the same and mapstruct knows how to map fields that are named the same automatically. As you can see we can translate both ways between the model and the entity.<\/p><\/blockquote>\n\n\n\n<h4 class=\"graf graf--h4 graf-after--blockquote wp-block-heading\" id=\"bac7\">Create the&nbsp;Service<\/h4>\n\n\n\n<p class=\"graf graf--p graf-after--h4\" id=\"5c71\">In <code class=\"markup--code markup--p-code\">com.brianrook.medium.customer.service<\/code>create a java class called <code class=\"markup--code markup--p-code\">CustomerService<\/code>. In that class add this content:<\/p>\n\n\n\n<pre id=\"c13b\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>package com.brianrook.medium.customer.service;\n\nimport com.brianrook.medium.customer.dao.CustomerDAO;\nimport com.brianrook.medium.customer.dao.entity.CustomerEntity;\nimport com.brianrook.medium.customer.dao.mapper.CustomerEntityMapper;\nimport com.brianrook.medium.customer.service.model.Customer;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n@Service\n@Slf4j\npublic class CustomerService {\n\n    @Autowired\n    CustomerDAO customerDAO;\n\n    public Customer saveCustomer(Customer customer) {\n        return persistCustomer(customer);\n    }\n\n    private Customer persistCustomer(Customer customer) {\n        CustomerEntity customerEntity = CustomerEntityMapper.<em class=\"markup--em markup--pre-em\">INSTANCE<\/em>.customerToCustomerEntity(customer);\n        CustomerEntity storedEntity = customerDAO.save(customerEntity);\n        Customer returnCustomer = CustomerEntityMapper.<em class=\"markup--em markup--pre-em\">INSTANCE<\/em>.customerEntityToCustomer(storedEntity);\n        return returnCustomer;\n    }\n\n\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=\"9284\"><p>This is a very simple service but you can see how we\u2019re using mapstruct. I\u2019ve isolated the code that is used for transforming a customer to a customer entity into its own method and tied it to the logic around the <code class=\"markup--code markup--blockquote-code\">CustomerDAO<\/code>. That makes the <code class=\"markup--code markup--blockquote-code\">saveCustomer <\/code>method very clean and it would be very easy to add validation logic, message publishing or any other functionality to that service method.<\/p><\/blockquote>\n\n\n\n<p class=\"graf graf--p graf-after--blockquote\" id=\"c13c\">At this point, I probably should write tests, especially around the mapping logic since I\u2019ve already called that out as a very risky bit of code. However, I\u2019m going to save that for the next step. Lets make sure this builds and the tests still pass.<\/p>\n\n\n\n<h3 class=\"graf graf--h3 graf-after--p wp-block-heading\" id=\"1b45\"><strong class=\"markup--strong markup--h3-strong\">Build and&nbsp;Commit<\/strong><\/h3>\n\n\n\n<pre id=\"e297\" class=\"wp-block-code graf graf--pre graf-after--h3\"><code>git checkout -b service\nmvn clean install\ngit add .\ngit commit -m \"Building the service layer\"\ngit push --set-upstream origin service<\/code><\/pre>\n\n\n\n<pre id=\"f2c9\" class=\"wp-block-code graf graf--pre graf-after--pre\"><code>git checkout master\ngit merge service\ngit push<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<div class=\"entry-summary\">\nIn this stage we\u2019re going to build out the service or logical&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-3-f03bdfe30ceb\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &ldquo;Building a Service Layer&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":[29,48,47,50,55,42,43],"course":[40],"class_list":["post-819","post","type-post","status-publish","format-standard","hentry","category-software-development","tag-git","tag-lombok","tag-mapstruct","tag-maven","tag-microservice","tag-spring","tag-spring-boot","course-spring-with-kubernetes","entry"],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":827,"url":"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-1-d67f80487848\/","url_meta":{"origin":819,"position":0},"title":"Setup: IDE and New Project","author":"Bullyrook","date":"March 30, 2020","format":false,"excerpt":"\u00a0Its very easy to get a spring boot microservice up and running. You can read any variety of articles on medium (or other service) on how to do that. However, there\u2019s little about how to do some of the more complicated things that you need in order to support a\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":"","width":0,"height":0},"classes":[]},{"id":1242,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/02\/13\/kube-cloud-pt3-synchronous-service-interaction\/","url_meta":{"origin":819,"position":1},"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":1356,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/02\/27\/kube-cloud-pt5-create-an-event-consumer\/","url_meta":{"origin":819,"position":2},"title":"Kube Cloud Pt5 | Create an Event Consumer","author":"Bullyrook","date":"February 27, 2022","format":false,"excerpt":"Now that we've got messages being published to kafka, we are going to need to build our consumer that receives those events and stores them into the mongo database. Go ahead and create a new repository called message-repository according to the microservice startup course here. This is the pom.xml that\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-49.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-49.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-49.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":1220,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/01\/23\/cloud-kube-pt2-setting-up-a-datastore\/","url_meta":{"origin":819,"position":3},"title":"Cloud Kube Pt2 | Setting Up a Datastore","author":"Bullyrook","date":"January 23, 2022","format":false,"excerpt":"The first part of these courses was all about setting up an build and deploy pipeline so that we could automate building a helm chart and deploying to our cloud hosted environment at Okteto. In this course we're going to start adding more functionality so that we can demonstrate best\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-38.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-38.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-38.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":815,"url":"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-14-8e1ade0b7b84\/","url_meta":{"origin":819,"position":4},"title":"System Design","author":"Bullyrook","date":"March 30, 2020","format":false,"excerpt":"We\u2019ve successfully deployed a service and confirmed that its accessible. However, a single service doesn\u2019t make an app. We now need to fill out the rest of the application and introduce some best practices around service governance and system engineering. The Application Design We\u2019re going to be organizing the UI\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":"","width":0,"height":0},"classes":[]},{"id":828,"url":"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-4-dba10da3d834\/","url_meta":{"origin":819,"position":5},"title":"Create a REST Controller","author":"Bullyrook","date":"March 30, 2020","format":false,"excerpt":"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 functional or component test and explain how those test work and why they\u2019re\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":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/819","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=819"}],"version-history":[{"count":2,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/819\/revisions"}],"predecessor-version":[{"id":881,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/819\/revisions\/881"}],"wp:attachment":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/media?parent=819"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/categories?post=819"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/tags?post=819"},{"taxonomy":"course","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/course?post=819"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}