<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: krud.dev</title>
    <description>The latest articles on DEV Community by krud.dev (@krud).</description>
    <link>https://dev.to/krud</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F5899%2F286a9165-6d30-4563-87ff-4a0b04468a9f.png</url>
      <title>DEV Community: krud.dev</title>
      <link>https://dev.to/krud</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/krud"/>
    <language>en</language>
    <item>
      <title>Ostara Version 0.10.0 Has Been Released</title>
      <dc:creator>Idan Elhalwani</dc:creator>
      <pubDate>Mon, 12 Jun 2023 08:48:00 +0000</pubDate>
      <link>https://dev.to/krud/ostara-version-0100-has-been-released-50ap</link>
      <guid>https://dev.to/krud/ostara-version-0100-has-been-released-50ap</guid>
      <description>&lt;p&gt;Hello and welcome to the first major update of Ostara! &lt;/p&gt;

&lt;p&gt;We've been working hard the last 3 weeks on our latest release and I'm happy to say it's finally here: we are super excited to release version 0.10.0 of Ostara and bring it one step closer out of Alpha. This release is full of new features and improvements to make your experience smoother than ever. Among the many awesome updates, the one we are most thrilled about is the newly introduced Metrics Notifications!&lt;/p&gt;

&lt;p&gt;Before diving into the specifics, let's quickly brush up on Ostara.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Quick Recap
&lt;/h2&gt;

&lt;p&gt;If you're new around here or just need a quick memory jog, Ostara is your go-to solution for managing and monitoring Spring Boot Actuator-enabled microservices. &lt;/p&gt;

&lt;p&gt;With a primary focus on simplicity and user-friendliness, Ostara provides you with real-time insights into the health and performance of your microservices, allowing you to monitor critical metrics such as CPU and memory usage. &lt;/p&gt;

&lt;p&gt;For more information, see my &lt;a href="https://dev.to/krud/introducing-ostara-3o6b"&gt;previous article&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Metric Notifications
&lt;/h2&gt;

&lt;p&gt;Managing microservices can get a tad complex, and that's where Ostara's new feature comes into play - Metric Notifications. Let's take a deep dive into this key update in version 0.10.0.&lt;/p&gt;

&lt;p&gt;Metric Notifications in Ostara serves as your personalized alarm system, alerting you when something goes amiss with your metrics. This feature introduces a level of proactive monitoring that is set to redefine how you interact with your metrics data.&lt;/p&gt;

&lt;p&gt;In the Metric Notifications interface, you can now create custom alert rules for your application metrics. Once these rules are in place, Ostara will monitor your instances for metric updates and evaluate them, notifying you if the value has crossed the threshold that was set.&lt;/p&gt;

&lt;p&gt;You can define the metric you wish to monitor and set the trigger value. Ostara currently supports two types of rules:&lt;/p&gt;

&lt;h4&gt;
  
  
  Simple rule
&lt;/h4&gt;

&lt;p&gt;Monitors a single metric and triggers when the metric crosses your defined trigger value.&lt;/p&gt;

&lt;h4&gt;
  
  
  Relative rule
&lt;/h4&gt;

&lt;p&gt;Tracks the relative value between two metrics, triggering when this value crosses your defined trigger value. For instance, you can set a rule for free disk space on your instance, where the first metric is disk.free and the relative value is disk.total. You can set a trigger for when the relative value drops below 20%.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3AcPTHBa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qjuz0y028svubnccqyi0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3AcPTHBa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qjuz0y028svubnccqyi0.gif" alt="Relative rule" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's talk about how Ostara evaluates these rules. Ostara provides three comparison operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lower than '&amp;lt;': Triggers a notification if the metric value (or relative value) falls below the trigger value.&lt;/li&gt;
&lt;li&gt;Greater than '&amp;gt;': Triggers a notification if the metric value (or relative value) exceeds the trigger value.&lt;/li&gt;
&lt;li&gt;Between: Triggers a notification if the metric value (or relative value) falls within the set trigger values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this is all too confusing and you're just looking to play around with the new rules, we've also added &lt;strong&gt;Predefined Rules&lt;/strong&gt; that will allow you to instantly create a variety of default rules to play around with;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GVw6Er_7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/631lwizpdh1fpeh1hun8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GVw6Er_7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/631lwizpdh1fpeh1hun8.gif" alt="Predefined rules" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more information, visit &lt;a href="https://docs.ostara.dev/features/application-features/monitor/metric-notifications"&gt;Metric Notifications&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  All The Other Goodies in Version 0.10.0
&lt;/h2&gt;

&lt;p&gt;We've managed to achieve quite a lot in this version, here are some of the other features you will encounter:&lt;/p&gt;

&lt;h3&gt;
  
  
  Application Health Notifications
&lt;/h3&gt;

&lt;p&gt;This feature sends immediate alerts if your application's health status changes. It's designed to help you react quickly to potential issues, reducing manual monitoring.&lt;/p&gt;

&lt;h3&gt;
  
  
  Notification settings
&lt;/h3&gt;

&lt;p&gt;With the addition of OS level notifications, we've also added the option to turn them off completely in Settings, or just their sound.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5r6r0dIn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hk1qznj9ir1h5mva96eg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5r6r0dIn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hk1qznj9ir1h5mva96eg.png" alt="Notification Settings" width="626" height="876"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Global, App and Folder Dashboard
&lt;/h3&gt;

&lt;p&gt;There are three new dashboards for you to explore - the Global Dashboard, the App Dashboard and the Folder Dashboard. These dashboards provide a concise overview of the status of your applications and folders. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JfuYcypQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b0w9bxvtju8yq68o6eu3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JfuYcypQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b0w9bxvtju8yq68o6eu3.png" alt="Global Dashboard" width="800" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Export/Import Configurations
&lt;/h3&gt;

&lt;p&gt;For those who manage multiple systems, want a backup of your configuration, or want to share your configurations with your friends and colleagues, you can now export and import Ostara configurations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Instance Shutdown
&lt;/h3&gt;

&lt;p&gt;We've added support for the shutdown capability on Actuator, allowing you to shutdown your instances directly from Ostara;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pyc9bEf_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/32s3zp4rolbba75cxwx4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pyc9bEf_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/32s3zp4rolbba75cxwx4.gif" alt="Shutdown example" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And a lot more! You can find the full changelog at the end of this post.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Start with Ostara
&lt;/h3&gt;

&lt;p&gt;If you're ready to dive into Ostara 0.10.0, head over to our &lt;a href="https://ostara.dev"&gt;website&lt;/a&gt;, download the version for your OS, and follow the &lt;a href="https://docs.ostara.dev/getting-started/quick-start"&gt;Quick Start guide&lt;/a&gt;. You'll be up and monitoring in no time!&lt;/p&gt;

&lt;h3&gt;
  
  
  Contributions
&lt;/h3&gt;

&lt;p&gt;Ostara is in pre release so we would greatly appreciate any feedback, recommendations and/or requests as well as any contributions. We would also love to hear from other Spring Boot developers. Head to the &lt;a href="https://github.com/krud-dev/ostara"&gt;repository&lt;/a&gt; to participate and keep an eye out for our upcoming Beta program!&lt;/p&gt;

&lt;h3&gt;
  
  
  Links
&lt;/h3&gt;

&lt;p&gt;Changelog: &lt;a href="https://docs.ostara.dev/getting-started/changelog"&gt;https://docs.ostara.dev/getting-started/changelog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ostara home: &lt;a href="https://ostara.dev"&gt;https://ostara.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ostara repository: &lt;a href="https://github.com/krud-dev/ostara"&gt;https://github.com/krud-dev/ostara&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ostara documentation: &lt;a href="https://docs.ostara.dev/"&gt;https://docs.ostara.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Join us on Discord! &lt;a href="https://discord.gg/8pUtGUYncD"&gt;https://discord.gg/8pUtGUYncD&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>opensource</category>
      <category>discuss</category>
      <category>devops</category>
    </item>
    <item>
      <title>Introducing Ostara</title>
      <dc:creator>Idan Elhalwani</dc:creator>
      <pubDate>Tue, 16 May 2023 13:09:11 +0000</pubDate>
      <link>https://dev.to/krud/introducing-ostara-3o6b</link>
      <guid>https://dev.to/krud/introducing-ostara-3o6b</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--POLUvm7M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x8xpnsrv87hpb9pp8qr8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--POLUvm7M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x8xpnsrv87hpb9pp8qr8.png" alt="Ostara UI" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(A previous version of this article introduced Ostara under its previous name, Boost, the article has been amended to reflect this)&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Ostara
&lt;/h2&gt;

&lt;p&gt;Ostara is a modern tool for managing and monitoring actuator-enabled microservices that aims to make the process more user-friendly and straightforward. &lt;/p&gt;

&lt;p&gt;One of our main goals with Ostara was to create a tool that just works out of the box, without needing anything besides a functioning Actuator API on the other end.&lt;/p&gt;

&lt;p&gt;Ostara allows you to gain insights into the performance and health of your microservices by providing real-time monitoring of critical metrics such as CPU and memory usage.&lt;/p&gt;

&lt;p&gt;One of the key benefits of Ostara is its simplicity. The tool is designed to be easy to use and requires minimal setup. All you need is a running instance of your microservice with Actuator enabled, and you can start monitoring and managing it with Ostara.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;The first question to ask is &lt;strong&gt;&lt;u&gt;why even use Ostara, when excellent tools such as Spring Boot Admin already exist?&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As Spring Boot Admin users, we had to ask ourselves this question before embarking on the development journey of Ostara.&lt;/p&gt;

&lt;p&gt;For all its greatness, one thing Spring Boot Admin that cannot be said about Spring Boot Admin is that it's plug and play or 'off-the-shelf'.&lt;/p&gt;

&lt;p&gt;To setup Spring Boot Admin, we start by having to create Spring project for the server itself (In our case, which is true for many, also meant we have to setup a full CI/CD flow, complete with Helm charts and Docker images in order to create a full production flow)&lt;/p&gt;

&lt;p&gt;If we needed additional features such as authentication, notifications and so on, we would need to add them directly to the project. &lt;/p&gt;

&lt;p&gt;All of this, despite the infinite versatility it offers (because it is essentially a blank slate), raises the startup costs of Spring Boot Admin considerably and even more so when you remember that you have to continually maintain this project as with any other project within your code ecosystem, either due to security updates to unrelated dependencies you may have needed to add, or in order to update Spring to match your main project(s).&lt;/p&gt;

&lt;p&gt;But aren't there ready-made images of Spring Boot Admin Server? A quick Google search will show a few (often outdated) pre-built ones that people in the community have created for different scenarios, including this official &lt;code&gt;codecentric/spring-boot-admin&lt;/code&gt; Docker image which states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This repository contains pre-build Docker Images containing basic and hence not production-ready builds of Spring Boot Admin.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now onto the client, in order to register instances on Spring Boot Admin, you have to add the &lt;code&gt;spring-boot-admin-starter-client&lt;/code&gt; dependency to your app and point it at the admin server. From personal production experience in mature projects, this isn't always a pleasant, straightforward experience.&lt;/p&gt;

&lt;p&gt;If your project guards Actuator's endpoints with Spring Security, you also have to configure the client to send the server the credentials it will need when registering itself.&lt;/p&gt;

&lt;p&gt;Alternatively, if you use Spring Cloud Discovery within your ecosystem you will be able to use that in order to discover instances, dependency free, but not hassle free, as you will again have to add this to your server's project and configure on both ends.&lt;/p&gt;

&lt;p&gt;The second part is performance. Spring Boot Admin lacks in a lot of areas when it comes to performance. The simplest example is the Thread Dump page, where if you stick around long enough without refreshing, it will eventually crash your tab.&lt;/p&gt;

&lt;p&gt;With Ostara, we aimed for a solution that just &lt;em&gt;works&lt;/em&gt; performantly with your existing setups, no matter their size &lt;br&gt;
 or scale and without requiring any prior modifications in your code or environment with the only prerequisite being the presence of Spring Actuator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature Overview
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A robust and user-friendly UI for an ever-growing list of Actuator endpoints (&lt;a href="https://docs.ostara.dev/features/instance-features/insights"&gt;Full list&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Health monitoring of your applications and their individual instances&lt;/li&gt;
&lt;li&gt;Neatly organize your applications and instances into different folders, with color coding and unique icons&lt;/li&gt;
&lt;li&gt;Modify the loggers of your applications and individual instances on the fly&lt;/li&gt;
&lt;li&gt;Evict caches from applications and individual instances on the fly&lt;/li&gt;
&lt;li&gt;View cache statistics&lt;/li&gt;
&lt;li&gt;View HTTP request statistics&lt;/li&gt;
&lt;li&gt;Bean dependency visualization&lt;/li&gt;
&lt;li&gt;Spring Integration Graph visualization&lt;/li&gt;
&lt;li&gt;Application Security built in, interact with your secured Actuator instances with no extra code&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Future
&lt;/h2&gt;

&lt;p&gt;Some of our planned features for future releases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Service discovery support&lt;/li&gt;
&lt;li&gt;Notifications&lt;/li&gt;
&lt;li&gt;Custom themes&lt;/li&gt;
&lt;li&gt;A plugin ecosystem for custom Actuator endpoints&lt;/li&gt;
&lt;li&gt;Support for non-official actuator endpoints, such as &lt;a href="https://www.togglz.org/documentation/spring-boot-starter.html"&gt;Togglz&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Native support for non-Spring Actuator facades such as &lt;a href="https://gitlab.com/mikeyGlitz/gohealth"&gt;gohealth&lt;/a&gt;, &lt;a href="https://github.com/rcruzper/express-actuator"&gt;express-actuator&lt;/a&gt; and &lt;a href="https://github.com/SolarEdgeTech/pyctuator"&gt;pyctuator&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting up Ostara
&lt;/h2&gt;

&lt;p&gt;Setting up Ostara is super simple, simply head over and download the &lt;a href="https://github.com/krud-dev/ostara/releases/latest"&gt;latest release&lt;/a&gt; for your OS and follow the &lt;a href="https://docs.ostara.dev/getting-started/quick-start"&gt;Quick Start&lt;/a&gt; to create your first instance and begin monitoring with Ostara&lt;/p&gt;

&lt;h2&gt;
  
  
  Contributions
&lt;/h2&gt;

&lt;p&gt;Ostara is in pre release so we would greatly appreciate any feedback, recommendations and/or requests as well as any contributions. We would also love to hear from other Spring Boot developers. Head to the &lt;a href="https://github.com/krud-dev/ostara"&gt;repository&lt;/a&gt; to participate!&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Ostara home: &lt;a href="https://ostara.dev"&gt;https://ostara.dev&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ostara repository: &lt;a href="https://github.com/krud-dev/ostara"&gt;https://github.com/krud-dev/ostara&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ostara documentation: &lt;a href="https://docs.ostara.dev/"&gt;https://docs.ostara.dev/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>spring</category>
      <category>devops</category>
      <category>java</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Spring Boot + Electron, a case study</title>
      <dc:creator>Idan Elhalwani</dc:creator>
      <pubDate>Mon, 15 May 2023 11:45:08 +0000</pubDate>
      <link>https://dev.to/krud/spring-boot-electron-a-case-study-2p75</link>
      <guid>https://dev.to/krud/spring-boot-electron-a-case-study-2p75</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;We recently finished writing our desktop app for Spring Actuator, &lt;a href="https://github.com/krud-dev/ostara/" rel="noopener noreferrer"&gt;Ostara&lt;/a&gt;. Initially, we decided to rely on Electron's main process and write our "backend" in Node. We quickly hit roadblock after roadblock, until a decision was made to ditch the backend entirely, rewrite it in Spring Boot and Kotlin in the JVM ecosystem, and have the renderer communicate with it via REST.&lt;/p&gt;

&lt;p&gt;We did this for a multitude of reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First and foremost, we wanted the versatility of being able to run the project on and off Electron, and possibly with a remote backend. Our initial Node implementation relied heavily on IPC between the main and renderer and we knew that, for the most part, had to go.&lt;/li&gt;
&lt;li&gt;It's a mature and robust ecosystem, and especially one where we knew we would be able to make rapid progress&lt;/li&gt;
&lt;li&gt;We would be able to leverage our own JVM libraries, namely &lt;a href="https://shapeshift.krud.dev/" rel="noopener noreferrer"&gt;ShapeShift&lt;/a&gt; and a yet-unreleased framework we use for CRUD operations with traditional ORMs and ODMs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ecosystem Overview
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/krud-dev/ostara/" rel="noopener noreferrer"&gt;Ostara&lt;/a&gt; is based off of &lt;a href="https://github.com/electron-react-boilerplate/electron-react-boilerplate" rel="noopener noreferrer"&gt;electron-react-boilerplate&lt;/a&gt; and uses &lt;a href="https://www.electron.build/" rel="noopener noreferrer"&gt;electron-builder&lt;/a&gt; to package the application.&lt;/p&gt;

&lt;p&gt;The daemon uses JDK 17 with Kotlin, Spring Boot and Gradle&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Daemon
&lt;/h2&gt;

&lt;p&gt;Before we set out to research and implement this daemon for Ostara, we laid out a list of requirements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A user should not need to install Java.&lt;/li&gt;
&lt;li&gt;No significant downgrades to the developer experience.&lt;/li&gt;
&lt;li&gt;The daemon process should be robust and resilient.&lt;/li&gt;
&lt;li&gt;Support two-way communication in a manner that is similar to IPC, but doesn't tie us to Electron.&lt;/li&gt;
&lt;li&gt;The startup time for the daemon should be under 20 seconds at all times.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's break these down.&lt;/p&gt;

&lt;h3&gt;
  
  
  A user should not need to install Java
&lt;/h3&gt;

&lt;p&gt;The rationale here is simple, right? The user installed your app, they don't really care about your app's dependencies, and they certainly don't want to be given (either automatically or otherwise) a shopping list before they can use it. &lt;/p&gt;

&lt;p&gt;Now, this may sound like a silly argument to make when you realize Ostara's primary target audience is &lt;em&gt;JVM developers&lt;/em&gt; who certainly have JDK on their workstation. But &lt;em&gt;which&lt;/em&gt; JDK? Spring Boot developers come in all shapes and sizes, some will still run JDK 8 on their workstation while others will be on the cutting edge.&lt;/p&gt;

&lt;p&gt;Overall, the goal of this requirement was to reduce our footprint and (visible) overhead as much as possible while allowing maximum versatility.&lt;/p&gt;

&lt;p&gt;Now right off the bat, let me just say that an alternative to this process called &lt;a href="https://docs.oracle.com/javase/9/tools/jlink.htm" rel="noopener noreferrer"&gt;jlink&lt;/a&gt; exists. We opted not to use it, so I will not elaborate on it further.&lt;/p&gt;

&lt;p&gt;The app is packaged 4 times, once for Windows (x64), once for Linux (x64), and twice for Mac (ARM and x64). Each one of these has its own unique JDK.&lt;/p&gt;

&lt;p&gt;The goal would be to download the respective JDK, where it would eventually find its way inside the finished package for each operating system and architecture.&lt;/p&gt;

&lt;p&gt;An additional goal we set was to avoid bloating the repository with zip files that we can easily download on the spot and being forced to use Git LFS, so committing the JDKs was not an option.&lt;/p&gt;

&lt;p&gt;To achieve the procurement part, we wrote &lt;a href="https://github.com/krud-dev/ostara/blob/master/devops/jdkutil.py" rel="noopener noreferrer"&gt;jdkutil&lt;/a&gt;, a pure Python tool with no external dependencies.&lt;/p&gt;

&lt;p&gt;The tool is very simple in its operation. Given a list of categorized URLs (In our case, &lt;a href="https://github.com/krud-dev/ostara/blob/master/devops/jdks.csv" rel="noopener noreferrer"&gt;this csv&lt;/a&gt;), it will download them, verify the checksum matches, and unzip them into a directory tree matching this pattern: &lt;code&gt;{platform}/{arch}/jdk&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As a visual example, for the four variants above we will receive the following tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jdks/
├── linux
│   └── x64
│       └── jdk
├── mac
│   ├── arm64
│   │   └── jdk
│   └── x64
│       └── jdk
└── windows
    └── x64
        └── jdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the JDKs were ready in this format, all we had to do was add the following to the &lt;code&gt;extraResources&lt;/code&gt; block of the &lt;code&gt;build&lt;/code&gt; section within our &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"extraResources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jdks/${os}/${arch}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"filter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"**/*"&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;electron-builder&lt;/code&gt; runs, it will &lt;a href="https://www.electron.build/file-patterns#file-macros" rel="noopener noreferrer"&gt;populate&lt;/a&gt; &lt;code&gt;${os}&lt;/code&gt; and &lt;code&gt;${arch}&lt;/code&gt; according to the operating system and architecture being built, so at the end of this process we should have an arch specific, OS specific folder called &lt;code&gt;jdk&lt;/code&gt; in every package that we create, with the correct JDK for the designated platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  No significant downgrades to the developer experience
&lt;/h3&gt;

&lt;p&gt;While a developer is expected to have JDK 17 installed, if they are only working on the Electron side there should be no additional steps to run or perform.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setup
&lt;/h4&gt;

&lt;p&gt;A "frontend" developer shouldn't need to setup a working environment to work on the daemon, but they will still need to be able to run the current development version and build it from scratch.&lt;/p&gt;

&lt;p&gt;Likewise, a "backend" developer should be able to run their daemon from their IDE of choice and be able to hook it up to the process.&lt;/p&gt;

&lt;p&gt;Finally, in a packaged state we will have a jar as well as a custom JDK that we will need to use.&lt;/p&gt;

&lt;p&gt;This lead us to split the way we start the daemon into two ways.&lt;/p&gt;

&lt;p&gt;The first is the "Packaged" approach, where Electron already knows the location of a prebuilt JAR and simply runs the process. &lt;/p&gt;

&lt;p&gt;The second is the "Remote" approach. In this approach, Electron doesn't actually start the process, but simply receives a predetermined port and address (Usually localhost) and creates a connection with the daemon over HTTP.&lt;/p&gt;

&lt;p&gt;The remote approach covers both development use-cases. In order to achieve this, we split our &lt;code&gt;start&lt;/code&gt; command into two:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"concurrently &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;npm run start:daemon&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;  &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;ts-node ./.erb/scripts/check-port-in-use.js &amp;amp;&amp;amp; npm run start:renderer&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start:thin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ts-node ./.erb/scripts/check-port-in-use.js &amp;amp;&amp;amp; npm run start:renderer"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A "frontend" developer in this case would run &lt;code&gt;start&lt;/code&gt;, which would then in turn compile and run the daemon locally. Since the app isn't packaged, the app will automatically determine that it needs to use a Remote daemon with the default host and port.&lt;/p&gt;

&lt;p&gt;A "backend" developer would run &lt;code&gt;start:thin&lt;/code&gt; which essentially does everything except start the daemon, with the expectation that the daemon is already running. Like the previous example, the app will automatically determine that it needs to use a Remote daemon with the default host and port.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementing health checks
&lt;/h4&gt;

&lt;p&gt;Since the Daemon, like any process had the possibility of crashing or freezing, the next step was to implement health checks. We opted for a simple polling HTTP health check from the Electron main process to the daemon.&lt;/p&gt;

&lt;p&gt;For this process we created 3 events in the Electron main process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;daemon-ready&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;daemon-healthy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;daemon-unhealthy&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The flow created around these events is simple.&lt;/p&gt;

&lt;p&gt;Upon app start, the user will be sent to the splash screen. Once the &lt;code&gt;daemon-ready&lt;/code&gt; event is fired, the splash screen is closed and is replaced by the main screen. If at any point during this time we receive the &lt;code&gt;daemon-unhealthy&lt;/code&gt; event, the user's screen is replaced with the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu4fuwl01gujitj04tj2r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu4fuwl01gujitj04tj2r.png" alt="Example of crashed daemon"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If, during this time, &lt;code&gt;daemon-healthy&lt;/code&gt; is fired, then the screen returns to normal.&lt;/p&gt;

&lt;h4&gt;
  
  
  Support two-way communication in a manner that is similar to IPC, but doesn't tie us to Electron
&lt;/h4&gt;

&lt;p&gt;To achieve two-way communication between the Electron renderer and the daemon, we opted to use Websockets with the STOMP protocol. This approach decoupled the communication between the renderer and the daemon from the Electron framework, allowing for greater flexibility in the future and the ability to break away from Electron entirely if needed&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In conclusion, despite the unorthodox choice, we successfully developed a robust and resilient daemon for our Electorn app using Spring Boot, all while addressing our primary goals.&lt;/p&gt;

&lt;p&gt;By doing so, we have created a flexible and scalable app that can run on and off Electron with the potential for remote backend functionality. Additionally, we have opened the door for further expansion and improvements in the future, should the need arise.&lt;/p&gt;

</description>
      <category>electron</category>
      <category>springboot</category>
      <category>kotlin</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Strategy Design Pattern with Spring Boot + Kotlin - Cleaner code with no boilerplate</title>
      <dc:creator>Aviv Mor</dc:creator>
      <pubDate>Thu, 02 Mar 2023 09:48:50 +0000</pubDate>
      <link>https://dev.to/krud/strategy-design-pattern-with-spring-boot-kotlin-cleaner-code-with-no-boilerplate-2id1</link>
      <guid>https://dev.to/krud/strategy-design-pattern-with-spring-boot-kotlin-cleaner-code-with-no-boilerplate-2id1</guid>
      <description>&lt;h1&gt;
  
  
  The Strategy Pattern
&lt;/h1&gt;

&lt;p&gt;If you already know the strategy pattern just jump here.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is it?
&lt;/h2&gt;

&lt;p&gt;According to &lt;a href="https://en.wikipedia.org/wiki/Strategy_pattern" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt;, the strategy pattern is a behavioral software design pattern that enables selecting an algorithm at runtime. Instead of implementing a single algorithm directly, code receives run-time instructions as to which in a family of algorithms to use.&lt;/p&gt;

&lt;p&gt;In simple words, the strategy pattern is used to specify how something should be done by providing a specific algorithm.&lt;br&gt;
For example, a strategy for payment could be Credit Card, PayPal, or any other payment provider.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why should we use it?
&lt;/h2&gt;

&lt;p&gt;The Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it (&lt;a href="https://fjp.at/design-patterns/strategy" rel="noopener noreferrer"&gt;source&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In short, it makes our code cleaner, easier to maintain, and reusable.&lt;/p&gt;
&lt;h1&gt;
  
  
  The Strategy Pattern in Code
&lt;/h1&gt;

&lt;p&gt;Implementations of the pattern consist of an interface defining the strategy, multiple concrete implementations of the strategy and a context using the strategy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2F4%2F45%2FW3sDesign_Strategy_Design_Pattern_UML.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2F4%2F45%2FW3sDesign_Strategy_Design_Pattern_UML.jpg" alt="Strategy Pattern UML Diagram"&gt;&lt;/a&gt;&lt;/p&gt;
By Vanderjoe - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=60733582


&lt;h2&gt;
  
  
  Code Example
&lt;/h2&gt;

&lt;p&gt;Let's look at the following simplified scenario:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have an application with users and we need to send them verification codes for 2FA. &lt;/li&gt;
&lt;li&gt;The application supports multiple communication options for receiving the verification code: Email, SMS, Notifications...&lt;/li&gt;
&lt;li&gt;Each user selects its preferred communication method.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First we will define our strategy interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;VerificationCodeCommunicationStrategy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendVerificationCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's add our implementations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailCommunicationStrategy&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;VerificationCodeCommunicationStrategy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendVerificationCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;emailClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Verification code"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Your verification is $code."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SmsCommunicationStrategy&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;VerificationCodeCommunicationStrategy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendVerificationCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;smsClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendSMS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Your verification is $code."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All that's left is to use the strategy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CommunicationMethod&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SMS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VerificationCodeService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;verificationCodeStrategyMap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CommunicationMethod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;VerificationCodeCommunicationStrategy&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mapOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;CommunicationMethod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Email&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nc"&gt;EmailCommunicationStrategy&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nc"&gt;CommunicationMethod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SMS&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nc"&gt;SmsCommunicationStrategy&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendVerificationCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;code&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateVerificationCode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;verificationCodeStrategy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;verificationCodeStrategyMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;preferredCommunicationMethod&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;verificationCodeStrategy&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;sendVerificationCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see how the code is clean and easy to maintain. Adding a new communication method would be easy and will not need to change existing code other than adding it to the map of strategies.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Library
&lt;/h1&gt;

&lt;p&gt;We use the strategy pattern a-looot in our projects. Moreover, like all developers we are lazy and want to make our life as easy as possible. This is why we created our &lt;a href="https://github.com/krud-dev/spring-componentmap" rel="noopener noreferrer"&gt;library&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Example WITHOUT the library
&lt;/h2&gt;

&lt;p&gt;Let's revise the previous example for a regular Spring Boot implementation.&lt;/p&gt;

&lt;p&gt;When using the strategy pattern in a Spring Boot application the context and strategy implementations are usually Spring components.&lt;/p&gt;

&lt;p&gt;We will start with the strategies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;VerificationCodeCommunicationStrategy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendVerificationCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailCommunicationStrategy&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;VerificationCodeCommunicationStrategy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendVerificationCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;emailClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Verification code"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Your verification is $code."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SmsCommunicationStrategy&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;VerificationCodeCommunicationStrategy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendVerificationCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;smsClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendSMS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Your verification is $code."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interface remains the same and the implementations receive the &lt;code&gt;@Component&lt;/code&gt; annotation.&lt;/p&gt;

&lt;p&gt;Now let's move on to the verification service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VerificationCodeServiceImpl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;emailCommunicationStrategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;EmailCommunicationStrategy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;smsCommunicationStrategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;SmsCommunicationStrategy&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;verificationCodeStrategyMap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CommunicationMethod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;VerificationCodeCommunicationStrategy&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mapOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;CommunicationMethod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Email&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;emailCommunicationStrategy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;CommunicationMethod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SMS&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;smsCommunicationStrategy&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendVerificationCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;code&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateVerificationCode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;verificationCodeStrategy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;verificationCodeStrategyMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;preferredCommunicationMethod&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;verificationCodeStrategy&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;sendVerificationCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to add the strategy implementations to the constructor and build the map manually. That's no fun!&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Example WITH the library
&lt;/h2&gt;

&lt;p&gt;The entire objective of the library is to make our life easier and the code cleaner and less bug prone. It does it by simply building the strategy map automatically.&lt;/p&gt;

&lt;p&gt;We will start by modifying the strategy interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;VerificationCodeCommunicationStrategy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;ComponentMapKey&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;CommunicationMethod&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendVerificationCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see we have added a new field &lt;code&gt;method&lt;/code&gt; with the annotation &lt;code&gt;@ComponentMapKey&lt;/code&gt;. This informs the library which field is the key for the strategy map.&lt;/p&gt;

&lt;p&gt;Let's update the implementations according to the modified interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailCommunicationStrategy&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;VerificationCodeCommunicationStrategy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;method&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CommunicationMethod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Email&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendVerificationCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;emailClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Verification code"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Your verification is $code."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SmsCommunicationStrategy&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;VerificationCodeCommunicationStrategy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;method&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CommunicationMethod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SMS&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendVerificationCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;smsClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendSMS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Your verification is $code."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's modify the service to use the library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VerificationCodeServiceImpl&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@ComponentMap&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;lateinit&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;verificationCodeStrategyMap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CommunicationMethod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;VerificationCodeCommunicationStrategy&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendVerificationCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;code&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateVerificationCode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;verificationCodeStrategy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;verificationCodeStrategyMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;preferredCommunicationMethod&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;verificationCodeStrategy&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;sendVerificationCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! All we had to do is to add the &lt;code&gt;@ComponentMap&lt;/code&gt; annotation to the strategy map and voila! The map is built automatically from the components. No boiler-plate code. To add a new strategy all you need to do is to create a new implementation and it will be "magically" added to all relevant strategy maps.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final Words
&lt;/h1&gt;

&lt;p&gt;This &lt;a href="https://github.com/krud-dev/spring-componentmap" rel="noopener noreferrer"&gt;library&lt;/a&gt; is the most used library in our projects. Although it's not life changing, it's just useful, helps us keep our code clean and prevents lots of recurring bugs from forgetting to add new strategies to their appropriate maps.&lt;/p&gt;

&lt;p&gt;If you would like to use it you can start with the &lt;a href="https://componentmap.krud.dev/introduction/quick-start" rel="noopener noreferrer"&gt;quick start guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We develop open source because we love it and want to contribute to the cause. If you would like to support us please consider starring &lt;a href="https://github.com/krud-dev/spring-componentmap" rel="noopener noreferrer"&gt;the repository&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>architecture</category>
      <category>oop</category>
      <category>spring</category>
    </item>
    <item>
      <title>Introducing ShapeShift: A lightweight, modular, performant and extensible object mapping library for Kotlin/Java</title>
      <dc:creator>Aviv Mor</dc:creator>
      <pubDate>Wed, 12 Oct 2022 12:07:23 +0000</pubDate>
      <link>https://dev.to/krud/introducing-shapeshift-a-lightweight-modular-performant-and-extensible-object-mapping-library-for-kotlinjava-2cl1</link>
      <guid>https://dev.to/krud/introducing-shapeshift-a-lightweight-modular-performant-and-extensible-object-mapping-library-for-kotlinjava-2cl1</guid>
      <description>&lt;h1&gt;
  
  
  WHY
&lt;/h1&gt;

&lt;h2&gt;
  
  
  The short answer
&lt;/h2&gt;

&lt;p&gt;We needed a simple to use, minimal boiler plate mapping engine, that is also flexible and supports the most advanced use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  The long answer
&lt;/h2&gt;

&lt;p&gt;A few years ago we got tired of developing the same boiler plate code for CRUD and decided to develop a generic CRUD framework.&lt;/p&gt;

&lt;p&gt;As a part of this framework we needed an object mapping library and could not find one that answered all of our requirements.&lt;/p&gt;

&lt;p&gt;The first iteration of the library was part of the entire CRUD framework. However, some time ago we decided we want to start contributing to the open source community and we thought "What is the best way to contribute if not to release our CRUD framework?". The issue with this thought is that the framework is huge and contains lots of code, polishing it and getting it ready to be published as open source would take a lot of time (documentation anyone?).&lt;/p&gt;

&lt;p&gt;Our solution was to separate the framework into multiple smaller libraries we can polish and publish in smaller time frames. The first of these libraries is &lt;a href="https://shapeshift.krud.dev/"&gt;ShapeShift&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  WHAT
&lt;/h1&gt;

&lt;h2&gt;
  
  
  The short answer
&lt;/h2&gt;

&lt;p&gt;ShapeShift will help you transform object of type A to object of type B easily, fast and without boiler plate code.&lt;/p&gt;

&lt;p&gt;ShapeShift main features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto mapping&lt;/li&gt;
&lt;li&gt;Custom field transformers&lt;/li&gt;
&lt;li&gt;Default transformers&lt;/li&gt;
&lt;li&gt;Deep mapping&lt;/li&gt;
&lt;li&gt;Multiple mapping targets&lt;/li&gt;
&lt;li&gt;Conditional mapping&lt;/li&gt;
&lt;li&gt;Mapping decorators&lt;/li&gt;
&lt;li&gt;Seamless spring integration&lt;/li&gt;
&lt;li&gt;Native Kotlin DSL API&lt;/li&gt;
&lt;li&gt;Java builder API&lt;/li&gt;
&lt;li&gt;Annotations API&lt;/li&gt;
&lt;li&gt;Native Android support&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The longer answer
&lt;/h2&gt;

&lt;p&gt;ShapeShift's job seems simple, convert object of type A to object of type B. But to do its job in the best way possible, the library offers lots of features, to name a few: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://shapeshift.krud.dev/features/auto-mapping"&gt;Advanced auto mapping&lt;/a&gt; - Automatically map fields with the same name from the source object to the target object. Control wether to map only fields of the same type or use the advanced &lt;a href="https://shapeshift.krud.dev/features/transformers#default-transformers"&gt;default transformers&lt;/a&gt; feature to auto map fields of different types!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://shapeshift.krud.dev/guides/spring-usage"&gt;Seamless Spring integration&lt;/a&gt; - ShapeShift's Spring Boot library allows to integrate it with Spring easily. Use Spring's power to create custom transformers beans with access to DB or other resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More about the advanced features with code examples is available in &lt;a href="https://dev.to/krud/object-mapping-advanced-features-qol-with-kotlin-5dgn"&gt;Kotlin version&lt;/a&gt; and &lt;a href="https://dev.to/krud/object-mapping-advanced-features-qol-with-java-43m9"&gt;Java version&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  HOW
&lt;/h1&gt;

&lt;h2&gt;
  
  
  The short answer
&lt;/h2&gt;

&lt;p&gt;ShapeShift supports multiple APIs to configure your mappings.&lt;br&gt;
&lt;a href="https://shapeshift.krud.dev/api-documentation/annotations"&gt;Annotations&lt;/a&gt;, &lt;a href="https://shapeshift.krud.dev/api-documentation/dsl"&gt;Kotlin DSL&lt;/a&gt; and &lt;a href="https://shapeshift.krud.dev/api-documentation/java-builder"&gt;Java Builder&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The long answer
&lt;/h2&gt;

&lt;p&gt;ShapeShift's documentation is available &lt;a href="https://shapeshift.krud.dev/"&gt;here&lt;/a&gt;. You can check our &lt;a href="https://shapeshift.krud.dev/introduction/quick-start"&gt;Quick Start&lt;/a&gt; guide to get it up and running in 5 minutes.&lt;/p&gt;

&lt;p&gt;Built with &lt;strong&gt;Kotlin&lt;/strong&gt; in mind, ShapeShift was designed around its ecosystem and best practices. The library APIs for mapping with Kotlin:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://shapeshift.krud.dev/api-documentation/annotations"&gt;Annotations&lt;/a&gt; - Fully featured annotation based mapping, just add annotations to your objects and ShapeShift handles the rest. Including using custom field transformers, conditional mapping, advanced object decoration and much more.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://shapeshift.krud.dev/api-documentation/dsl"&gt;Kotlin DSL&lt;/a&gt; - Allowing you to define the relations between objects. This allows you to map objects you can't change (or don't want to), like objects from 3rd party libraries. Additionally you can define inline transformations, conditions and decorations, enabling deep customization and very advanced mapping.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ShapeShift also has full &lt;strong&gt;Java&lt;/strong&gt; support available with multiple APIs for mapping:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://shapeshift.krud.dev/api-documentation/annotations"&gt;Annotations&lt;/a&gt; - Same API as Kotlin with full Java support.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://shapeshift.krud.dev/api-documentation/java-builder"&gt;Java Builder&lt;/a&gt; - The equivalent Java API for the Kotlin DSL. Allowing you to define the relations between objects without modifying their code, and map objects you can't change (or don't want to).&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Final words
&lt;/h1&gt;

&lt;p&gt;We poured our love, time, knowledge and what not into ShapeShift. I'm proud of the result and our greatest achievement is to be able to help others with their work.&lt;/p&gt;

&lt;p&gt;If you would like to contribute, please feel free to open issues, join as a contributor or star the &lt;a href="https://github.com/krud-dev/shapeshift/"&gt;repository&lt;/a&gt;. Thanks in advance!&lt;/p&gt;

</description>
      <category>java</category>
      <category>kotlin</category>
      <category>opensource</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Good code is like an onion, it has layers</title>
      <dc:creator>TheWizKid</dc:creator>
      <pubDate>Tue, 11 Oct 2022 13:17:39 +0000</pubDate>
      <link>https://dev.to/krud/good-code-is-like-an-onion-it-has-layers-2jea</link>
      <guid>https://dev.to/krud/good-code-is-like-an-onion-it-has-layers-2jea</guid>
      <description>&lt;p&gt;The stack — Java, GWT, Mysql&lt;/p&gt;

&lt;p&gt;The Experience — 11 Years&lt;/p&gt;

&lt;p&gt;The Job — Senior Developer at Startup&lt;/p&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;h2&gt;
  
  
  Teaching some new recruits
&lt;/h2&gt;

&lt;p&gt;It was my 3rd year at the startup, things were going well, the company was growing. We needed more working hands, so like any company, we hired a new group of devs, straight off the assembly line (because why spread it out, or get someone with experience). I don't exactly remember how it came to be, but I was in charge of getting them up to speed. This was my first true taste of teaching and leading.&lt;/p&gt;

&lt;p&gt;I was always good at winging explanations, and presentations, so it was no different here. I showed them the ropes, the way things were put together, and what talked to what and how.&lt;/p&gt;

&lt;p&gt;The problem came when I needed to explain the way the code was written, and why it was written that way. We were using GWT, and for those who don't know, it allowed us to write the client code as JAVA and use the same entities as we do with the DB.&lt;/p&gt;

&lt;p&gt;To say that it was useful was an understatement, but like everything in life, this had its drawbacks. Namely everything you save in the DB is sent to the client. This could and did cause many performance issues, and looking back I'm pretty sure there were security issues stemming from this behavior. This code was not layered correctly, but I didn't quite know it yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The code that forced me to look and understand layers
&lt;/h2&gt;

&lt;p&gt;It was around this time that my friend started working on another startup, there he worked with this outsourced dev. She had written the main structure of the server code, and had very distinct layers and separation.&lt;/p&gt;

&lt;p&gt;I try not to go too deep in technical terms in these posts, but I kind of need to here. There are a few different actors in our story, and each has some specific needs and talents.&lt;/p&gt;

&lt;h3&gt;
  
  
  The DB
&lt;/h3&gt;

&lt;p&gt;The job of the DB is simple, save the objects you need to, and allow you to query them when needed. So naturally, this is where you need to think of how to save things, how they are connected to the other entities in the system, and how you are going to query them.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Server
&lt;/h3&gt;

&lt;p&gt;Its main job is to process things, take requests from the client, do some logic, and save it to the DB. This is the man in the middle, between the client and the DB.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Client
&lt;/h3&gt;

&lt;p&gt;This is where things are displayed, not everything you need to do the job needs to be displayed. Sometimes you want to display things as a mix of other things.&lt;/p&gt;

&lt;p&gt;Now I want to focus on the server, this is where my expertise is, and this is where the layers are most prevalent. It's the server's job to get tasks from the client and process them, update the DB, and send the results back for display. Let's break this down into meaningful layers.&lt;/p&gt;

&lt;p&gt;[API] ← RO (Representation Object)→ [Service] ← Entity/RO → [Handler] ←  Entity → [Dao/DB]&lt;/p&gt;

&lt;p&gt;The client does requests against the server, this is deserialized to a RO.&lt;/p&gt;

&lt;p&gt;This RO is then used by the service to do logic, this is where processes are done.&lt;/p&gt;

&lt;p&gt;The service in turn works with the handlers, where short and transactional logic can be performed. &lt;/p&gt;

&lt;p&gt;They in turn can use the DAO (Data Access Object) to persist and fetch data from the DB.&lt;/p&gt;

&lt;p&gt;I'll dig deeper into the different layers, and what they are in charge of, and why they use the Objects they do to talk to the other layers.&lt;/p&gt;

&lt;h3&gt;
  
  
  The API
&lt;/h3&gt;

&lt;p&gt;This is a facade, facing the client. Not all data needs to be transferred in order to do the requested action. For example, there could be fields on an object that are immutable, and there is no reason for the client to send them over when updating an object. Or there could be fields in the server that are only required for server logic, no reason to send them back via the API. This is why this layer works with ROs aka Representation Objects. They can have less fields, or aggregated fields, that can be used by the client.&lt;/p&gt;

&lt;p&gt;This layer should be kept as “stupid” as you can, allowing the system to have multiple different types of APIs that call the same logic. The logic is based on the Service layer, and the API calls upon that layer to achieve its goals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Service Layer
&lt;/h3&gt;

&lt;p&gt;This is where most of the business logic lives, the different processes that constitute a system. These processes can be long, and can require multiple entities within the system. It's the service layer's responsibility to map the ROs into something more useful for handling the logic.&lt;/p&gt;

&lt;p&gt;The service layer calls different Handlers, each with its own domain of responsibility to run the logic. These processes can be long, and should not be transactional (Create locks in the DB).&lt;/p&gt;

&lt;h3&gt;
  
  
  Handlers
&lt;/h3&gt;

&lt;p&gt;Handlers have very well defined responsibilities, they usually work with only 1 entity, and they are the ones that can do transactional actions. They are also the only ones that talk to the DAO/DB. &lt;/p&gt;

&lt;p&gt;As you know, DB transactions can cause locks. One of the things we strive for in good system design, is to minimize lock time and scope. This is why the handlers are separated from the services. In the handlers is where you will find the code most optimized, and single goal oriented.&lt;/p&gt;

&lt;h3&gt;
  
  
  DAO/DB
&lt;/h3&gt;

&lt;p&gt;This is where persistence occurs. This layer is similar to the API layer in that it should be as simple and “stupid” as possible. Correct implementation of this allows us to simply (relatively) change DB by just re-implementing the DAO layer.&lt;/p&gt;

&lt;p&gt;An example:&lt;/p&gt;

&lt;p&gt;Lets take for example a process of publishing a new version of a post. This process is triggered by a request from the client, all that is needed is the post_id and version_number. So we have an RO with those fields only.&lt;/p&gt;

&lt;p&gt;The process starts with some validation&lt;/p&gt;

&lt;p&gt;Does that post_id exist?&lt;/p&gt;

&lt;p&gt;Can the user requesting the publishing perform that action?&lt;/p&gt;

&lt;p&gt;Is there a version_number like that?&lt;/p&gt;

&lt;p&gt;Is it already published?&lt;/p&gt;

&lt;p&gt;You can think of some more….&lt;/p&gt;

&lt;p&gt;Now of course at the end of this, we want to transactionally update the is_published flag at the same time on the old version as the new. But during the time we are doing validations there is no reason to open a write transaction in the DB, and lock the entities. It is much better to do the validation process, call the handler just to do the swap, then continue after the transaction to create the result for the client. &lt;/p&gt;

&lt;p&gt;This way we gained a few key points.&lt;/p&gt;

&lt;p&gt;Shortest transaction time possible.&lt;/p&gt;

&lt;p&gt;No connection to DB used if the request fails in the validation phase.&lt;/p&gt;

&lt;p&gt;Code reuse - the method that publishes in the handler can later be used by different services (for example an automated time publisher).&lt;/p&gt;

&lt;p&gt;Clear single responsibilities for each layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practice what I preach
&lt;/h2&gt;

&lt;p&gt;Over the years I have honed this layered design (I will get into it in later posts), but the basics remain. This code forced me to look at my code differently, and implement the layers, and I have to tell you, this has made my code much more readable and maintainable as well. It has also increased my development speed, because I can write each layer's interface, and then start filling in the methods. &lt;/p&gt;

&lt;p&gt;I won't lie, it took me a while to get used to working this way, and even longer to get it right (I would put things in the handler that could have been in a service and split among multiple handlers), but it's a process. I urge you to try and split some code you are working on using these principals. Everyone has that 1 method that is so big that nobody wants to touch it. Go ahead, give it a go, I'm confident that after some time (and banging your head against the wall) you will be able to split it up and have much better code at the end.&lt;/p&gt;

&lt;p&gt;Please check out my &lt;a href="https://github.com/krud-dev/shapeshift/"&gt;open source library&lt;/a&gt; and maybe even star it. I would appreciate it greatly!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>career</category>
      <category>beginners</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Object Mapping advanced features &amp; QoL with Java</title>
      <dc:creator>Aviv Mor</dc:creator>
      <pubDate>Thu, 08 Sep 2022 12:04:01 +0000</pubDate>
      <link>https://dev.to/krud/object-mapping-advanced-features-qol-with-java-43m9</link>
      <guid>https://dev.to/krud/object-mapping-advanced-features-qol-with-java-43m9</guid>
      <description>&lt;p&gt;This is the Java version of the &lt;a href="https://dev.to/krud/object-mapping-advanced-features-qol-with-kotlin-5dgn"&gt;Kotlin article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When working with multi-layered applications, external libraries, a legacy code base or external APIs, we are often required to map between different objects or data structures.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will check out some Object Mapping libraries advanced features to simplify this task while saving development and maintenance time.&lt;/p&gt;

&lt;p&gt;In our examples we will use the library &lt;a href="https://github.com/krud-dev/shapeshift/"&gt;ShapeShift&lt;/a&gt;. It's a light-weight object mapping library for Java/Kotlin with lots of cool features.&lt;/p&gt;

&lt;h1&gt;
  
  
  Auto Mapping
&lt;/h1&gt;

&lt;p&gt;We will start with a bang. Auto mapping can and will save you lots of time and boiler-plate code. Some applications require manual mapping between objects, but most applications will save tons of time working on boring boiler-plate by just using this one feature. And it gets even better, with ShapeShift's default transformers we can even use automatic mapping between different data types.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple Mapping
&lt;/h2&gt;

&lt;p&gt;Let's start with a simple example for auto mapping. We have our two objects, imagine they could also have tens, hundreds, or even thousands (for the crazy people here) of fields.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Getters, Setters, Constructors, Equals...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Getters, Setters, Constructors, Equals...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to map all the field from &lt;code&gt;User&lt;/code&gt; to &lt;code&gt;UserDTO&lt;/code&gt;. Using auto mapping we don't need to write any boiler-plate code. The mapper will be defined as follow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;MappingDefinition&lt;/span&gt; &lt;span class="n"&gt;mappingDefinition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MappingDefinitionBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;autoMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AutoMappingStrategy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BY_NAME_AND_TYPE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voila! All the fields will be mapped automatically without any manual boiler-plate code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Mapping
&lt;/h2&gt;

&lt;p&gt;In this example we will use the power of &lt;a href="https://shapeshift.krud.dev/api-documentation/transformers#default-transformers"&gt;default transformers&lt;/a&gt; to take auto mapping even further.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt; &lt;span class="n"&gt;birthDate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Getters, Setters, Constructors, Equals...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;fullName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;birthDate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Getters, Setters, Constructors, Equals...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the types of the &lt;code&gt;birthDate&lt;/code&gt; field are different in the source and destination classes. But using the power of default transformers we can still use auto mapping here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;MappingDefinition&lt;/span&gt; &lt;span class="n"&gt;mappingDefinition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MappingDefinitionBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;autoMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AutoMappingStrategy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BY_NAME&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We changed the auto mapping strategy to &lt;code&gt;BY_NAME&lt;/code&gt; so it will map fields also with different types. Now we need to register a default transformer to the &lt;code&gt;ShapeShift&lt;/code&gt; instance in order for it to know how to transform &lt;code&gt;Date&lt;/code&gt; to &lt;code&gt;Long&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ShapeShift&lt;/span&gt; &lt;span class="n"&gt;shapeShift&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ShapeShiftBuilder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withTransformer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
                &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DateToLongMappingTransformer&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; 
                &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;// Default Transformer&lt;/span&gt;
        &lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also add manual mapping on top of the auto mapping in order to add/change behavior. The source and destination classes have different names for the &lt;code&gt;name&lt;/code&gt; field so we will add manual mapping for it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;MappingDefinition&lt;/span&gt; &lt;span class="n"&gt;mappingDefinition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MappingDefinitionBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;autoMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AutoMappingStrategy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BY_NAME&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"fullName"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Auto mapping is great for use cases that does not require specific mapping. It helps reduce the amount manual boiler-plate code needed to configure mapping and also helps you keep your sanity.&lt;/p&gt;

&lt;h1&gt;
  
  
  Transformers
&lt;/h1&gt;

&lt;p&gt;Transformers are very useful feature that allows you to transform the type/value of a field to a different type/value when mapping a field.&lt;/p&gt;

&lt;p&gt;Some use cases we have been using widely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transform date to long and vice versa between server and client objects.&lt;/li&gt;
&lt;li&gt;Transform JSON string to it's actual type and vice versa between server and client objects.&lt;/li&gt;
&lt;li&gt;Transform comma separated string to list of enums.&lt;/li&gt;
&lt;li&gt;Transform another object id to its object or one of its fields from the DB using Spring transformers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Basic Transformers
&lt;/h2&gt;

&lt;p&gt;We will start with a simple transformer example. Date-to-Long  and Long-to-Date transformers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DateToLongMappingTransformer&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;MappingTransformer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Nullable&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@NonNull&lt;/span&gt; &lt;span class="nc"&gt;MappingTransformerContext&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOriginalValue&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOriginalValue&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getTime&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LongToDateMappingTransformer&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;MappingTransformer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Nullable&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt; &lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@NonNull&lt;/span&gt; &lt;span class="nc"&gt;MappingTransformerContext&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOriginalValue&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOriginalValue&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All we need to do now is to &lt;a href="https://shapeshift.krud.dev/api-documentation/transformers#registering-transformers"&gt;register&lt;/a&gt; them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ShapeShift&lt;/span&gt; &lt;span class="n"&gt;shapeShift&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ShapeShiftBuilder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withTransformer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DateToLongMappingTransformer&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// "true" is optional, we are registering the transformers as default transformers, more on that later.&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withTransformer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LongToDateMappingTransformer&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! We can now use the transformers when mapping objects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt; &lt;span class="n"&gt;birthDate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Getters, Setters, Constructors, Equals...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;birthDate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Getters, Setters, Constructors, Equals...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;MappingDefinition&lt;/span&gt; &lt;span class="n"&gt;mappingDefinition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MappingDefinitionBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"birthDate"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"birthDate"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;withTransformer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DateToLongMappingTransformer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// We don't have to state the transformer here because it is a default transformer&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Inline Transformers
&lt;/h2&gt;

&lt;p&gt;In some use cases we want to transform the value but we don't need a reusable transformer and we don't want to create a class just for a one time use.&lt;/p&gt;

&lt;p&gt;Inline transformers for the rescue! Inline transformers allow to transform the value without the need to create and register and transformer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;MappingDefinition&lt;/span&gt; &lt;span class="n"&gt;mappingDefinition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MappingDefinitionBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Source&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"birthDate"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"birthYear"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;withTransformer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOriginalValue&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOriginalValue&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;getYear&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advanced Transformers
&lt;/h2&gt;

&lt;p&gt;Transformers also allow us to do transformations with the DB or other data sources.&lt;/p&gt;

&lt;p&gt;In this example we will use the power of the &lt;a href="https://shapeshift.krud.dev/guides/spring-usage"&gt;Spring Boot integration&lt;/a&gt; to create transformers with DB access.&lt;/p&gt;

&lt;p&gt;We have three models:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Job - DB entity.&lt;/li&gt;
&lt;li&gt;User - DB entity.&lt;/li&gt;
&lt;li&gt;UserDTO - Client model.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Job&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Getters, Setters, Constructors, Equals...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;jobId&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Getters, Setters, Constructors, Equals...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;jobName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Getters, Setters, Constructors, Equals...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to convert the &lt;code&gt;jobId&lt;/code&gt; on &lt;code&gt;User&lt;/code&gt; to &lt;code&gt;jobName&lt;/code&gt; on &lt;code&gt;UserDTO&lt;/code&gt; by querying the job from the DB and setting it on the DTO.&lt;/p&gt;

&lt;p&gt;In Spring's case, you generally avoid interaction with the application context from static functions or functions on domain objects.&lt;/p&gt;

&lt;p&gt;We will use a ShapeShift's &lt;a href="https://shapeshift.krud.dev/guides/spring-usage"&gt;Spring integration&lt;/a&gt; to create a component as a transformer to access our DAO bean.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JobIdToNameTransformer&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;MappingTransformer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;JobDao&lt;/span&gt; &lt;span class="n"&gt;jobDao&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Nullable&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@NonNull&lt;/span&gt; &lt;span class="nc"&gt;MappingTransformerContext&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOriginalValue&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="nc"&gt;Job&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jobDao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findJobById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOriginalValue&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All that's left to do is to use this transformer in our mapping.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;MappingDefinition&lt;/span&gt; &lt;span class="n"&gt;mappingDefinition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MappingDefinitionBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"jobId"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"jobName"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;withTransformer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JobIdToNameTransformer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another bonus of using transformers is their reusability. In some use cases, We could create more generic transformers that will have application-wide usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Default Transformers
&lt;/h2&gt;

&lt;p&gt;When registering transformers you can indicate wether a transformer is a &lt;a href="https://shapeshift.krud.dev/api-documentation/transformers#default-transformers"&gt;default transformer&lt;/a&gt;. A default transformer of types &amp;lt;A, B&amp;gt; is used when you map a field of type &amp;lt;A&amp;gt; to field of type &amp;lt;B&amp;gt; without specifying a transformer to be used.&lt;/p&gt;

&lt;p&gt;As we already seen, default transformers are useful for recurring transformations and especially for automatic mapping.&lt;/p&gt;

&lt;h1&gt;
  
  
  Deep Mapping
&lt;/h1&gt;

&lt;p&gt;What if we want to map from/to fields that available inside a field which is an object? We can even do that, easily.&lt;/p&gt;

&lt;p&gt;In order to access child classes we can use the full path of a field. Let's look at the following example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;From&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Child&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Child&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// Getters, Setters, Constructors, Equals...&lt;/span&gt;

    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Child&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;// Getters, Setters, Constructors, Equals...&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;To&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;childValue&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Getters, Setters, Constructors, Equals...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to map the &lt;code&gt;value&lt;/code&gt; field in &lt;code&gt;Child&lt;/code&gt; class inside the &lt;code&gt;From&lt;/code&gt; class to the &lt;code&gt;childValue&lt;/code&gt; field in the &lt;code&gt;To&lt;/code&gt; class. We will use the full path of &lt;code&gt;value&lt;/code&gt; which is &lt;code&gt;child.value&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;MappingDefinition&lt;/span&gt; &lt;span class="n"&gt;mappingDefinition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MappingDefinitionBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;From&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;To&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"child.value"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"childValue"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full path is supported in both source and destination fields, it also supports multi level depth (e.g. &lt;code&gt;x.y.z&lt;/code&gt;).&lt;/p&gt;

&lt;h1&gt;
  
  
  Conditional Mapping
&lt;/h1&gt;

&lt;p&gt;Conditions allow us to add a predicate to a specific field mapping to determine whether this field should be mapped.&lt;/p&gt;

&lt;p&gt;Using this feature is as easy as creating a condition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotBlankStringCondition&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;MappingCondition&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;isValid&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@NonNull&lt;/span&gt; &lt;span class="nc"&gt;MappingConditionContext&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOriginalValue&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOriginalValue&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;trim&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And adding the condition to the desired field mapping.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleEntity&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Getters, Setters, Constructors, Equals...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleEntityDisplay&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Getters, Setters, Constructors, Equals...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;MappingDefinition&lt;/span&gt; &lt;span class="n"&gt;mappingDefinition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MappingDefinitionBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SimpleEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SimpleEntityDisplay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withCondition&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NotBlankStringCondition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Inline Conditions
&lt;/h2&gt;

&lt;p&gt;Like transformers, conditions can also be added inline using a function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;MappingDefinition&lt;/span&gt; &lt;span class="n"&gt;mappingDefinition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MappingDefinitionBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SimpleEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SimpleEntityDisplay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withCondition&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOriginalValue&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!((&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOriginalValue&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;trim&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Annotations Mapping
&lt;/h1&gt;

&lt;p&gt;This specific feature receives lots of hate because it breaks the separation of concerns principle. Agreed, this could be an issue in some applications, but in some use cases where all objects are part of the same application it can also be very useful to configure the mapping logic on top of the object. Check out the &lt;a href="https://shapeshift.krud.dev/api-documentation/annotations"&gt;documentation&lt;/a&gt; and decide for yourself.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Object mapping libraries are not the solution for every application. For small, simple applications using boiler-plate mapping functions are more than enough. But, when developing larger, more complex applications, object mapping libraries can take your code to the next level, saving you development and maintenance time. All of these while reducing the amount of boiler-plate code and overall improving the development experience.&lt;/p&gt;

&lt;p&gt;On a personal note, I used to work with manual mapping functions and was ok with it. It was "just" some simple lines of code. After upgrading our applications to use object mapping as part of our "boiler-plate free" framework (We will discuss that framework at a later time), I can't go back. Now we spend more time on what's important and interesting and almost no time on boring boiler-plate code.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>java</category>
      <category>architecture</category>
      <category>oop</category>
    </item>
    <item>
      <title>My First Real Job</title>
      <dc:creator>TheWizKid</dc:creator>
      <pubDate>Tue, 06 Sep 2022 13:24:33 +0000</pubDate>
      <link>https://dev.to/krud/my-first-real-job-1h5f</link>
      <guid>https://dev.to/krud/my-first-real-job-1h5f</guid>
      <description>&lt;p&gt;The stack — Java, Mysql&lt;/p&gt;

&lt;p&gt;The Experience — 9 Years&lt;/p&gt;

&lt;p&gt;The Job — Junior Developer at Startup&lt;/p&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;h2&gt;
  
  
  My first job interview
&lt;/h2&gt;

&lt;p&gt;In my last year of uni Aviv (my now best friend and business partner) told me he is working at a startup that is now growing, and I should join him working there. I was nervous for my first job interview, they were working with a different stack than I had experience with, and let's just say I'm a little weird. A little background, I live and had grown up in a rural farming area, I wear shorts, and sandals (even in the dead of winter), not exactly “professional” looking. Anyway I vividly remember taking long pants and shoes in the car with me to the interview, thinking I would change right before I went in, to look the part. At the last moment I changed my mind, and told myself, “You should not try to pretend you are something you are not, they will either take you with your quirks or it's not the right place for you”. So I walked into the interview with the CEO of the company, in shorts and sandals. Lucky for me, the CEO was wearing torn jeans, and dirty worn sneakers, I felt right at home. &lt;/p&gt;

&lt;p&gt;All this was to say something simple, but not easy. Be true to yourself, if you go work somewhere you won’t give your 100% if you feel out of place. I'm not saying you need to reject any job that isn't perfect, it's more like, find a job that doesn't compromise on your core, and be flexible about the “less important” stuff. In the long run this will be much better for you and the company.&lt;/p&gt;

&lt;h2&gt;
  
  
  Java you say
&lt;/h2&gt;

&lt;p&gt;My first day on the job was an interesting one, I got to the new office, they gave me a laptop, and told me to install my environment. Easier said than done, till now it was a visual studio, now I needed this weird eclipse thing. Then I got the code and nothing runs :/ weird. After some back and forth, I learned that for java and eclipse I need to download the JDK (Java development toolkit), fine. Still nothing… Just a reminder it was my first day on the job, in a language/stack I didn't know, and I didnt want to be the new “idiot” they hired. Safe to say it took me the whole day or maybe even 2 just to get the code up and running.&lt;/p&gt;

&lt;p&gt;Later that week I got my first task, I needed to copy some functionality that existed in the client area to the back office. This was actually a perfect first task, for many reasons, most of all it was 70% copy paste. This was great because I had barely knew how to read the java code I was looking at. Additionally the adaptation needed in the back office project was simple and existed in one form or another in different areas of the code. So basically the task was like a big jigsaw puzzle, I got 1 big piece, now I need to go hunt down some smaller ones and put it all together.&lt;/p&gt;

&lt;h3&gt;
  
  
  A small tangent
&lt;/h3&gt;

&lt;p&gt;Over the years this “jigsaw puzzle” approach has really sunk in, and today I can tell you with confidence, if you structure the tasks given to developers (especially juniors) in this way, a few good things happen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;They get into the code much faster.&lt;/li&gt;
&lt;li&gt;They write less buggy code.&lt;/li&gt;
&lt;li&gt;They build confidence in their abilities.
Finally as a business owner I can tell you from my experience, it takes a lot less time to see a positive ROI for their time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This has led me to a core belief of mine (in regards to development). A good programmer needs to know 3 things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How to read and understand code.&lt;/li&gt;
&lt;li&gt;Be proficient in google searches for solutions to the problem at hand.&lt;/li&gt;
&lt;li&gt;Know how to adapt other code to meet their current needs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A great programmer is one that knows how/why things are done in this way, and understands optimization and deep diving into frameworks they use. While a good programmer just needs to know how to use the framework, and not how it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is this Spring magic - using frameworks
&lt;/h2&gt;

&lt;p&gt;The project we were writing was built upon Spring (a hugely popular dependency injection framework in Java). Now frameworks are powerful tools, but they hide many things under the hood. Over the years I have learned in depth how/why Spring works, but truth be told, as a junior developer back then it seemed like magic to me. &lt;/p&gt;

&lt;p&gt;I want to take you through a few different stages of understanding that I use today when I am faced with a new framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 - Basics (The what)
&lt;/h3&gt;

&lt;p&gt;In this step it is most important NOT to try to understand how it works, just to understand the tools and capabilities it provides. I have seen it many times that a junior gets “stuck” on trying to understand the depths of the framework, and the truth is they are just not ready to. They don’t fully understand WHAT the framework can do, so they have no chance to understand how.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 - Advanced Usage (The how)
&lt;/h3&gt;

&lt;p&gt;Almost every framework I have used has many different features that compliment each other (makes sense). This stage is focused on that, using the framework to its fullest. Mixing and matching different features, making the whole greater than the sum of its parts. This is where the developer truly learns HOW to use the framework correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 - Down the rabbit hole (The why)
&lt;/h3&gt;

&lt;p&gt;Here is where things get truly interesting. There comes a time when you reach the limits of the framework and try to do something you think should be possible, but turns out it isn't. This is when you download the source code and start the deep dive to understand the WHY. Sometimes it's something at the core of how it's built, but other times it's just on the fringes of what the framework can do, and that means, no examples, no documentation. Then the only answer is to understand why the framework works the way it does.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4 - Building upon the framework
&lt;/h3&gt;

&lt;p&gt;This is the final stage, where you can start using the tools the framework gives you to build your own mini framework upon. Or even build your own libraries from scratch. This is where you start contributing to the framework, or start releasing some open source of your own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generalization is a powerful tool
&lt;/h2&gt;

&lt;p&gt;After a year or 2 in the company, I got a new task, implementing a new PSP (Payment service provider), basically adding something like paypal to the clients payment options. This was a new area in the code for me, something I had no experience with. So off to the races, I went and looked at the implementation of a few different PSPs, and to my shock, I saw a ton of very similar code, makes sense since it doesn't really matter how the money comes in, we still need to update billing, create the relevant logs, and credit the account. All this was done time and time again, in the different PSPs, this was mainly because the objects we were getting back from the PSP api were so different.&lt;/p&gt;

&lt;p&gt;Interfaces to the rescue, this is one of my first epiphanies, this has led me to proper code layers, and a few “new” design patterns (really just classes that give me a mix of design patterns with no boilerplate code). So I told my boss I needed more time to rewrite it correctly, and set to work. I created a handler that was in charge of the process of communication with the PSPs. It had methods for the different actions, like charge or refund and so forth. It managed the different steps of the process and called upon the different classes of the PSP for interpretation of the response received via API.&lt;/p&gt;

&lt;p&gt;I don't want to get into the code (this is not the point of the post), but basically there was a PspResponse that all PSPs needed to inherit from, and then methods like:&lt;br&gt;
getIsSuccess()&lt;br&gt;
getErrorText()&lt;br&gt;
getAmount()&lt;/p&gt;

&lt;p&gt;This took some time to refactor the old code, but in the long run reduced implementation time for new PSPs drastically, all the while reducing the amount of bugs (mainly because someone would always forget to update the new logic in some old PSP).&lt;/p&gt;

&lt;p&gt;The experience I gained designing and implementing this led me down the path to becoming an architect. I felt so proud from my new creation, and caused me to look at code in a different way. This is a pivotal point in my career, and has caused me to think about how to write code correctly in the long run, and not just this feature.&lt;/p&gt;

&lt;p&gt;Please check out my &lt;a href="https://github.com/krud-dev/shapeshift/"&gt;open source library&lt;/a&gt; and maybe even star it. I would appreciate it greatly!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>career</category>
      <category>beginners</category>
      <category>opensource</category>
    </item>
    <item>
      <title>What I learned in Uni</title>
      <dc:creator>TheWizKid</dc:creator>
      <pubDate>Thu, 25 Aug 2022 13:21:09 +0000</pubDate>
      <link>https://dev.to/krud/what-i-learned-in-uni-1jic</link>
      <guid>https://dev.to/krud/what-i-learned-in-uni-1jic</guid>
      <description>&lt;p&gt;The stack — C#&lt;/p&gt;

&lt;p&gt;The Experience — 7 Years&lt;/p&gt;

&lt;p&gt;The Job — Uni Student + Freelancer&lt;/p&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;h2&gt;
  
  
  My first paying job
&lt;/h2&gt;

&lt;p&gt;Let me set the mood, poor uni student, first year physics major, tooo many courses at the same time, not enough sleep; I think you get the idea (and possibly what it feels like). Now I know we would all love to have some money, to go out with, and enjoy our time. We can all find some minimum wage 9-5, but I was looking for something better, and thought I could use my skills as a developer to land some work.&lt;/p&gt;

&lt;p&gt;Luckily for me, a family friend was looking for someone to develop something for them. The job was a good mix of my knowledge and skills. This friend owned a factory that builds custom water treatment and purification equipment, and he had a bottleneck in his quoting division. Every quote the sales team needed required an engineer to write up plans, then someone needed to calculate not only the costs of the different parts, but things like length of welds, amount of paint needed, amount of bolts needed, and so forth. Till this point it was done in excels with lookups and required a lot of know-how.&lt;/p&gt;

&lt;p&gt;My job (should I choose to accept it) was to create a visual tool, that the sales agent can drag and drop to the parts needed, including piping and such, and the output would be a detailed quote, including everything mentioned above and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working with/for a client as a freelancer
&lt;/h2&gt;

&lt;p&gt;Now for all you developers out there, I'm sure you are thinking, “OK, he got some requirement documents on how/what to build”. That couldn't be farther from the truth (and surprisingly more common than I had expected). I had to basically interview all the people involved in the company, to try and get a feel of what was needed. After that I would sit down and write my own basic requirement documents, that I would then go over with the client. &lt;/p&gt;

&lt;h3&gt;
  
  
  If there is one thing you take away from this: “Always go over the requirements with the client in writing”
&lt;/h3&gt;

&lt;p&gt;This has saved my @$$ many times.&lt;/p&gt;

&lt;p&gt;It took some time learning how to deal with clients, and I learned a ton. This first client helped me learn, the development skills aren't the only thing important, it is important to understand the clients needs, pain points, and where to focus my efforts, this has rang true throughout my career.&lt;/p&gt;

&lt;p&gt;I was lucky (in a sadistic kind of way) that my first client had no idea on how to write requirements, and how to handle a development cycle. In the years to come, I would receive many “requirements” of the type “put a button there that does that”; and 9/10 times there is a better way to do things that answers the clients problems in a better way. I urge you to look at anything you are developing, and try to understand the business use case behind it, and look at the bigger picture. You will be surprised to find that this will help you tremendously write better code.&lt;/p&gt;

&lt;p&gt;Just for an example, I was told to make a button for export of the quote, sounds reasonable enough, but then it would be the sales agent's job to send copies to the client, the management, and the project manager. I wouldn't have known this if I just would have developed the button. Instead I suggested that the system have projects in it, with the project managers info, and have a “send to email” button. This may seem minor, but after talking to the CEO I found out it saved him tons of heartache, because more than once, the wrong quote was sent to the wrong client, just because the agent attached the wrong file.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you can’t learn in Uni
&lt;/h2&gt;

&lt;p&gt;During my time at uni, I learned a ton of things, in many different subjects, including programming. A few caveats to this is the fact that most of the time, the languages that were taught were out of date, and the professors didn't really know how to program a product, more like write blocks of code. Sadly there is more truth than I had hoped for in the old saying “Those who can't, teach”.&lt;/p&gt;

&lt;p&gt;I think I can confidently say I learned more in my first freelance job, then everything uni could teach. There is nothing like getting your hands “dirty” and just doing some work. Here is a small list of the top things I “learned on the job”:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Understand the business - Like I stated before, understand “why” your client needs the feature, not just how they see the feature implemented&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Pareto_principle"&gt;80/20 principle&lt;/a&gt; - Try and spend your time wisely covering most of the needs, and leaving “known issues” for the really rare edge cases. &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/KISS_principle"&gt;KISS&lt;/a&gt; - “Keep it, simple stupid” (or sometimes I think it’s “Keep it simple, stupid”), try to simplify your code, break it into smaller bite sized pieces, that will pay dividends in the long run.&lt;/li&gt;
&lt;li&gt;Performance isn't everything (or even important most of the time) - Today's computers are fast (like really really fast) and that fancy Binary search algorithm you learned, doesn't really matter in real life (most of the time), when you filter a list of even a few 10s of thousands, it’s not really going to change the runtime.&lt;/li&gt;
&lt;li&gt;Use open source wherever you can - There are so many amazing open source projects out there, and they can cut your programming time by a huge factor. Additionally they can (usually) do it better then if you tried to write it yourself.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Please check out my &lt;a href="https://github.com/krud-dev/shapeshift/"&gt;open source library&lt;/a&gt; and maybe even star it. I would appreciate it greatly!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>career</category>
      <category>beginners</category>
      <category>opensource</category>
    </item>
    <item>
      <title>They don't call it intelligence for nothing</title>
      <dc:creator>TheWizKid</dc:creator>
      <pubDate>Wed, 17 Aug 2022 14:20:08 +0000</pubDate>
      <link>https://dev.to/krud/they-dont-call-it-intelligence-for-nothing-14l1</link>
      <guid>https://dev.to/krud/they-dont-call-it-intelligence-for-nothing-14l1</guid>
      <description>&lt;p&gt;The stack — C#, Oracle&lt;/p&gt;

&lt;p&gt;The Experience — 4 Years&lt;/p&gt;

&lt;p&gt;The Job — The intelligence corps&lt;/p&gt;




&lt;h2&gt;
  
  
  It's my time to serve
&lt;/h2&gt;

&lt;p&gt;This may be doxing myself a little, but where I live there is a mandatory military service, for 3 f%$#ing years. Luckily for me, I had some skills, computer skills. It works here like this, you go do a lot of tests, intelligence tests, aptitude tests, physical tests, and at the end you get stationed somewhere (usually NOT where you want to be). I was in the running for a few different positions, and then one day out of the blue, I got a phone call. Come now to interview for a new position, nothing that I ever heard of, well of course I went. They were looking for someone with programming experience that they didn't need to send to the military academy to learn, and I fit the bill…&lt;/p&gt;

&lt;p&gt;One thing led to another, and within the week I found myself in basic training on my way to the intelligence corps, as a developer in a small unit. After a few weeks of basic training (even us developers go through boot camp), I arrived at my unit. This is where I found out that just me and 1 other guy are the only people in the unit that can “speak computer”, and no I don't just mean program. We were in charge of the whole system there, from the network, to the servers, and of course the software.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to learn C# in 3 easy steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Get enlisted to the military, to a plush desk job as a programmer.&lt;/li&gt;
&lt;li&gt;Be 1 of 2 people in charge of the whole system.&lt;/li&gt;
&lt;li&gt;Never forget that if you don't get on top of things within a few months, they will ship you out to somewhere much worse.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Easy right?&lt;/p&gt;

&lt;p&gt;But in all seriousness, I had to teach myself C# on the job. At least I had the running code, and the coveted PC on the internet. You see in the intelligence corps, and probably most military installations, no one has internet access on their PC. Well technically neither did I, but what I did have was access to the only PC (that was air gapped from the network) which had internet access. &lt;/p&gt;

&lt;p&gt;By this time of my life (luckily for me), google was a thing already, and there were more and more resources online about programming. Even more for things like C#, because it was Microsoft's. But (I hate it that there is always a “but”)… The computer in question is air gapped, so no copy paste.&lt;/p&gt;

&lt;h2&gt;
  
  
  Into the deep end
&lt;/h2&gt;

&lt;p&gt;This was the first time I truly worked with a DB (I don't really count MS Access). It was my first time, and they threw me into the deep end (without floats). Our systems used Oracle, till this day I think it's an amazing DB, but it's a beast. Our system was complex, and today, I would have never built it this way (I didn't build it back then either, the system was operational when I got there). &lt;/p&gt;

&lt;p&gt;I know I'm going to spark some debate about this, but I dont think business logic is supposed to be in stored procedures (there I said it). This architecture caused some very weird side effects, for example, releasing versions requiring simultaneous release of new stored procedures, or updates to old ones. Triggers that can cause chain reactions of events, and you can't quite see them in any IDE. &lt;/p&gt;

&lt;p&gt;If that wasn't bad enough, we didn't really have a server side. The C# was a desktop app, installed via group policy to all PCs on the network. The server was basically the stored procedures in Oracle. So things like creating thread pools to handle large tasks, or locks on editing were all out of the question.&lt;/p&gt;

&lt;p&gt;This is where I started thinking about how code should be built, and it was the start of the path to architecture. Even if it still took a few years to find out what I should do, at least now, I know what I shouldn't. It was an important realization, one that I have since seen on some of the juniors I mentored. Writing code without bugs is important, but writing code in a maintainable way, is just as important.&lt;/p&gt;

&lt;h2&gt;
  
  
  My partner in crime
&lt;/h2&gt;

&lt;p&gt;About half way through my service, the other guy I was with finished his tour. It was up to me to find a replacement. I had access to candidates (and it's not like they had CVs, they are all 18 year old fresh out of high school), I gave them tests to do, asked them questions. Remember back then I couldn't send them anything online, all by phone, or in person.&lt;/p&gt;

&lt;p&gt;After a few weeks, and at least 50 candidates, I had found him, my new partner. Again we couldn't send him to learn in any course, so I had to find someone with the knowhow from home. Additionally even after I selected him, it took months for him to get to me. He had to get security clearance, and go through boot camp. So months later he was finally here, I would like to introduce you to a new character (that will have a recurring role in the articles to come), my business partner (and best friend).&lt;/p&gt;

&lt;p&gt;Like any relationship it was rocky at first. I won't go into the details, but what I can say is that we went through a lot together. Things that built our relationship strong. Little did I know (spoilers) that we would be working together till this day (over 16 years).&lt;/p&gt;

&lt;p&gt;Please check out our &lt;a href="https://github.com/krud-dev/shapeshift/"&gt;open source library&lt;/a&gt;  and maybe even star it ;-)&lt;br&gt;
We would appreciate it greatly.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>career</category>
      <category>opensource</category>
      <category>beginners</category>
    </item>
    <item>
      <title>So the journey begins</title>
      <dc:creator>TheWizKid</dc:creator>
      <pubDate>Wed, 10 Aug 2022 12:52:04 +0000</pubDate>
      <link>https://dev.to/krud/so-the-journey-begins-2n12</link>
      <guid>https://dev.to/krud/so-the-journey-begins-2n12</guid>
      <description>&lt;p&gt;The stack — VB6, C&lt;br&gt;
The Experience — 2 Years&lt;br&gt;
The Job — High school&lt;/p&gt;




&lt;h2&gt;
  
  
  Isn’t learning fun?
&lt;/h2&gt;

&lt;p&gt;To set the scene, it was early 2000s in a small farming village. Yes we had internet, but it was dial up, and no stack overflow or anything close yet, the best you could hope for is a forum post.&lt;/p&gt;

&lt;p&gt;So how did we learn? TL;DR — Books and lots of them…&lt;/p&gt;

&lt;p&gt;I remember going to the library looking for books, swapping with friends. If you got the expensive ones you even got a CD (you know the round thing with a hole in it) with them with code examples and lesson projects, not that the CD ever worked (or was even there) from the library. No searching the book for your problem or an example, no copy paste, nothing. Just read and hope you remember later where you saw something about that problem you are having.&lt;/p&gt;

&lt;p&gt;Yes the internet existed, but there wasn’t much in the way or programming guides, tutorials, or even examples. One of the most useful tools was IRC channels (for you kids out there, a really old chat). Tell you the truth, I don’t even remember how I found what channel to write to, but I remember talking to people from around the world about the most silly things, things that today you will find the solution to as the top search result on google.&lt;/p&gt;

&lt;h2&gt;
  
  
  I know this is weird, but you can learn at school
&lt;/h2&gt;

&lt;p&gt;When I reached the last year of high school, I took a tech class. In this class we learned things from electrical engineering basics, mechanical design, and of course programming. The main problem was, I had taught myself more than what the teacher reached in class. Nonetheless I gained a great resource, my teacher could answer questions, point me in the right direction.&lt;/p&gt;

&lt;p&gt;First of all, I would like to say, not all teachers are bad (yes many are, but not all). Luckily for me our high school tech teacher saw my potential (especially after I broke the school’s network). I used to get bored in class, everyone was learning C and VB6 at a level I passed a long time ago on my own. That is when my teacher came to my rescue.&lt;/p&gt;

&lt;h2&gt;
  
  
  My first real project
&lt;/h2&gt;

&lt;p&gt;Computer vision, you know when computers look at an image and try to understand what is there. Well for that time it was no AI models or anything, it was purely algorithmic. My mission should I choose to accept it (over being thrown out of class) was to take this “new” library that allowed me to capture an image from a webcam in VB6 and process it (pixel by pixel), and try and make out a shape in an image, simple geometric shapes (circle, square, triangle).&lt;/p&gt;

&lt;p&gt;So my best friend and I set out to this task, it was soooo interesting we would have all nighters trying to solve it. Let me take you through the basics.&lt;/p&gt;

&lt;p&gt;Go over the image one pixel at a time to try and find a place with a big change in color (black shape on white paper).&lt;br&gt;
When I reach it, go in a pattern to find its neighbor that is also a border pixel.&lt;br&gt;
Do this in a loop till I can’t find any more border pixels.&lt;br&gt;
This worked (in theory). There is always a “but”… It all went to hell when we would hit these edge cases of a few pixels out of place.&lt;/p&gt;

&lt;p&gt;That’s when it hit me, the solution may be obvious to you, but to me it wasn’t. Well, it turns out there is a use for the data structure “stack” we’ve been taught. We put all pixels in the stack, and each time we would hit a brick wall, we would pop a pixel and try again. This would continue till we popped them all out and got back to our starting pixel.&lt;/p&gt;

&lt;p&gt;This turned out to be very effective, and solved our biggest problem.&lt;/p&gt;

&lt;p&gt;We actually found a few solutions for understanding what shape it was.&lt;/p&gt;

&lt;p&gt;From the trivial, see how many “straight” lines made up the shape, which worked pretty well for simple shapes. To the most advanced solution, that I am still proud of till this day, calculate the area of the shape, and the perimeter of the shape, and see what constant best defines the relation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The moral of the story
&lt;/h2&gt;

&lt;p&gt;I told you this whole story to come to a small point, one that shaped the next few years of my development life. Data structures &amp;amp; design patterns are there for a reason, and even though it might not be obvious, you ask yourself “why would I ever need that”. At some point you will, and it’s good to keep them handy.&lt;/p&gt;




&lt;p&gt;If you would like to check out our &lt;a href="https://github.com/krud-dev/shapeshift/"&gt;open source library&lt;/a&gt; and leave feedback we would appreciate it greatly.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>career</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Object Mapping advanced features &amp; QoL with Kotlin</title>
      <dc:creator>Aviv Mor</dc:creator>
      <pubDate>Tue, 09 Aug 2022 18:33:31 +0000</pubDate>
      <link>https://dev.to/krud/object-mapping-advanced-features-qol-with-kotlin-5dgn</link>
      <guid>https://dev.to/krud/object-mapping-advanced-features-qol-with-kotlin-5dgn</guid>
      <description>&lt;p&gt;When working with multi-layered applications, external libraries, a legacy code base or external APIs, we are often required to map between different objects or data structures.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will check out some Object Mapping libraries advanced features to simplify this task while saving development and maintenance time.&lt;/p&gt;

&lt;p&gt;In our examples we will use the library &lt;a href="https://github.com/krud-dev/shapeshift/"&gt;ShapeShift&lt;/a&gt;. It's a light-weight object mapping library for Kotlin/Java with lots of cool features.&lt;/p&gt;

&lt;h1&gt;
  
  
  Auto Mapping
&lt;/h1&gt;

&lt;p&gt;We will start with a bang. Auto mapping can and will save you lots of time and boiler-plate code. Some applications require manual mapping between objects, but most applications will save tons of time working on boring boiler-plate by just using this one feature. And it gets even better, with ShapeShift's default transformers we can even use automatic mapping between different data types.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple Mapping
&lt;/h2&gt;

&lt;p&gt;Let's start with a simple example for auto mapping. We have our two objects, imagine they could also have tens, hundreds, or even thousands (for the crazy people here) of fields.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to map all the field from &lt;code&gt;User&lt;/code&gt; to &lt;code&gt;UserDTO&lt;/code&gt;. Using auto mapping we don't need to write any boiler-plate code. The mapper will be defined as follow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mapper&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;autoMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AutoMappingStrategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BY_NAME_AND_TYPE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voila! All the fields will be mapped automatically without any manual boiler-plate code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Mapping
&lt;/h2&gt;

&lt;p&gt;In this example we will use the power of &lt;a href="https://shapeshift.krud.dev/api-documentation/transformers#default-transformers"&gt;default transformers&lt;/a&gt; to take auto mapping even further.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;birthDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;birthDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the types of the &lt;code&gt;birthDate&lt;/code&gt; field are different in the source and destination classes. But using the power of default transformers we can still use auto mapping here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mapper&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;autoMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AutoMappingStrategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BY_NAME&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We changed the auto mapping strategy to &lt;code&gt;BY_NAME&lt;/code&gt; so it will map fields also with different types. Now we need to register a default transformer to the &lt;code&gt;ShapeShift&lt;/code&gt; instance in order for it to know how to transform &lt;code&gt;Date&lt;/code&gt; to &lt;code&gt;Long&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;shapeShift&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ShapeShiftBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withTransformer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DateToLongMappingTransformer&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also add manual mapping on top of the auto mapping in order to add/change behavior. The source and destination classes have different names for the &lt;code&gt;name&lt;/code&gt; field so we will add manual mapping for it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mapper&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;autoMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AutoMappingStrategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BY_NAME&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;mappedTo&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fullName&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Auto mapping is great for use cases that does not require specific mapping. It helps reduce the amount manual boiler-plate code needed to configure mapping and also helps you keep your sanity.&lt;/p&gt;

&lt;h1&gt;
  
  
  Transformers
&lt;/h1&gt;

&lt;p&gt;Transformers are very useful feature that allows you to transform the type/value of a field to a different type/value when mapping a field.&lt;/p&gt;

&lt;p&gt;Some use cases we have been using widely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transform date to long and vice versa between server and client objects.&lt;/li&gt;
&lt;li&gt;Transform JSON string to it's actual type and vice versa between server and client objects.&lt;/li&gt;
&lt;li&gt;Transform comma separated string to list of enums.&lt;/li&gt;
&lt;li&gt;Transform another object id to its object or one of its fields from the DB using Spring transformers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Basic Transformers
&lt;/h2&gt;

&lt;p&gt;We will start with a simple transformer example. Date-to-Long  and Long-to-Date transformers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DateToLongMappingTransformer&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;MappingTransformer&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;MappingTransformerContext&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;):&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;originalValue&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LongToDateMappingTransformer&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;MappingTransformer&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;MappingTransformerContext&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;):&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;originalValue&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;originalValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All we need to do now is to &lt;a href="https://shapeshift.krud.dev/api-documentation/transformers#registering-transformers"&gt;register&lt;/a&gt; them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;shapeShift&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ShapeShiftBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withTransformer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DateToLongMappingTransformer&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// "true" is optional, we are registering the transformers as default transformers, more on that later.&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withTransformer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;LongToDateMappingTransformer&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! We can now use the transformers when mapping objects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;birthDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;birthDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mapper&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;mappedTo&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
    &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;mappedTo&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
    &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;birthDate&lt;/span&gt; &lt;span class="n"&gt;mappedTo&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;birthDate&lt;/span&gt; &lt;span class="n"&gt;withTransformer&lt;/span&gt; &lt;span class="nc"&gt;DateToLongMappingTransformer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="c1"&gt;// We don't have to state the transformer here because it is a default transformer&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Inline Transformers
&lt;/h2&gt;

&lt;p&gt;In some use cases we want to transform the value but we don't need a reusable transformer and we don't want to create a class just for a one time use.&lt;/p&gt;

&lt;p&gt;Inline transformers for the rescue! Inline transformers allow to transform the value without the need to create and register and transformer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;shapeShift&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ShapeShiftBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withMapping&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Target&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Map birthDate to birthYear with a transformation function&lt;/span&gt;
            &lt;span class="nc"&gt;Source&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;birthDate&lt;/span&gt; &lt;span class="n"&gt;mappedTo&lt;/span&gt; &lt;span class="nc"&gt;Target&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;birthYear&lt;/span&gt; &lt;span class="nf"&gt;withTransformer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;originalValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;originalValue&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advanced Transformers
&lt;/h2&gt;

&lt;p&gt;Transformers also allow us to do transformations with the DB or other data sources.&lt;/p&gt;

&lt;p&gt;In this example we will use the power of the &lt;a href="https://shapeshift.krud.dev/guides/spring-usage"&gt;Spring Boot integration&lt;/a&gt; to create transformers with DB access.&lt;/p&gt;

&lt;p&gt;We have three models:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Job - DB entity.&lt;/li&gt;
&lt;li&gt;User - DB entity.&lt;/li&gt;
&lt;li&gt;UserDTO - Client model.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Job&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;jobId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;jobName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to convert the &lt;code&gt;jobId&lt;/code&gt; on &lt;code&gt;User&lt;/code&gt; to &lt;code&gt;jobName&lt;/code&gt; on &lt;code&gt;UserDTO&lt;/code&gt; by querying the job from the DB and setting it on the DTO.&lt;/p&gt;

&lt;p&gt;In Spring's case, you generally avoid interaction with the application context from static functions or functions on domain objects.&lt;/p&gt;

&lt;p&gt;We will use a ShapeShift's &lt;a href="https://shapeshift.krud.dev/guides/spring-usage"&gt;Spring integration&lt;/a&gt; to create a component as a transformer to access our DAO bean.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JobIdToNameTransformer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;jobDao&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;JobDao&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;MappingTransformer&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;MappingTransformerContext&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;):&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;originalValue&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;job&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jobDao&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findJobById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;originalValue&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All that's left to do is to use this transformer in our mapping.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mapper&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;mappedTo&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
    &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;jobId&lt;/span&gt; &lt;span class="n"&gt;mappedTo&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;jobName&lt;/span&gt; &lt;span class="n"&gt;withTransformer&lt;/span&gt; &lt;span class="nc"&gt;JobIdToNameTransformer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another bonus of using transformers is their reusability. In some use cases, We could create more generic transformers that will have application-wide usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Default Transformers
&lt;/h2&gt;

&lt;p&gt;When registering transformers you can indicate wether a transformer is a &lt;a href="https://shapeshift.krud.dev/api-documentation/transformers#default-transformers"&gt;default transformer&lt;/a&gt;. A default transformer of types &amp;lt;A, B&amp;gt; is used when you map a field of type &amp;lt;A&amp;gt; to field of type &amp;lt;B&amp;gt; without specifying a transformer to be used.&lt;/p&gt;

&lt;p&gt;As we already seen, default transformers are useful for recurring transformations and especially for automatic mapping.&lt;/p&gt;

&lt;h1&gt;
  
  
  Deep Mapping
&lt;/h1&gt;

&lt;p&gt;What if we want to map from/to fields that available inside a field which is an object? We can even do that, easily.&lt;/p&gt;

&lt;p&gt;In order to access child classes we can use the &lt;code&gt;..&lt;/code&gt; operator. Let's look at the following example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;From&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;child&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Child&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Child&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;To&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;childValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to map the &lt;code&gt;value&lt;/code&gt; field in &lt;code&gt;Child&lt;/code&gt; class inside the &lt;code&gt;From&lt;/code&gt; class to the &lt;code&gt;childValue&lt;/code&gt; field in the &lt;code&gt;To&lt;/code&gt; class. We will create a mapper with the &lt;code&gt;..&lt;/code&gt; operator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mapper&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;From&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;To&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;From&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="nc"&gt;From&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Child&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;mappedTo&lt;/span&gt; &lt;span class="nc"&gt;To&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;childValue&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take it one step further with multi level depth.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;From&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;grandChildValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;To&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;child&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Child&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Child&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;grandChild&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;GrandChild&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GrandChild&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GrandChild&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To access the grand child field we just use the &lt;code&gt;..&lt;/code&gt; operator twice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mapper&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;From&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;To&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;From&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;grandChildValue&lt;/span&gt; &lt;span class="n"&gt;mappedTo&lt;/span&gt; &lt;span class="nc"&gt;To&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="nc"&gt;To&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Child&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;grandChild&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="nc"&gt;To&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GrandChild&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conditional Mapping
&lt;/h1&gt;

&lt;p&gt;Conditions allow us to add a predicate to a specific field mapping to determine whether this field should be mapped.&lt;/p&gt;

&lt;p&gt;Using this feature is as easy as creating a condition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotBlankStringCondition&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;MappingCondition&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;MappingConditionContext&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;):&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;originalValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isNullOrBlank&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And adding the condition to the desired field mapping.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;SimpleEntity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;SimpleEntityDisplay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mapper&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SimpleEntity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SimpleEntityDisplay&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;SimpleEntity&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;mappedTo&lt;/span&gt; &lt;span class="nc"&gt;SimpleEntityDisplay&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;withCondition&lt;/span&gt; &lt;span class="nc"&gt;NotBlankStringCondition&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Inline Conditions
&lt;/h2&gt;

&lt;p&gt;Like transformers, conditions can also be added inline using a function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mapper&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SimpleEntity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SimpleEntityDisplay&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;SimpleEntity&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;mappedTo&lt;/span&gt; &lt;span class="nc"&gt;SimpleEntityDisplay&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nf"&gt;withCondition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;originalValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isNullOrBlank&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Annotations Mapping
&lt;/h1&gt;

&lt;p&gt;This specific feature receives lots of hate because it breaks the separation of concerns principle. Agreed, this could be an issue in some applications, but in some use cases where all objects are part of the same application it can also be very useful to configure the mapping logic on top of the object. Check out the &lt;a href="https://shapeshift.krud.dev/api-documentation/annotations"&gt;documentation&lt;/a&gt; and decide for yourself.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Object mapping libraries are not the solution for every application. For small, simple applications using boiler-plate mapping functions are more than enough. But, when developing larger, more complex applications, object mapping libraries can take your code to the next level, saving you development and maintenance time. All of these while reducing the amount of boiler-plate code and overall improving the development experience.&lt;/p&gt;

&lt;p&gt;On a personal note, I used to work with manual mapping functions and was ok with it. It was "just" some simple lines of code. After upgrading our applications to use object mapping as part of our "boiler-plate free" framework (We will discuss that framework at a later time), I can't go back. Now we spend more time on what's important and interesting and almost no time on boring boiler-plate code.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>kotlin</category>
      <category>architecture</category>
      <category>oop</category>
    </item>
  </channel>
</rss>
