<?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>Forem: Sven Hettwer</title>
    <description>The latest articles on Forem by Sven Hettwer (@svettwer).</description>
    <link>https://forem.com/svettwer</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%2Fuser%2Fprofile_image%2F79288%2F50da1b82-409f-434e-a081-817c6f94f333.jpeg</url>
      <title>Forem: Sven Hettwer</title>
      <link>https://forem.com/svettwer</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/svettwer"/>
    <language>en</language>
    <item>
      <title>Don`t try to sell chaos to the management!</title>
      <dc:creator>Sven Hettwer</dc:creator>
      <pubDate>Mon, 09 Jul 2018 03:42:24 +0000</pubDate>
      <link>https://forem.com/svettwer/dont-try-to-sell-chaos-to-the-management-306f</link>
      <guid>https://forem.com/svettwer/dont-try-to-sell-chaos-to-the-management-306f</guid>
      <description>&lt;p&gt;I recently visited a meetup in Düsseldorf where &lt;a href="http://www.russmiles.com"&gt;Russ Miles&lt;/a&gt; was talking about chaos engineering, its techniques, its mindset and the technology that support this awesome way of exploring weaknesses in systems. After the talk ended, it was clear to see that the attending developers were fascinated about these concepts, as was I. There was so much motivation to start testing and experimenting with software systems, it was awesome!&lt;/p&gt;

&lt;p&gt;The next day, when I was thinking about the things I’d learned, I came up with some questions that I could not answer to myself. Fortunately, Russ is a person interested in sharing knowledge and experience. That’s why he offers that his audience should contact him as soon as questions come to their mind. So that is what I did.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sven:&lt;/strong&gt; Hey Russ! I was thinking about your talk last evening. I’m curious how you would explain the worth of chaos engineering or things like Game-Days, where the developers are locked out of business for a whole day, to the management? All these things improve the software quality, but this is nothing you can make money with in a direct way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Russ:&lt;/strong&gt; Hey! So firstly, a “Game Day” can be a lot shorter than a day. In my experience it’s a few hours at most and fits well into the usual ceremonies around your agile process and preferably around retrospectives. So it can be achieved with a minimally increased time investment in comparison to the process you may already be running. Second, when I explain chaos engineering to managers, I use the term “continuous limited scope disaster recovery”. I also point out that software resilience is directly related to money, in most cases, and that this is a proactive, lightweight approach to avoid costly outages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sven:&lt;/strong&gt; Makes sense! But in my experience, even those arguments don’t convince everybody. Some may argue that they never had an outage ever so why should they invest?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Russ:&lt;/strong&gt; Usually, there has been an outage in the near-past and so people are familiar with the potential costs of not investing into resilient software. If that’s the case, I ask about that outage and ask what they do to avoid that and other outages in the future. I also ask how they’re now building up confidence in their systems again. Another important point I mention is that for a small investment they can get big returns. They just have to add a little more discipline through resilience engineering practices.&lt;br&gt;&lt;br&gt;
If they haven’t experienced an outage themselves in their own systems, I bet they have been impacted from an outage in someone else’s system that they depend on. So I use that as a “you wouldn’t want to be them” perspective. In addition, I also have a growing catalogue of production failure stories that I could tell if people are still unconvinced.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sven:&lt;/strong&gt; You mentioned that things like Game-Days fit well into agile processes. So would you say that an agile process is a prerequisite to efficient chaos engineering?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Russ:&lt;/strong&gt; Oh no, not exactly. I’d say that any business-critical system of software development and delivery will gain from improved resilience. If you’re agile, then you might have the sorts of learning loops in place that are critical already, but chaos engineering does not require an agile process, microservices or cloud native. It’s much more broadly applicable than those things. They sometimes help, but they’re not a prerequisite.&lt;br&gt;&lt;br&gt;
And just another remark on arguing for chaos engineering: As a customer, we’ve all experienced an outage at some point. So even if people have never been in touch with a system outage in their business, they know how an outage feels.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sven:&lt;/strong&gt; Maybe that’s a good point to start from, if you have to argue for these things with someone. Something like “What would you think if you would be on the couch to watch a movie but the service is down? And now imagine the mood of your customers with your product if it’s unavailable.”&lt;br&gt;&lt;br&gt;
Russ, that made it a lot clearer for me! Thank you for your time and your thoughts!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Russ:&lt;/strong&gt; No problem at all!&lt;/p&gt;

&lt;p&gt;For me, the most important outcome of this conversation is:&lt;br&gt;&lt;br&gt;
&lt;em&gt;Don’t try to sell chaos to the management!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Better call it “continuous limited scope disaster recovery” and point out that their revenue stream is directly linked to their software. If the software is unstable, your revenue stream is unstable. And if this is not enough to convince the skeptics, show them how they would feel when they are hit by a system outage.&lt;/p&gt;

&lt;p&gt;There are also a few other dos and don’ts Russ is pointing out in his article “&lt;a href="https://medium.com/russmiles/chaos-engineering-for-the-business-17b723f26361"&gt;&lt;em&gt;Chaos Engineering for the Business - 6 Tips for how to explain Chaos Engineering to non-technical stakeholders&lt;/em&gt;&lt;/a&gt;&lt;em&gt;”.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Authors: Sven Hettwer, Russ Miles&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This article is originally published at &lt;a href="https://medium.com/@SvenHettwer/don-t-try-to-sell-chaos-to-the-management-61f21e12a942"&gt;medium.com/@SvenHettwer&lt;/a&gt;&lt;/p&gt;

</description>
      <category>chaosengineering</category>
      <category>interview</category>
      <category>cloudnative</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Arch Linux for Devs</title>
      <dc:creator>Sven Hettwer</dc:creator>
      <pubDate>Sat, 23 Jun 2018 08:58:49 +0000</pubDate>
      <link>https://forem.com/svettwer/arch-linux-for-devs-26dm</link>
      <guid>https://forem.com/svettwer/arch-linux-for-devs-26dm</guid>
      <description>&lt;p&gt;This report is about the experience I've made with Arch Linux as the operating system for a developers workstation. You'll be introduced into the concepts of Arch Linux, followed by a introduction into the main tasks such as package installation and OS maintenance. At the end, I'll discuss why I think that Arch Linux is a great OS for developers, and finish with a conclusion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;First of all, I'd like to avoid the typical OS comparison statements like "Linux is better than Windows", "Mac is better than Linux" or "Windows is better than Mac". If the operating system suites your personal requirements, it is the right choice for you. There is, as in so many aspects in life, no absolute "better" choice.&lt;/p&gt;

&lt;p&gt;Please note that this article is nevertheless based on my personal opinion and may vary from your or others opinions.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Arch Linux?
&lt;/h2&gt;

&lt;p&gt;Arch Linux is a extremely lightweight, fully customizable, &lt;a href="https://en.wikipedia.org/wiki/Rolling_release"&gt;rolling release&lt;/a&gt; Linux distribution which is driven by its community and has been written from scratch. It follows the &lt;a href="https://en.wikipedia.org/wiki/KISS_principle"&gt;KISS principle&lt;/a&gt; which results in the fact that there is no &lt;em&gt;overhead&lt;/em&gt; in the operating system such as a graphical or a commandline installation dialog nor is a configuration tool provided by the distribution itself available. Therefore Arch Linux is targeted on the more experienced Linux user. The simplicity of Arch Linux allows you to build your system exactly as you need it without a reinstall to obtain a new major OS version ever, due to the rolling release attempt. That gives you the opportunity to run your first Arch Linux installation theoretically forever, if you maintain it well.&lt;br&gt;
Different to other distributions, Arch Linux does not ship with a default desktop installation, a default file system or a default tool set. It is &lt;em&gt;just&lt;/em&gt; an operating system. Nothing more and nothing less. That's simplicity, isn't it?&lt;/p&gt;

&lt;p&gt;There are various guides in the &lt;a href="https://wiki.archlinux.org"&gt;official wiki&lt;/a&gt; that help you to setup your system as desired. There are also projects providing distributions based on Arch. One of them is &lt;a href="https://anarchy-linux.org/"&gt;Anarchy Linux&lt;/a&gt;, which I'm personally using. It's basically a Arch Linux with an installation dialog. It's still possible to customize your installation by aborting the installer and do things manually or to uncheck some packages you don't want to be installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Package management
&lt;/h2&gt;

&lt;p&gt;The package manager of Arch Linux is called &lt;em&gt;&lt;a href="https://wiki.archlinux.org/index.php/Pacman"&gt;pacman&lt;/a&gt;&lt;/em&gt;. It's a CLI tool allowing you to install, remove and update the packages on your system. May the packages be self build, downloaded from the official repositories or from the &lt;a href="https://aur.archlinux.org/"&gt;AUR (Arch User Repository)&lt;/a&gt;, where users are able to provide self maintained packages, pacman is your tool to manage them. Let's have a look at the most important commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pacman -Syu&lt;/code&gt;: Update all packages after synchronizing the package repository database&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pacman -S &amp;lt;package-name&amp;gt;&lt;/code&gt; Install a package&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pacman -R &amp;lt;package-name&amp;gt;&lt;/code&gt; Remove a package&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pacman -Qdt&lt;/code&gt; Query the package database and find all packages that are not longer required.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The only slightly uncomfortable task is to install a package from the AUR. These packages have to be build, before you're able to install them. This requires the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download the sources&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd /path/to/the/sources&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Check all files carefully, because AUR repos could potentially contain anything.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;makepkg -si&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another uncomfortable task is to keep your AUR packages up to date, because pacman is not able to do that. So you would have to check the versions of your AUR packages on a regular basis and reinstall them if required.&lt;br&gt;
But don't be scared! &lt;a href="https://wiki.archlinux.org/index.php/AUR_helpers"&gt;AUR helper tools&lt;/a&gt; to the rescue! These tools are capable of managing the official repositories as well as the AUR. I've recently chosen &lt;em&gt;aurman&lt;/em&gt; as my AUR helper, because it is well maintained, well documented, contains a lot of functionality and simply works well. It is also relatively new as its AUR entry has been created at 2018-03-20 22:31. Have a look at the &lt;a href="https://aur.archlinux.org/packages/aurman/"&gt;aurman AUR page&lt;/a&gt; for more details.&lt;br&gt;
&lt;em&gt;To install aurman on a fresh Arch Linux, just install it manually from the AUR as mentioned earlier. If you're interested in some more details, just visit the &lt;a href="https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages"&gt;Arch User Respository wiki entry&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Because aurman has a native pacman integration, you can just use it as you would use pacman but with AUR support.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick edit on 2018-12-28&lt;/strong&gt;:&lt;br&gt;
Polygamma has stopped aurman development: &lt;br&gt;
&lt;em&gt;I am not willing to continue developing aurman for public use. The GitHub issues are closed, I am not interested in feedback, feature requests or bug reports anymore. aurman is going to be developed for myself only from now on, I suggest migrating to yay. &lt;a href="https://github.com/polygamma/aurman/commit/c409feef4c93137c2f0917d8ecdede2d51e06ea9"&gt;source&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
For more information, please have a look at the &lt;a href="https://github.com/polygamma/aurman/blob/master/README.md"&gt;README&lt;/a&gt; on github. &lt;/p&gt;

&lt;p&gt;I migrated to yay and it works great. Thx to &lt;a class="mentioned-user" href="https://dev.to/maxdevjs"&gt;@maxdevjs&lt;/a&gt;
 for pointing out that this blog still recommends aurman. Happy new year everybody! &lt;/p&gt;

&lt;h3&gt;
  
  
  Available packages
&lt;/h3&gt;

&lt;p&gt;One of my biggest concerns has been, that I could be unable to find all the software packages that I need for my daily work or that the packages may be outdated, because Arch Linux is using its own packaging system. As of today, all packages I require where available via the official repositories or the AUR. This also includes software as the IntelliJ Ultimate IDEA. Contradicting to what I once thought, the Arch Linux packages are absolutely up to date, if not bleeding edge. &lt;/p&gt;

&lt;h2&gt;
  
  
  Maintaining your system
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Software updates
&lt;/h3&gt;

&lt;p&gt;As for many other operating systems the most usual maintenance process is installing updates. As mentioned earlier, this can be done easily with one command &lt;code&gt;pacman -Syu&lt;/code&gt; or &lt;code&gt;aurman -Syu&lt;/code&gt; in case that you've chosen aurman. If you install your updates once a week, it wont take long. Currently my updates take ~10 minutes. This excludes the updates where I have to update IntelliJ IDEA. This takes 5-10 min. extra. &lt;br&gt;
Before you start an update, I highly recommend to check &lt;a href="https://www.archlinux.org/"&gt;archlinux.org&lt;/a&gt; for any known issues. As mentioned, Arch Linux is a bleeding edge rolling release distribution. So it might be that some updates require your attention more than others. As of today,  I've had only one update that required manual interaction. The instructions to solve this issue (js52 update) have been well documented on archlinux.org.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backups and Restore
&lt;/h3&gt;

&lt;p&gt;Having backups of your files is one of the most important rules when you work with computers. I think nearly everybody has had a situation where data was lost because of insufficient backup. So, I assume that this lesson has been learned and therefore I'll skip that chapter. The more interesting part, that I want to talk about is creating a backup of your operating system so that you're able to restore your system in case of a dramatic system failure. As always, you've many possibilities to achieve that. Let's discuss some scenarios and possible solutions.&lt;/p&gt;

&lt;h4&gt;
  
  
  Unstable system
&lt;/h4&gt;

&lt;p&gt;Let's pretend, you've updated your system. Now your system is throwing error messages around and is slower as it should be. Identifying the root cause can easily become a tedious task if the update was not only performed for one package but for 10 or 20. So, it would be great to roll back your system, right? No Problem! If you've chosen &lt;a href="https://wiki.archlinux.org/index.php/Btrfs"&gt;BTRFS&lt;/a&gt; as your file system, you're able to create snapshots of your entire filesystem. These snapshots can be restored If you've booted into a restore medium or a rescue partition. &lt;em&gt;Please note that a btrfs snapshot is technically **not&lt;/em&gt;* a backup. It is just a &lt;a href="https://en.wikipedia.org/wiki/Copy-on-write"&gt;copy on write&lt;/a&gt; shadow of your original device.*&lt;br&gt;
Well, to be fair, BTRFS is not Arch Linux exclusive. But it leverages the rolling release concept as any other software package does. Therefore you'll most likely receive bug fixes and improvements earlier than with other distributions.  &lt;/p&gt;

&lt;h4&gt;
  
  
  Fatal system crash
&lt;/h4&gt;

&lt;p&gt;Worst case scenario! HDD/SSD damage. Because you've created backups of your files, it's not that bad, right? You just have to setup your system again, restore your files from backup and everything is fine. Nevertheless, installing all of your required packages and setting up your individual configurations may consume some time. Therefore I recommend to backup these information as well, because what is an operating system more than a bunch of packages and configuration, right? Here are the tools I use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://wiki.archlinux.org/index.php/Etckeeper"&gt;etckeeper&lt;/a&gt;: Creates a git repository for your &lt;code&gt;/etc&lt;/code&gt; folder including fully automated commits after every pacman operation due to lifecycle hooks.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aur.archlinux.org/packages/packup/"&gt;packup&lt;/a&gt;: A simple tool to export the list of installed packages. It also provides a installation functionality, but I would go with aurman here as well.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aur.archlinux.org/packages/dotfiles/"&gt;dotfiles&lt;/a&gt;: A tool to keep track of your dotfiles across multiple systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So a recovery of a system using these tools is really simple: Install Arch Linux, install all packages from your exported package list, restore your config, restore your dotfiles, done!&lt;/p&gt;

&lt;h3&gt;
  
  
  More information
&lt;/h3&gt;

&lt;p&gt;As mentioned earlier, there are tons of information in the &lt;a href="https://wiki.archlinux.org"&gt;official wiki&lt;/a&gt;. This also includes a article about &lt;a href="https://wiki.archlinux.org/index.php/System_maintenance"&gt;system maintainance&lt;/a&gt;. Here you'll find a lot of tools and tasks to keep your system healthy and stable. Please note that not all of the mentioned tasks are required to keep your system stable. Just pick what you think is important to you. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why I think Arch Linux is great for developers
&lt;/h2&gt;

&lt;p&gt;Many of the mentioned aspects in this article are achievable with other distributions as well, but there are some points that make Arch Linux the ideal choice for developers from my point of view.&lt;br&gt;
As developers, we know about software and technology. We know how software works, we know how these technical things come together, we know how to treat software systems. And if we don't know, we're able to learn quickly, because software is our daily business and passion. These aspects in combination with the simplicity and flexibility of Arch Linux is a great combination with a lot of potential to make your day to day work as efficient as possible.&lt;br&gt;&lt;br&gt;
As a rolling release distribution, you've always an up to date system without fearing the end of a LTS period. The software packages are also up to date if not bleeding edge. That means, you don't have to wait until a maintainer decides that a new package version is stable and good to go. You're in charge to maintain your system and customize it as you desire while the maintainance effort is similar to other distributions. You decide, if you want a fully fledged modern desktop environment with all the nice looking effects, or if you want a minimal or CLI driven system unleashing the full computation power of your machine. And if things break? Well, then you know where to search for the issue, because you've setup your system and therefore you know whats running on it.&lt;br&gt;
All this in combination with the active Arch Linux community and the detailed documentation in the &lt;a href="https://wiki.archlinux.org"&gt;official wiki&lt;/a&gt; makes it a great choice for developers in my opinion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As mentioned in the beginning:&lt;br&gt;
&lt;em&gt;If the operating system suites your personal requirements, it is the right choice for you.&lt;/em&gt;&lt;br&gt;
In my case, this is Arch Linux. Not because it brings a new stunning feature or a life changing enhancement to the world of Linux but it brings some different concepts that make sense and improve the way the system works and feels from a users perspective. &lt;/p&gt;

&lt;p&gt;I want my system to be as efficient as possible without missing the comfort of a desktop environment. I also want to be able to work with up to date software. I want my system to be stable and reliable and I want to understand what's going on on it. All of this and nothing can be found with Arch Linux.&lt;br&gt;
With Arch Linux you have a simple, fully customizable, community driven rolling release operating system with a massive ecosystem of software packages and documentation. You’ve everything available that is available in other distributions, but with Arch Linux, you’ve the choice to use it or not. Nevertheless Arch Linux is not for beginners. You should have a solid understanding of Linux systems, before you start. But if you gained that knowledge, you'll be able to use its full potential.&lt;/p&gt;

&lt;p&gt;This article is originally published at &lt;a href="https://labs.consol.de/development/linux/operating-systems/2018/06/18/arch-linux-for-devs.html"&gt;labs.consol.de&lt;/a&gt; at 2018-06-18&lt;/p&gt;

</description>
      <category>development</category>
      <category>linux</category>
      <category>rollingrelease</category>
      <category>experiencereport</category>
    </item>
    <item>
      <title>Database testing with Citrus</title>
      <dc:creator>Sven Hettwer</dc:creator>
      <pubDate>Sat, 23 Jun 2018 08:53:37 +0000</pubDate>
      <link>https://forem.com/svettwer/database-testing-with-citrus-4o0n</link>
      <guid>https://forem.com/svettwer/database-testing-with-citrus-4o0n</guid>
      <description>&lt;p&gt;Database communication is an essential part of many applications, when persistent data storage is required. May it be orders, customer data, product recommendations or product information, if persistent storage is in place, the data contains a certain business value. Therefore it's important that your software handles your persistent storage the right way.&lt;/p&gt;

&lt;p&gt;In this blog post you'll learn how to test your database communication using Citrus. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why would you test your database with Citrus?
&lt;/h2&gt;

&lt;p&gt;Testing database communication at all is not an easy task. There are a lot of things to consider if you want to use a test database and work with it in an effective, automated way.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have to deploy a test database.&lt;/li&gt;
&lt;li&gt;You have costs for additional hardware, licence fees, etc. &lt;/li&gt;
&lt;li&gt;You have to setup your test schemas.&lt;/li&gt;
&lt;li&gt;You have to ensure that the test schema matches the prod schema and vise versa.&lt;/li&gt;
&lt;li&gt;You have to add comples sample data to your schema to test complex use cases.&lt;/li&gt;
&lt;li&gt;Testing your software offline is impossible.&lt;/li&gt;
&lt;li&gt;Testing your software in case of a database failure is nearly impossible.&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You'll find way more challenges to cope depending on your individual infrastructure.&lt;/p&gt;

&lt;p&gt;We thought that all this has to come to an end, so we developed Citrus JDBC!&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;To follow this tutorial, your system should fulfill the following requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;git&lt;/li&gt;
&lt;li&gt;maven&lt;/li&gt;
&lt;li&gt;Java 8&lt;/li&gt;
&lt;li&gt;An IDE of your choice&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;With the upcoming Release of the &lt;strong&gt;citrus framework 2.7.4&lt;/strong&gt;, you'll be able to verify the database communication of your application without setting up a test database server or even schemas!&lt;/p&gt;

&lt;p&gt;The Citrus JDBC integration consists of two essential parts, the &lt;em&gt;Citrus-JDBC-Server&lt;/em&gt; and the &lt;em&gt;Citrus-JDBC-Driver&lt;/em&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fl8kz828gbgo3epctd648.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fl8kz828gbgo3epctd648.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To be able to use the Citrus JDBC integration, you just have to do two things:&lt;br&gt;
1) Exchange the productive JDBC Driver of your application with the Citrus-JDBC-Driver in the test environment.&lt;br&gt;
2) Add the Citrus-JDBC-Server to your test project by adding the &lt;code&gt;citrus-jdbc&lt;/code&gt; dependency.  &lt;/p&gt;

&lt;p&gt;The driver will be available on maven central under &lt;code&gt;com.consol.citrus.citrus-db-driver&lt;/code&gt; while you can find the dependency in the following snippet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.consol.citrus&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;citrus-jdbc&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;${citrus.version}&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Currently Citrus JDBC supports the following features.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validation of:

&lt;ul&gt;
&lt;li&gt;Connections&lt;/li&gt;
&lt;li&gt;Statements&lt;/li&gt;
&lt;li&gt;Prepared Statements&lt;/li&gt;
&lt;li&gt;Callable Statements&lt;/li&gt;
&lt;li&gt;Transactions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Simulating database failure&lt;/li&gt;

&lt;li&gt;Simulating timeouts&lt;/li&gt;

&lt;li&gt;Mocking result sets on requests&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;For detailed information, please have a look at the &lt;a href="http://citrusframework.org/docs/user-guide/" rel="noopener noreferrer"&gt;citrus user guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Please note, that it's also possible to obtain &lt;a href="http://christophd.github.io/citrus/" rel="noopener noreferrer"&gt;snapshot releases of the documentation&lt;/a&gt; as well as nightly builds of Citrus and it's components from the following repository:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;repository&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;consol-labs-snapshots&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;http://labs.consol.de/maven/snapshots-repository/&lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;snapshots&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;enabled&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/enabled&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/snapshots&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;releases&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;enabled&amp;gt;&lt;/span&gt;false&lt;span class="nt"&gt;&amp;lt;/enabled&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/releases&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/repository&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;em&gt;Because this post is about a snapshot version of Citrus, some examples and outputs may look slightly differently, when the version is finally released.&lt;/em&gt;&lt;br&gt;
As for many other use cases, the &lt;a href="https://github.com/christophd/citrus-samples" rel="noopener noreferrer"&gt;citrus-examples&lt;/a&gt; project contains examples concerning the jdbc implementation. So in the first step, please clone the citrus-examples project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/christophd/citrus-samples.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;If you are new to the &lt;a href="https://github.com/christophd/citrus-samples" rel="noopener noreferrer"&gt;citrus-examples&lt;/a&gt; project, please have a look at the &lt;a href="http://www.citrusframework.org/samples/run/" rel="noopener noreferrer"&gt;Running the examples&lt;/a&gt; guide.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;Assumed that you performed the examples setup, let's execute the samples!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mvn clean verify &lt;span class="nt"&gt;-f&lt;/span&gt; citrus-samples/sample-jdbc/pom.xml &lt;span class="nt"&gt;-Dembedded&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;...]

CITRUS TEST RESULTS

ExecuteQueryIT.testCreateTable ................................. SUCCESS
ExecuteQueryIT.testDelete ...................................... SUCCESS
ExecuteQueryIT.testDropTable ................................... SUCCESS
ExecuteQueryIT.testSelect ...................................... SUCCESS
TodoListIT.selectTodoEntry ..................................... SUCCESS
TodoListIT.testAddTodoEntry .................................... SUCCESS
TodoListIT.testException ....................................... SUCCESS
TodoListIT.testIndexPage ....................................... SUCCESS

TOTAL: 8
SKIPPED:       0 &lt;span class="o"&gt;(&lt;/span&gt;0.0%&lt;span class="o"&gt;)&lt;/span&gt;
FAILED:        0 &lt;span class="o"&gt;(&lt;/span&gt;0.0%&lt;span class="o"&gt;)&lt;/span&gt;
SUCCESS:       8 &lt;span class="o"&gt;(&lt;/span&gt;100.0%&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="nt"&gt;------------------------------------------------------------------------&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that you've executed your first database integration tests, lets have a look on how they're written.&lt;br&gt;
&lt;em&gt;If you're completely new to Citrus, it might be helpful to start with the setup guides on &lt;a href="http://citrusframework.org/" rel="noopener noreferrer"&gt;citrusframework.org&lt;/a&gt; to understand the basic concepts before you proceed.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This test performs a &lt;code&gt;GET&lt;/code&gt; request to our SUT API, asking for the list of todo entries. Afterwards, when the &lt;code&gt;SELECT&lt;/code&gt; statement hits the database, a result set is generated and sent to the SUT as query result. Finally the receive step of the http client verifies, that the SUT produces the correct data representation - here in XHTML.&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;TodoListIT&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestNGCitrusTestDesigner&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;JdbcServer&lt;/span&gt; &lt;span class="n"&gt;jdbcServer&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;HttpClient&lt;/span&gt; &lt;span class="n"&gt;todoClient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="nd"&gt;@CitrusTest&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;selectTodoEntry&lt;/span&gt;&lt;span class="o"&gt;(){&lt;/span&gt;
        &lt;span class="n"&gt;variable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"todoName"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"citrus:concat('todo_', citrus:randomNumber(4))"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;variable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"todoDescription"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Description: ${todoName}"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;todoClient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/todolist"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fork&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;accept&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"text/html"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SELECT id, title, description FROM todo_entries"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

        &lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;messageType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MessageType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;JSON&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;dataSet&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="s"&gt;"\"id\": \""&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomUUID&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()&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="s"&gt;"\"title\": \"${todoName}\","&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                    &lt;span class="s"&gt;"\"description\": \"${todoDescription}\","&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                    &lt;span class="s"&gt;"\"done\": \"false\""&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="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;todoClient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;OK&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;messageType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MessageType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;XHTML&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;xpath&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"(//xh:li[@class='list-group-item']/xh:span)[last()]"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"${todoName}"&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;As you can see in the highlighted sections, you're able to configure the database behavior, including the returned result sets, using the &lt;code&gt;receive&lt;/code&gt; and &lt;code&gt;send&lt;/code&gt; actions of the JDBC-Server endpoint. This empowers you to test your system without additional test-database deployments, test-schemas or other operative overhead. &lt;/p&gt;

&lt;p&gt;You may ask yourself, where the &lt;code&gt;todoClient&lt;/code&gt; and the &lt;code&gt;jdbcServer&lt;/code&gt; are coming from. These components are specified in a spring configuration class.&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;@Configuration&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;EndpointConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;HttpClient&lt;/span&gt; &lt;span class="nf"&gt;todoClient&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="nc"&gt;CitrusEndpoints&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requestUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:8080"&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;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;JdbcServer&lt;/span&gt; &lt;span class="nf"&gt;jdbcServer&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="nc"&gt;CitrusEndpoints&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jdbc&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;databaseName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"testdb"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3306&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000L&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;autoStart&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;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;h2&gt;
  
  
  Citrus-JDBC Features
&lt;/h2&gt;

&lt;p&gt;Now that you know how these kind of tests are setup, lets talk about the feature set you receive by adding the &lt;code&gt;citrus-jdbc&lt;/code&gt; dependency to your project. Due to the fact that all tests are setup similarly, I'll leave the redundant part out of the examples and focus on the feature related parts.&lt;br&gt;
&lt;em&gt;All features are also available in the Citrus XML DSL. You can find the related examples in the &lt;a href="https://github.com/christophd/citrus-samples" rel="noopener noreferrer"&gt;Citrus examples&lt;/a&gt; project.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Simulating database failures
&lt;/h3&gt;

&lt;p&gt;One of the core concepts of Citrus JDBC is the distinction between a &lt;code&gt;success&lt;/code&gt; and an &lt;code&gt;error&lt;/code&gt; concerning database operations. This concept makes it incredibly easy to simulate a database failure after a certain message has been received by the &lt;code&gt;jdbcServer&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="n"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"@startsWith("&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="s"&gt;"'INSERT INTO todo_entries (id, title, description, done) "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="s"&gt;"VALUES (?, ?, ?, ?)')@"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Something went wrong"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the message has been sent from the Citrus-JDBC-Server to the Citrus-JDBC-Driver, the SUT receives the database failure as an &lt;code&gt;SQLException&lt;/code&gt; and is then in charge to handle it. Afterwards you're able to validate the behavior of your SUT by using other Citrus components such as a Citrus HTTP Client.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Prepared/Callable Statements
&lt;/h3&gt;

&lt;p&gt;Even if prepared statements and callable statements are for different database operations and use cases, they share a similar workflow from the API perspective.&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="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prepareStatement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"INSERT INTO todo_entries (id, title, description, done) VALUES (?, ?, ?, ?)"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prepareCall&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{CALL limitedToDoList(?)}"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both kinds of statements are created from a JDBC connection with a SQL command expression as &lt;code&gt;String&lt;/code&gt; parameter. Because of that, we're able to verify them in the same way as regular statements. The only difference between prepared and callable statements compared to regular statements is, that the parameters for the concrete call are attached to the query string for validation purposes.&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="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;todoClient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api/todolist/1"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fork&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="n"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{CALL limitedToDoList(?)} - (1)"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;messageType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MessageType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;JSON&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;dataSet&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="s"&gt;"\"id\": \"${todoId}\","&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="s"&gt;"\"title\": \"${todoName}\","&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="s"&gt;"\"description\": \"${todoDescription}\","&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="s"&gt;"\"done\": \"false\""&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the API call path parameter &lt;code&gt;api/todolist/1&lt;/code&gt; is reflected within the statement execution validation &lt;code&gt;"{CALL limitedToDoList(?)} - (1)"&lt;/code&gt;. Multiple parameters would look as following &lt;code&gt;"{CALL limitedToDoList(?, ?, ?)} - (1,2,3)"&lt;/code&gt;. Of course you're also able to work with the regular Citrus matcher as always. &lt;/p&gt;

&lt;h3&gt;
  
  
  Transaction handling
&lt;/h3&gt;

&lt;p&gt;When it comes to complex modifications of your database, transactions are commonly used. Citrus is able to verify the behavior of your system under test concerning start, commit and rollback actions of transactions. The verification of transactions has to be enabled in the server Citrus-JDBC-Server configuration.&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;@Configuration&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;EndpointConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;JdbcServer&lt;/span&gt; &lt;span class="nf"&gt;jdbcServer&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="nc"&gt;CitrusEndpoints&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jdbc&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;databaseName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"testdb"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3306&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000L&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;autoStart&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;autoTransactionHandling&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&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;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a &lt;code&gt;JdbcServer&lt;/code&gt; endpoint configured that way, you are able to state and verify the transactional behavior of your SUT within your test cases.&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="n"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;startTransaction&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

&lt;span class="n"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"@startsWith('INSERT INTO todo_entries (id, title, description, done) VALUES (?, ?, ?, ?)')@"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;rowsUpdated&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

&lt;span class="n"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commitTransaction&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because of the ease of creating database failures, you could also cause failed transactions and check whether your SUT performs a proper rollback.&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="n"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;startTransaction&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

&lt;span class="n"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"@startsWith('INSERT INTO todo_entries (id, title, description, done) VALUES (?, ?, ?, ?)')@"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not execute something"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

&lt;span class="n"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rollbackTransaction&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even the absolute worst case, a rollback failure, could be simulated with nothing more than another send statement.&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="n"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;startTransaction&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

&lt;span class="n"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"@startsWith('INSERT INTO todo_entries (id, title, description, done) VALUES (?, ?, ?, ?)')@"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not execute something"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

&lt;span class="n"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rollbackTransaction&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not perform database rollback"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Timeout simulation
&lt;/h3&gt;

&lt;p&gt;Simulating timeouts with a real database can be tricky if not impossible to achieve. With Citrus, you just configure your server to validate connection statements but leave them out of the test.&lt;/p&gt;

&lt;p&gt;Here is a server configuration enforcing connection validation.&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;@Bean&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;JdbcServer&lt;/span&gt; &lt;span class="nf"&gt;jdbcServer&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="nc"&gt;CitrusEndpoints&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jdbc&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;databaseName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"testdb"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3306&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000L&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;autoStart&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;autoConnect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&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;The following test does not accept the connection attempt from the driver because the receive instruction for the server is missing. Therefore the connection will timeout, because no answer will be sent to the SUT. Nevertheless the Citrus HTTP client expects that the SUT responds as expected.&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="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;todoClient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/todolist"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fork&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;contentType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"application/x-www-form-urlencoded"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"title=${todoName}&amp;amp;description=${todoDescription}"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;todoClient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;I_AM_A_TEAPOT&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Advanced validations
&lt;/h3&gt;

&lt;p&gt;There are some advanced validation options to verify the very basic behavior of your SUT concerning database operations like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opening and closing connection&lt;/li&gt;
&lt;li&gt;Creating and closing statements&lt;/li&gt;
&lt;li&gt;Performing transactions (seen in the previous section)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because most modern application use some kind of framework for their database operations, one as a developer is not responsible for managing these basic JDBC driver interactions, but in case you want to be sure, you're absolutely able to! As for transactions, connection and statement validation has to be activated via configuration of the &lt;code&gt;JdbcServer&lt;/code&gt; endpoint.&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;@Configuration&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;EndpointConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;JdbcServer&lt;/span&gt; &lt;span class="nf"&gt;jdbcServer&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="nc"&gt;CitrusEndpoints&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jdbc&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;databaseName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"testdb"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3306&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000L&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;autoStart&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;autoConnect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;autoCreateStatement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&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;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the &lt;code&gt;JdbcServer&lt;/code&gt; instance will validate the connection related operations including statement creation.&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="n"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;openConnection&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

&lt;span class="n"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createCallableStatement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{CALL limitedToDoList(?)}"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

&lt;span class="n"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{CALL limitedToDoList(?)} - (1)"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;messageType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MessageType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;JSON&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;dataSet&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="n"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;closeStatement&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

&lt;span class="n"&gt;receive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jdbcServer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;closeConnection&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this blog post you have executed your first citrus database tests, learned how these tests are setup, how to verify your database communication using the features of &lt;code&gt;citrus-jdbc&lt;/code&gt; including low level JDBC driver related operations. This empowers you to get rid of most of your test database deployments by using Citrus. If you are interested in further readings, I highly recommend you to visit the following links. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://citrusframework.org/" rel="noopener noreferrer"&gt;Citrus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://christophd.github.io/citrus/" rel="noopener noreferrer"&gt;Citrus documentation snapshots&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/christophd/citrus" rel="noopener noreferrer"&gt;Citrus on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/christophd/citrus-samples" rel="noopener noreferrer"&gt;Citrus examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.citrusframework.org/samples/run/" rel="noopener noreferrer"&gt;Running Citrus examples&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article is originally published at &lt;a href="https://labs.consol.de/development/citrus/2018/03/01/database-testing-with-citrus.html" rel="noopener noreferrer"&gt;labs.consol.de&lt;/a&gt; at 2018-03-01&lt;/p&gt;

</description>
      <category>citrus</category>
      <category>integrationtests</category>
      <category>database</category>
      <category>jdbc</category>
    </item>
    <item>
      <title>Automated debugging with git</title>
      <dc:creator>Sven Hettwer</dc:creator>
      <pubDate>Sat, 23 Jun 2018 08:40:33 +0000</pubDate>
      <link>https://forem.com/svettwer/automated-debugging-with-git-2pod</link>
      <guid>https://forem.com/svettwer/automated-debugging-with-git-2pod</guid>
      <description>&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F0zfijln81q2uf624mlz9.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F0zfijln81q2uf624mlz9.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine your're working on a bigger feature in a complex piece of software. Your implementation is complete, all tests in scope turned green and you push your changes for integration testing. Then, some integration tests from a completely different module fail and you have no clue which change may have caused this. Now you start analyzing the issue. Probing your commits by hand would end up in a very tedious process for sure. Thankfully &lt;em&gt;git&lt;/em&gt; can do all the work for you, while you enjoy a cup of coffee.&lt;/p&gt;

&lt;p&gt;The high-level command &lt;code&gt;git bisect&lt;/code&gt; allows you to automatically run a specified test procedure, while it's crawling through your commit history to find the bad revision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;To do the hands-on part, the following setup is required on your local machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;Java 8&lt;/li&gt;
&lt;li&gt;Maven&lt;/li&gt;
&lt;li&gt;Bash (Cygwin on Windows)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is git bisect?
&lt;/h2&gt;

&lt;p&gt;The official description of the &lt;a href="https://git-scm.com/docs/git-bisect" rel="noopener noreferrer"&gt;git-bisect documentation&lt;/a&gt; states:&lt;br&gt;
&lt;em&gt;Use binary search to find the commit that introduced a bug.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So what does that mean?&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fr6x5ao18ihip8mhzv9kx.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fr6x5ao18ihip8mhzv9kx.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's say you have a bunch of commits, and you know that, at some point, your software was okay. Now, your software is broken, which means, that you introduced a bug somewhere during your development. What &lt;code&gt;git bisect&lt;/code&gt; does is, it divides the revision graph into a &lt;em&gt;good&lt;/em&gt; part and a &lt;em&gt;bad&lt;/em&gt; part by testing specific commits chosen by a binary search. Based on the result of the tests, git navigates towards the broken commit. After a few iterations, git will be able to identify the revision that introduced the issue.&lt;/p&gt;
&lt;h3&gt;
  
  
  The basic git bisect workflow
&lt;/h3&gt;

&lt;p&gt;The workflow of &lt;code&gt;git bisect&lt;/code&gt; consists of two major steps. At first, you have to specify a range of revisions, limited by a &lt;em&gt;good&lt;/em&gt; and a &lt;em&gt;bad&lt;/em&gt; revision. These revisions can be referenced as revision hash, tag or any other git revision selector. At second, the bisect process starts and git automatically performs a checkout of the first revision to test. After passing the result of the test to back to git, by executing &lt;code&gt;git bisect good&lt;/code&gt; in case of a success or &lt;code&gt;git bisect bad&lt;/code&gt; in case of a failure, the next revision will be chosen. The second step will be repeated until the first broken revision has been found.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fo4ts34nkm5blcgg2fbc6.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fo4ts34nkm5blcgg2fbc6.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Manual git bisect
&lt;/h2&gt;

&lt;p&gt;Now that you know about the idea and the workflow, let's continue with the hands-on. At first, checkout the &lt;a href="https://github.com/svettwer/git-bisect-examples" rel="noopener noreferrer"&gt;repository from GitHub&lt;/a&gt; containing the example project. As you can see, the repository contains three folders:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cake-factory: A sample spring boot web service containing some issues to find&lt;/li&gt;
&lt;li&gt;simple-bisect: A reference how to manually use git-bisect &lt;em&gt;&amp;lt;- This is what we'll do now&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;automated-bisect: A reference how to use automated bisect including a sample script&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let's try to build the cake-factory by executing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mvn &lt;span class="nt"&gt;-f&lt;/span&gt; ./cake-factory/pom.xml clean &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fya206dpbq4jxcry18n64.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fya206dpbq4jxcry18n64.png"&gt;&lt;/a&gt;&lt;br&gt;
You'll recognize, that the build was not successful, because of a failed &lt;a href="http://citrusframework.org/" rel="noopener noreferrer"&gt;Citrus&lt;/a&gt; integration test. Now, let's find out, where we introduced the bug.&lt;/p&gt;

&lt;p&gt;As shown in the workflow, we've to setup the bisect scenario first. Therefore we have to find a &lt;em&gt;good&lt;/em&gt; and a &lt;em&gt;bad&lt;/em&gt; revision to define the borders of the analysis. Both revisions are easy to find. The &lt;em&gt;good&lt;/em&gt; revision is most likely the revision, you branched from. The &lt;em&gt;bad&lt;/em&gt; revision is HEAD, due to the fact that your tests are failing now. Nevertheless, for our example we'll use two prepared tags &lt;em&gt;stable&lt;/em&gt; and &lt;em&gt;broken&lt;/em&gt; from the repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git bisect start &lt;span class="c"&gt;# start the bisect procedure&lt;/span&gt;
git bisect bad broken &lt;span class="c"&gt;# label the *bad* commit&lt;/span&gt;
git bisect good stable &lt;span class="c"&gt;# label the *good* commit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or if you want to use the shorter version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git bisect start broken stable &lt;span class="c"&gt;# start the procedure and label the *good* and *bad* commit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, that your bisect has been started, git has chosen a commit to test and provides the commit message as well as an estimation of the required iterations.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4om9i3rtdqhsti0r1d3h.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4om9i3rtdqhsti0r1d3h.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By not later than now, you should have figured out a test strategy to identify the root cause of your problem. In our case a integration test failed. Therefore we're concentrating our debugging efforts on integration tests. The setup of the cake-factory allows us to skip unit tests and start right away with the integration tests, by setting the property &lt;code&gt;skip.unit.test=true&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mvn clean verify &lt;span class="nt"&gt;-f&lt;/span&gt; ./cake-factory/pom.xml &lt;span class="nt"&gt;-Dskip&lt;/span&gt;.unit.tests&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4hwha3x7hh5jtl6lloxe.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4hwha3x7hh5jtl6lloxe.png"&gt;&lt;/a&gt;&lt;br&gt;
In this revision, everything is okay and the build was successful. Now we have to report this result to git&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git bisect good &lt;span class="c"&gt;# tells git that the current revision is okay&lt;/span&gt;
&lt;span class="c"&gt;#If the test would have been failed, you would have used 'git bisect bad'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on our reporting, git has chosen the next revision to check.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvp3wwglhk2a6n9vx9gop.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvp3wwglhk2a6n9vx9gop.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you have to repeat the testing and reporting procedure. After some iterations, you'll find the following commit causing the problem.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fu668g59o1arvqhsphicn.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fu668g59o1arvqhsphicn.png"&gt;&lt;/a&gt;&lt;br&gt;
Note the revision hash of the broken commit and don't forget to close your bisect session.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git bisect reset
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you look into the code of that revision, you'll find out that the default cake, delivered by the cake services, has been changed to &lt;em&gt;vanilla&lt;/em&gt; as stated in the commit message, but the integration test has not been adapted.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcm5kokw31wak6krjrmda.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcm5kokw31wak6krjrmda.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Automated git bisect
&lt;/h2&gt;

&lt;p&gt;As you may have recognized, the manual execution of the bisect steps produces some overhead and is a repetitive task. This increases, if you work in more complex projects with multiple modules involved. Thankfully &lt;code&gt;git bisect&lt;/code&gt; contains a sub command that allows us to execute a specific command or a scripted test procedure with automated reporting of the result. This does not only reduce the required amount of time but also the possibility of mistakes while repeating the steps by hand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git bisect run &amp;lt;&lt;span class="nb"&gt;command &lt;/span&gt;to execute&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To report the result of the test to git, your command or script has to fulfill the following contract:&lt;br&gt;
&lt;em&gt;If the test was successful, the executed command delivers the return code 0, otherwise a return code other that 0 is returned.&lt;/em&gt;&lt;br&gt;
Due to the fact that you just have to fulfill this contract, you could also do some more advanced testing logic using python, or even java. Nevertheless I would suggest to be pragmatic and keep the test simple.&lt;/p&gt;
&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Let us return to practice. If not already done during the previous section, please checkout the &lt;a href="https://github.com/FMAOuroboros/git-bisect-examples" rel="noopener noreferrer"&gt;repository from GitHub&lt;/a&gt; containing the example project. In the "automated-bisect" folder, you'll find a &lt;em&gt;findBug.sh&lt;/em&gt; bash script, that contains the test procedure from the "Manual git bisect" section as code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

mvn clean verify &lt;span class="nt"&gt;-f&lt;/span&gt; ./cake-factory/pom.xml &lt;span class="nt"&gt;-Dskip&lt;/span&gt;.unit.tests&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To execute the automated test now, just prepare a bisect environment and pass the script to &lt;code&gt;git bisect run&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git bisect start broken stable
git bisect run sh automated-bisect/findBug.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, if you have a one line command as in &lt;em&gt;findBug.sh&lt;/em&gt;, you could also pass the command directly to &lt;code&gt;git bisect run&lt;/code&gt; as long as the passed command fulfills the contract.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git bisect start broken stable
git bisect run mvn clean verify &lt;span class="nt"&gt;-f&lt;/span&gt; ./cake-factory/pom.xml &lt;span class="nt"&gt;-Dskip&lt;/span&gt;.unit.tests&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the process has been finished, git will show you the first bad commit as known from the manual part.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fbrb23h73q7ogaojkpecf.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fbrb23h73q7ogaojkpecf.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Tips and Tricks
&lt;/h2&gt;
&lt;h3&gt;
  
  
  About git bisect and TDD
&lt;/h3&gt;

&lt;p&gt;If you're following the TDD life cycle to develop your software, you may have some troubles using git-bisect, because your software alternates between a erroneous and a functional sate from a software test perspective. As soon as you specified a new test, your software becomes unstable. If you would execute a simple &lt;code&gt;mvn clean install&lt;/code&gt; in such a situation, &lt;code&gt;git bisect&lt;/code&gt; would not find the revision containing the root cause of your problem, because it is confused by the failed builds caused by your TDD tests. This can also be shown with our &lt;em&gt;cake-factory&lt;/em&gt; example, by removing &lt;code&gt;skip.unit.tests=true&lt;/code&gt; from the maven instruction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git bisect start broken stable
git bisect run mvn clean verify &lt;span class="nt"&gt;-f&lt;/span&gt; ./cake-factory/pom.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;git bisect&lt;/code&gt; will react on every single unit test that is failing. This leads to a result as well, but it has nothing to do with the root cause of the issue we were looking for.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Feem9nba39j6q64xlorp4.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Feem9nba39j6q64xlorp4.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup you test scenario wisely
&lt;/h3&gt;

&lt;p&gt;As you have seen in the section "About git bisect and TDD", a test scenario which is not restrictive enough, returns misleading results. Therefore it's important to create a test scenario, that suites your situation. Here are some bullet points that might help you avoiding pitfalls.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Keep your tests small&lt;/em&gt;
Test only what's necessary and relates directly to the issue. This will lead to the correct result and reduces the amount of time for your tests to run.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Know your dependencies&lt;/em&gt;
If the failing test depends on a different module, that has changed during development, keep in mind that you have to rebuild the dependency in every iteration before starting the test.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Automate your tests&lt;/em&gt;
If you do things more than once, automate them! Don't execute your tests manually. It's a repetitive task that consumes a lot of time. Script you test and let &lt;code&gt;git bisect run&lt;/code&gt; do the rest.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Use common "bad" and "good" candidates&lt;/em&gt;
Don't waste your time on thinking about the most efficient borders for your analysis. Because &lt;code&gt;git bisect run&lt;/code&gt; will do the job for you, one iteration more or less is not important at all.

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;bad&lt;/em&gt; candidate: mostly &lt;em&gt;HEAD&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;good&lt;/em&gt; candidates:&lt;/li&gt;
&lt;li&gt;The revision you branched from&lt;/li&gt;
&lt;li&gt;The last released version of your software&lt;/li&gt;
&lt;li&gt;The last revision of your branch that was build successfully. (E.g. last nightly)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;As you have seen, git bisect is a powerful tool to find broken commits within your git history. You're able to define a range of revisions that will be checked automatically. If you'd like to learn more about &lt;em&gt;git bisect&lt;/em&gt;, please visit the following links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/docs/git-bisect" rel="noopener noreferrer"&gt;git-bisect documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/book/en/v2/Git-Tools-Debugging-with-Git" rel="noopener noreferrer"&gt;Debugging with git&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article is originally published at &lt;a href="https://labs.consol.de/development/git/2018/01/12/automated-debugging-with-git.html" rel="noopener noreferrer"&gt;labs.consol.de&lt;/a&gt; at 2018-01-12&lt;/p&gt;

</description>
      <category>git</category>
      <category>debugging</category>
      <category>automation</category>
      <category>development</category>
    </item>
    <item>
      <title>Traveling through the Arch — Vol. 4</title>
      <dc:creator>Sven Hettwer</dc:creator>
      <pubDate>Wed, 01 Nov 2017 12:58:18 +0000</pubDate>
      <link>https://forem.com/svettwer/traveling-through-the-arch--vol-4-oe4</link>
      <guid>https://forem.com/svettwer/traveling-through-the-arch--vol-4-oe4</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yYridGaZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AAEwB_sQ0eZpf3n-lxLYT4g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yYridGaZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AAEwB_sQ0eZpf3n-lxLYT4g.png" alt=""&gt;&lt;/a&gt;My Desktop — Background picture by &lt;a href="https://twitter.com/C2Wtweets"&gt;ChaseOnTwoWheels&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hey folks! It has been a while since I was able to blog. But know, let’s get together for the final episode of “Traveling through the Arch”. This time, we’ll have a look at system customization, system maintenance and a résumé about my experience with Arch Linux™ so far.&lt;/p&gt;

&lt;h4&gt;
  
  
  System customization
&lt;/h4&gt;

&lt;p&gt;I took me some time to find out how to talk about system customization, because it’s &lt;em&gt;custom&lt;/em&gt; and depends on your requirements. Therefore there is not “the ultimate system” I can recommend to you. At this point it’s about you to find out what kind of system you want to build and what you really need and want. So instead of giving recommendations, let me just point out the &lt;a href="https://wiki.archlinux.org/index.php/General_recommendations"&gt;General recommendations&lt;/a&gt; section of the Arch documentation. It’s a good spot to start from. From that point you could build everything from a minimal installation up to a fully fledged desktop environment.&lt;/p&gt;

&lt;h4&gt;
  
  
  System maintenance
&lt;/h4&gt;

&lt;p&gt;System maintenance was one of my biggest concerns when I started with Arch Linux™. Because the software is distributed in a rolling release it could absolutely be possible to install an update that crashes your system. To prevent those situations, I imagined that I would have to read a lot of articles and patch notes to determine whether a particular upgrade would destabilize my system. Luckily, this is not the case. But nevertheless you better secure your system to be able to solve such a situation as fast as possible.&lt;/p&gt;

&lt;p&gt;There is a &lt;a href="https://wiki.archlinux.org/index.php/System_maintenance"&gt;big article in the Arch Linux™ wiki&lt;/a&gt; talking about that topic. Basically it all comes down to one command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pacman -Syu
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;S
Synchronizes your system with the remote repository&lt;/li&gt;
&lt;li&gt;y
Updating the package database&lt;/li&gt;
&lt;li&gt;u
Filtering the package list for outdated packages.
Those are the packages you want to update&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But that’s not everything you should do. I’ve installed several additional programs to help me maintaining my system stability.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://aur.archlinux.org/packages/packup/"&gt;packup&lt;/a&gt;
A simple terminal based tool to backup your pacman list of installed packages. It’s not only possible to save but also to restore from a given list of packages. So if everything goes wrong, you still have your list of installed packages to start a new installation or try a recovery.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aur.archlinux.org/packages/pakbak-git/"&gt;pakbak&lt;/a&gt;
A tool to backup your pacman database. This is similar to packup but stores much more data. In addition there is a pakbak.service specification so that this tool creates a backup whenever your system starts. Unfortunately the scripts contain some bugs and the service definition is not 100% complete. Therefore I experienced some problems using this tool. Another unfortunate fact is, that the maintainer does not react to my issues so far. Nevertheless it’s a cool attempt and if the maintainer does not answer my requests in the near future, I’ll think about forking that project and maintain it myself.&lt;/li&gt;
&lt;li&gt;etckeeper
A tool using a scm to safe your configs before and after installing packages via pacman. So you’re always able to switch to the last running config by just checking out the correct version.&lt;/li&gt;
&lt;li&gt;btrfs subvolume snapshots of my home
This allows me to track the changes of my home directory without storing tons of data on external drives. In case I did some stupid things with my data, I just recover from my last valid snapshot. There are some tools creating snapshots of the desired subvolume based on certain events. One more popular solution is &lt;a href="https://wiki.archlinux.org/index.php/Snapper"&gt;Snapper&lt;/a&gt; but the btrfs developer are working on their own solution called &lt;a href="https://btrfs.wiki.kernel.org/index.php/Autosnap"&gt;autosnap&lt;/a&gt; which is currently not part of the upstream. Nevertheless this does not secure your data to 100%, because it stays at the same drive. A incremental chronological backup system is also required if you ask me.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even if it comes to system maintenance, you’ve a ton of options and possibilities. You don’t have to use a certain backup solution someone created for a given problem. Just set everything up as you want and as you think it’s useful.&lt;/p&gt;

&lt;h4&gt;
  
  
  Résumé
&lt;/h4&gt;

&lt;p&gt;Now that I work Arch Linux™ on a daily basis for more than a month, I’m absolutely happy that I decided to switch over from Xubuntu. I’ve learned incredibly much about Linux and how everything works together, I’ve a truly minimal system where I can feel that it runs faster than a Xubuntu would.&lt;br&gt;&lt;br&gt;
The System is totally stable and I feel that I could really restore it, if something breaks. This is something that I’ve never experienced with all the distributions I’ve used. All software packages I need are available from the official repositories or from the AUR. In addition, I’ve the feeling that I’m really &lt;em&gt;free&lt;/em&gt; to setup my system as I want without missing up to date software.&lt;br&gt;&lt;br&gt;
So in case you have not tried Arch Linux™ until know, I would like to recommend it to you. One told me once &lt;em&gt;“If you make the switch, you’ll never switch back”&lt;/em&gt; . Sir, you’ve been right!&lt;/p&gt;

&lt;p&gt;This article is originally published at &lt;a href="https://medium.com/@SvenHettwer/traveling-through-the-arch-vol-4-77fc924fb612"&gt;medium.com/@SvenHettwer&lt;/a&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>experience</category>
      <category>archlinux</category>
    </item>
    <item>
      <title>Traveling through the Arch — Vol. 3</title>
      <dc:creator>Sven Hettwer</dc:creator>
      <pubDate>Wed, 11 Oct 2017 11:01:26 +0000</pubDate>
      <link>https://forem.com/svettwer/traveling-through-the-arch--vol-3-ii4</link>
      <guid>https://forem.com/svettwer/traveling-through-the-arch--vol-3-ii4</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JYR9lLqW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/637/1%2A8xkCMdxI6Dy2EL1UzBH18A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JYR9lLqW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/637/1%2A8xkCMdxI6Dy2EL1UzBH18A.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Welcome back to the third issue of “Traveling though the Arch”. The &lt;a href="https://dev.to/svettwer/traveling-through-the-arch--vol-2-3d43-temp-slug-3313923"&gt;last post&lt;/a&gt; was about a Anarchy Linux installation using the installer from &lt;a href="http://arch-anywhere.org"&gt;arch-anywhere.org&lt;/a&gt;. This time, we’ll install a basic Arch Linux™ by our own hands without any predefined installer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Requirements
&lt;/h3&gt;

&lt;p&gt;To follow this guide, I would like to recommend the following setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Virtual machine (VirtualBox, KVM, etc.)&lt;/li&gt;
&lt;li&gt;A downloaded &lt;a href="https://www.archlinux.org/download/"&gt;Arch Linux™ iso image&lt;/a&gt; to install the OS from.&lt;/li&gt;
&lt;li&gt;A web browser to read the instructions. I guess you‘ll have one when you’re reading this article ;-)&lt;/li&gt;
&lt;li&gt;10–60 minutes of time depending on the level of detail you’re looking for&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;At first, let me point out, that I’ll not cover every step of the installation in this article but only some of the more interesting parts. You can find the whole installation process in my &lt;a href="https://github.com/FMAOuroboros/Arch-Installation"&gt;Arch-Installation GitHub repository&lt;/a&gt;, where every command is commented. I separated the installation into three major steps just as the official installation guide does.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a bootable USB Stick
&lt;em&gt;Just in case you want to install it on a real machine&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Installing a very basic Arch Linux™&lt;/li&gt;
&lt;li&gt;Installing everything else on top
&lt;em&gt;Will be covered in the next episode&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This structure will be represented in the GitHub repository as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a bootable USB Stick
&lt;/h3&gt;

&lt;p&gt;Under Linux, there is nothing easier than that!&lt;br&gt;&lt;br&gt;
&lt;em&gt;Disclaimer!&lt;br&gt;&lt;br&gt;
If you use dd, please be careful! You can easily erase your disks, if you set&lt;/em&gt; &lt;strong&gt;&lt;em&gt;of&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;to the wrong device.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dd bs=4M if=/path/to/archlinux.iso of=/dev/sdX status=progress &amp;amp;&amp;amp; sync
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;dd
A tool to copy files byte by byte.&lt;/li&gt;
&lt;li&gt;bs=4M
Telling dd to read/write 4M byte at a time.&lt;/li&gt;
&lt;li&gt;if
Stands for &lt;strong&gt;i&lt;/strong&gt; nput  &lt;strong&gt;f&lt;/strong&gt; ile.&lt;/li&gt;
&lt;li&gt;of
Stands for &lt;strong&gt;o&lt;/strong&gt; utput  &lt;strong&gt;f&lt;/strong&gt; ile.&lt;/li&gt;
&lt;li&gt;status=progress
Limits the output of the output to transfer statistics.&lt;/li&gt;
&lt;li&gt;&amp;amp;&amp;amp;
An logical &lt;em&gt;and&lt;/em&gt; operator. Within the context of this command: If &lt;em&gt;dd&lt;/em&gt; was successful, please also execute &lt;em&gt;sync.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;sync
Tells the system to write cached data to persistent storage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re not familiar with dd or the way that Linux handles devices, please use a tool like the &lt;em&gt;Startup Disk Creator&lt;/em&gt; or one of the other numerous programs to create bootable USB Sticks.&lt;/p&gt;

&lt;p&gt;If you’re starting from Windows, I’d recommend the &lt;a href="https://www.linuxliveusb.com/"&gt;LinuxLive USB Creator&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing a very basic Arch Linux™
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CCs5cZ45--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/637/1%2AxENQrzTQl0cwXixOSck7WQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CCs5cZ45--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/637/1%2AxENQrzTQl0cwXixOSck7WQ.png" alt=""&gt;&lt;/a&gt;Arch Linux™ — Boot screen&lt;/p&gt;

&lt;p&gt;After booting your system from the medium of your choice, the boot screen will show up as in any other distribution. But After deciding to &lt;em&gt;Boot Arch Linux (x86_64)&lt;/em&gt; you’ll be dropped into a the live system with nothing more than a command prompt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wxmFIhxC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/804/1%2AWfX7hvVP-_F9uG1DJ4L76A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wxmFIhxC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/804/1%2AWfX7hvVP-_F9uG1DJ4L76A.png" alt=""&gt;&lt;/a&gt;Arch Linux live shell&lt;/p&gt;

&lt;h4&gt;
  
  
  Partitioning and encryption
&lt;/h4&gt;

&lt;p&gt;After performing some basic configuration, I prepared my partitions. I used the tool &lt;a href="https://linux.die.net/man/8/cfdisk"&gt;&lt;em&gt;cfdisk&lt;/em&gt;&lt;/a&gt; (just because I know how it works) and created two partitions. One partition for &lt;em&gt;/boot&lt;/em&gt;, with round about 200MB of space and the rest of the disk for everything else.&lt;/p&gt;

&lt;p&gt;If you’re curious what &lt;em&gt;/boot&lt;/em&gt; is:&lt;br&gt;&lt;br&gt;
Referring to the &lt;a href="http://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html"&gt;Filesystem Hirarchy Standards (FHS)&lt;/a&gt;, the &lt;a href="http://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch03s05.html"&gt;/boot&lt;/a&gt; folder holds the static files of the boot loader. It is allowed to store the kernel there as well.&lt;/p&gt;

&lt;p&gt;The only reason, why I setup a different partition for my boot loader and kernel is, that my main partition will be encrypted and therefore a decryption by the kernel is required before user-mode programs can be loaded.&lt;/p&gt;

&lt;p&gt;So now that I’ve setup my partitions, it’s time to encrypt the device!&lt;br&gt;&lt;br&gt;
Therefore I used the tool cryptsetup, which is a tool that is able to perform a plain &lt;a href="https://en.wikipedia.org/wiki/Dm-crypt"&gt;dm-crypt&lt;/a&gt; or a LUKS encryption. dm-crypt is the cryptographic device mapper module where LUKS stands for &lt;em&gt;Linux Unified key Setup&lt;/em&gt;, which extends the plain encryption of dm-crypt by an additional meta information header easing the identification of the encryption algorithm, finding user data within the encrypted data blob and makes some additional cryptographic features possible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cryptsetup -y -v luksFormat /dev/sdaX
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;cryptsetup
Tool to encrypt devices&lt;/li&gt;
&lt;li&gt;-y
Asks for passphrase verification&lt;/li&gt;
&lt;li&gt;-v
Verbose&lt;/li&gt;
&lt;li&gt;luksFormat
Encrypt with LUKS header&lt;/li&gt;
&lt;li&gt;/dev/sdaX
The device to be encrypted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Encryption is done!&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting up the File system
&lt;/h4&gt;

&lt;p&gt;After opening the encrypted device, we’re now able to write our file system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkfs.btrfs /dev/mapper/cryptroot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;mkfs
A tool to create Linux file systems&lt;/li&gt;
&lt;li&gt;mkfs.btrfs
Creates a btrfs file system&lt;/li&gt;
&lt;li&gt;/dev/mapper/cryptroot
The opened/mapped device
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkfs.ext2 /dev/sda1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;mkfs.ext2
Creates a ext2 file system&lt;/li&gt;
&lt;li&gt;/dev/sda1
The device to create the file system on.
&lt;em&gt;In this case, this is my /boot partition&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Setting up a file system is not that hard. Choosing your file system however is very hard. There are multiple file systems out there with many different features. Because I don’t want to start comparing all the pros and cons of the different systems, let me just point out why I’ve chosen &lt;em&gt;ext2&lt;/em&gt; for my boot partition and &lt;em&gt;btrfs&lt;/em&gt; for everything else. At first: It was a recommendation. But that’s not enough reason to do so. Therefore I did some research.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Ext2"&gt;&lt;em&gt;ext2&lt;/em&gt;&lt;/a&gt; is what one would call a very basic file system nowadays. It was meant to solve various issues of ext. But due to its simplicity it’s ideal for boot partitions, USB-Sticks and basically every storage, where &lt;a href="https://en.wikipedia.org/wiki/Journaling_file_system"&gt;journaling&lt;/a&gt; is not required.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Btrfs"&gt;&lt;em&gt;btrfs&lt;/em&gt;&lt;/a&gt; on the other hand is a file system that hits its stable state initially in 2014. It’s a &lt;a href="https://en.wikipedia.org/wiki/Copy-on-write#Copy-on-write_in_computer_storage"&gt;copy-on-write&lt;/a&gt; file system with a vast amount of features including self-healing mechanisms, file system snapshots, subvolumes and much much more. Especially because of it’s snapshot mechanism it’s very easy to create file system backups without copying tons of data to an external drive.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting up initramfs
&lt;/h4&gt;

&lt;p&gt;This section clarifies what bugged me the most when installing Linux systems with encrypted devices… until now.&lt;/p&gt;

&lt;p&gt;The keyboard layout while setting up the passphrase was German (due to my choices during the installation process) but while booting the system, the layout switches back to English!&lt;/p&gt;

&lt;p&gt;This led me to so many moments full of frustration but now, they are gone!&lt;br&gt;&lt;br&gt;
And unfortunately it could have been so easy avoiding the frustration at all.&lt;/p&gt;

&lt;p&gt;There is a file on your Arch Linux™ machine called &lt;em&gt;/etc/mkinitcpio.conf.&lt;/em&gt;&lt;br&gt;&lt;br&gt;
This is a configuration file for (who would have guessed) a program called &lt;em&gt;mkinitcpio&lt;/em&gt; which is able to create &lt;em&gt;initramfs&lt;/em&gt; archives. The most important part of this configuration file is the definition of the &lt;em&gt;HOOKS&lt;/em&gt; variable. &lt;em&gt;HOOKS&lt;/em&gt; specifies the composition and behavior of the initramfs. One of this glorious hooks is called &lt;em&gt;keymap&lt;/em&gt;. And this is what &lt;em&gt;keymap&lt;/em&gt; does:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Adds the specified keymap(s) from /etc/vconsole.conf to the initramfs.&lt;br&gt;&lt;br&gt;
Loads the specified keymap(s) from /etc/vconsole.conf during early userspace.&lt;br&gt;&lt;br&gt;
Source: &lt;a href="https://wiki.archlinux.org/index.php?title=Mkinitcpio&amp;amp;oldid=492088"&gt;https://wiki.archlinux.org/index.php?title=Mkinitcpio&amp;amp;oldid=492088&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkinitcpio -p linux
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Done!&lt;/p&gt;

&lt;p&gt;This means, that the keyboard layout of my choice is loaded within the initramfs. This empowers me to use as many special characters in my passphrase as I want!&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;One told me once: &lt;em&gt;Setting up an Arch Linux™is no witchcraft.&lt;/em&gt;&lt;br&gt;&lt;br&gt;
Now that I did it, I can only agree. I took some hours to find out only some of the details I wanted to know. One could spend hundreds of hours more depending on the level of detail you’re looking for. So the learning curve is steep and one will have to do some parts of the installation twice but at the end, you’ve a system which is absolutely transparent to you. And if I forget what I did once while I performed the installation, I can just look it up in the repository. At my current point it feels like there is not a single situation where the system could receives critical damage to the software that I’m unable to repair.&lt;/p&gt;

&lt;p&gt;This article is originally published at &lt;a href="https://medium.com/@SvenHettwer/traveling-through-the-arch-vol-3-9efc70bafc80"&gt;medium.com/@SvenHettwer&lt;/a&gt;&lt;/p&gt;

</description>
      <category>experience</category>
      <category>archlinux</category>
      <category>linux</category>
    </item>
    <item>
      <title>Traveling through the Arch — Vol. 2</title>
      <dc:creator>Sven Hettwer</dc:creator>
      <pubDate>Wed, 04 Oct 2017 11:01:01 +0000</pubDate>
      <link>https://forem.com/svettwer/traveling-through-the-arch--vol-2-2kl</link>
      <guid>https://forem.com/svettwer/traveling-through-the-arch--vol-2-2kl</guid>
      <description>&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%2Fcdn-images-1.medium.com%2Fmax%2F601%2F1%2AtFi6naMRCPI45v8foDxuuw.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%2Fcdn-images-1.medium.com%2Fmax%2F601%2F1%2AtFi6naMRCPI45v8foDxuuw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we are again! In the &lt;a href="https://dev.to/svettwer/traveling-through-the-arch--vol-1-1jee-temp-slug-8266800"&gt;last post&lt;/a&gt;, I summarized what I know about Arch Linux™ and its ecosystem. This time I’ll go through the installation using the Arch Linux™ distribution Anarchy Linux form &lt;a href="https://arch-anywhere.org" rel="noopener noreferrer"&gt;https://arch-anywhere.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s start up the (virtual) machines!&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;After telling the system to boot the live environment and choosing to install Arch Linux™, one is asked to answer some basic questions well known from other installers like preferred language and keyboard layout in a shell based dialog. After answering that, it’s time to partition your drive. In the first attempt, I’ll try the &lt;em&gt;Auto partition encrypted LVM&lt;/em&gt; option, because I’ve a encrypted LVM on all my machines and will definitely use some kind of encryption with Arch Linux™, too. Choosing the partition size, choose to create a swap partition, typing in the encryption passphrase for the LVM.&lt;/p&gt;

&lt;p&gt;Encryption passphrases… These little nasty things…&lt;br&gt;&lt;br&gt;
Well, if you have not guessed it yet, I’m from Germany and here in Germany, we’ve a different keyboard layout (qwertz). So using a passphrase that contains special characters led me into some very annoying situations when I realized, that the installer absolutely supported the German keyboard settings, but the prompt when booting your system after the fresh installation, does not! There we’ve the american layout and the special characters are located in different places. So I added a special character to my test password to try out, what’s going on with Arch Linux™ concerning this problem.&lt;/p&gt;

&lt;p&gt;The partitioning has been finished. Time to choose your kernel. I’ll stay with the base kernel for no special reason. After that I was choosing bash, grub, the networkmanager, the 32 bit repositories in addition to the 64 bit, enabled DHCP, disabled wifi utils, excluded PPPoE DSL connections (2017 u know?) and excluded os-prober because I’ve no multi boot system here. Typing my choices into this article took way longer that choosing them via the dialog.&lt;/p&gt;

&lt;p&gt;Now I’m at the point of choosing my desktop environment.&lt;br&gt;&lt;br&gt;
I’ll go with the default &lt;a href="http://www.xfce.org/" rel="noopener noreferrer"&gt;Xfce4 Light Desktop&lt;/a&gt;, just as always. But wait! There is something called &lt;a href="https://arch-anywhere.org/content/features/" rel="noopener noreferrer"&gt;Arch Anywhere Xfce&lt;/a&gt;, which is some kind of a custom Xfce4 from the Anarchy Linux developer. I’ll try this one out!&lt;br&gt;&lt;br&gt;
Going to the next screen…&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%2Fcdn-images-1.medium.com%2Fmax%2F721%2F1%2AgOUgUmUuMY5ztxHyXDg_HA.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%2Fcdn-images-1.medium.com%2Fmax%2F721%2F1%2AgOUgUmUuMY5ztxHyXDg_HA.png"&gt;&lt;/a&gt;Screenshot of the installation process — Detected VirtualBox installation&lt;/p&gt;

&lt;p&gt;So the installer is clever enough to detect that I’m using a VirtualBox installation and will therefore install the guest utils package? Awesome!&lt;/p&gt;

&lt;p&gt;After choosing the last few components for the installation, the installer asks me if I want to install all of the packages I’ve chosen. For sure I will and there we go…&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A few minutes later…&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;All packages have been installed. I choose a name for the computer, set the root password and created a test user with root privileges. Rebooted the system… aaaaaand…&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%2Fcdn-images-1.medium.com%2Fmax%2F641%2F1%2AUN2Qaw2dkE5Xs-hK3KHoBA.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%2Fcdn-images-1.medium.com%2Fmax%2F641%2F1%2AUN2Qaw2dkE5Xs-hK3KHoBA.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O’rly? That was not what I expected…&lt;br&gt;&lt;br&gt;
Okay so the ever so promising installer left me with a broken system after the fresh installation. Honestly, I’m not a into the deeps Linux expert so that I would exactly know what went wrong and what I have to do, to solve the problem. Therefore I’ll try to install the system again with the exact same setup.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A few more minutes later…&lt;/em&gt;&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%2Fcdn-images-1.medium.com%2Fmax%2F639%2F1%2ARmG9ii-Yd8epo6SSPblCsg.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%2Fcdn-images-1.medium.com%2Fmax%2F639%2F1%2ARmG9ii-Yd8epo6SSPblCsg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay… it seems like it worked this time…&lt;br&gt;&lt;br&gt;
So what could be the reason for that? I’ll come back to this point later on. Now let us enjoy the magnificence of Arch that everybody told me about!&lt;/p&gt;

&lt;p&gt;Ah! Before I forget: The LVM passphrase prompt comes with an English keyboard layout, while the booted OS loads the default keyboard setup you’ve chosen during the installation. So remember kids: &lt;em&gt;Before you setup your LVM passphrase, change the layout of your keyboard to English!&lt;/em&gt;&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AdIF-bgpeLMhPnTRzEHwiFw.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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AdIF-bgpeLMhPnTRzEHwiFw.png"&gt;&lt;/a&gt;Screenshot after the first time booting successfully into Arch Linux™&lt;/p&gt;

&lt;p&gt;Mission complete! Clicked a little bit around to discover what’s behind all the fancy symbols. Yep! Feels like a Xfce4 with some nice extras like the drop down shell. I’ll keep that one in mind. But for some reason I’m not satisfied with what I found here. And the reason is not Arch Linux™, it’s not the custom Xfce4 (which IMHO brings an awesome look and feel with it) but the installation of the System. So let’s get back and try to find some reasons why the first installation was broken after reboot.&lt;/p&gt;

&lt;h3&gt;
  
  
  Research about the broken installation
&lt;/h3&gt;

&lt;p&gt;Due to the fact, that I’m unable to reconstruct the technical environment, the only thing I could do now is guessing. But even if I’m not a Linux kernel hacker, the installation process is nothing more than a program. I can read programs! So, lets visit the &lt;a href="https://github.com/deadhead420/arch-linux-anywhere" rel="noopener noreferrer"&gt;Anarchy Linux github repository&lt;/a&gt;. With as of today round about 2k commits and 41 contributors, happily developing.&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%2Fcdn-images-1.medium.com%2Fmax%2F1016%2F1%2AJVjC_0euPMnOWsF9h9tkVw.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%2Fcdn-images-1.medium.com%2Fmax%2F1016%2F1%2AJVjC_0euPMnOWsF9h9tkVw.png"&gt;&lt;/a&gt;Contributions of Anarchy Linux&lt;/p&gt;

&lt;p&gt;Now lets find the place where the setup of the hard drive is made. A quick look into the &lt;a href="https://github.com/deadhead420/arch-linux-anywhere/blob/master/arch-installer.sh" rel="noopener noreferrer"&gt;arch-installer.sh&lt;/a&gt; showed up that &lt;em&gt;prepare_divers&lt;/em&gt; is what we’re looking for and this is contained in &lt;a href="https://github.com/deadhead420/arch-linux-anywhere/blob/master/lib/configure_device.sh" rel="noopener noreferrer"&gt;configure_devices.sh&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Before I go any further into details, I want to make clear that I appreciate the work of everyone who is providing free/open software to the world! I even more appreciate if someone offers her or his work to everyone free of charge! This is why the free software/open source community has grown so much and is so strong! So many thanks to the Anarchy Linux team for your work and the effort you put into your project! I really much appreciate it!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As of today, the &lt;em&gt;configure_devices.sh&lt;/em&gt; script is 850 lines long, whereas the &lt;em&gt;auto_encrypt&lt;/em&gt; method, which has been called after my set of choices, is 111 lines of that. The maximum indentation I’ve found in that file is 10. So navigating the code and finding what may have caused the troubles isn’t that easy, if you haven’t seen the code before. So after 5 Minutes scrolling the code I just left it. Googling the issue was not helpful too, because I could not find out what has exactly been done by the installation scripts.&lt;/p&gt;

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

&lt;p&gt;I think the main question now is: Would I recommend the arch-anywhere.org installer? The answer is, as ever so often: &lt;strong&gt;It depends.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If you’re a technical or Linux newbie, I wouldn’t recommend Arch Linux at all, start with Mint, Ubuntu or something like that.&lt;br&gt;&lt;br&gt;
If you know how Linux basically works and you’re looking for a distribution you can grow with, use the arch-anywhere.org and start to hack your distribution to your heart’s content.&lt;br&gt;&lt;br&gt;
If you know Linux quite well and just want to get rid off the extra ballast coming with the more end user oriented distributions and start with bleeding edge technology, write the installation by yourself and avoid any predefined installer.&lt;/p&gt;

&lt;p&gt;IMHO the benefits of doing the installation manually are huge.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You know exactly what you configured or installed on your system. So if a problem occurs, you know the parameters of every command you’ve set during installation so troubleshooting is way easier as if you would use a tool that selects the parameter due to user choices.&lt;/li&gt;
&lt;li&gt;A predefined installer is never able to provide all the options to you that the software comes with. E.g. the Anarchy Linux installer is not able to set user home encryption on top of the LVM encryption.&lt;/li&gt;
&lt;li&gt;Your system is truly minimal. You don’t know if an installer is choosing some additional packages and if you want to find out how the installer exactly works, you’ll have to bring a lot of time with you.&lt;/li&gt;
&lt;li&gt;You learn a lot! You’ll never learn as much as doing things with your own hands. This includes running into pitfalls, some level of frustration and pain, but at the end you will succeed and get a deep understanding of how things work together.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the previous post, I said, that installing everything by my own hands is not state of the art. And depending on the use case, this is still true. A non technical user would never be able to setup an Arch Linux™ out of the box. But this is not the use case of the distribution. It wants to be simple (not meaning user friendly), efficient and lightweight whereas the target audience is focused on people with technical know how.&lt;/p&gt;

&lt;p&gt;So contrary to my statement from the last article, I’ll setup my Arch Linux™ by my own hands!&lt;/p&gt;

&lt;p&gt;So lets start to explore strange new commands, to seek out for new packages to use and new setup options to choose in the next Episode of “Traveling through the Arch”.&lt;/p&gt;

&lt;p&gt;This article is originally published at &lt;a href="https://medium.com/@SvenHettwer/traveling-through-the-arch-vol-2-24e771deced" rel="noopener noreferrer"&gt;medium.com/@SvenHettwer&lt;/a&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>virtualbox</category>
      <category>archlinux</category>
      <category>experience</category>
    </item>
    <item>
      <title>Traveling through the Arch — Vol. 1</title>
      <dc:creator>Sven Hettwer</dc:creator>
      <pubDate>Wed, 27 Sep 2017 11:01:01 +0000</pubDate>
      <link>https://forem.com/svettwer/traveling-through-the-arch--vol-1-25jh</link>
      <guid>https://forem.com/svettwer/traveling-through-the-arch--vol-1-25jh</guid>
      <description>&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AtCvTXVkWKMzF_uWXsk6XNQ.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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AtCvTXVkWKMzF_uWXsk6XNQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this series of blog posts, I want to travel with you through my experiences with Arch Linux™ from the very beginning to the (hopefully) happy ending.&lt;/p&gt;

&lt;p&gt;As mentioned in my first blog post, I’ll join a new company next week. Because they allowed me to choose my OS, I’ll go for a Linux distribution. I use Linux on my PC, my Netbook, my Smartphone, etc. So for me it’s a obvious choice. The only question I ask myself every time, if I want to install a Linux on new hardware is: What distribution should I use?&lt;/p&gt;

&lt;p&gt;This time, I’ll try Arch Linux™. No clue what Arch Linux™ is? No Problem! I’ll try to give you a little overview of what I found out!&lt;/p&gt;

&lt;p&gt;Currently I’m mostly using &lt;a href="https://www.debian.org/" rel="noopener noreferrer"&gt;Debian GNU/Linux&lt;/a&gt;, &lt;a href="https://www.ubuntu.com/" rel="noopener noreferrer"&gt;Ubuntu&lt;/a&gt; or one of its derivatives. Both of them are easy to install and run on nearly every system. If a more stable system is required where up to date technology is not a must have, I go with Debian GNU/Linux. For development, I prefer Ubuntu or its derivatives, because the packages are kind of up to date. Nevertheless Ubuntu is a very heavy distribution consuming a lot of memory for it’s Unity Desktop (and Xubuntu with Xfce isn’t much better), it is shipped with a lot of software I’ll never need and every version has a expiration date (even the LTS versions). This is where Arch Linux comes into play.&lt;/p&gt;

&lt;p&gt;Arch Linux™ is a very lightweight distribution which allows you to setup your system just as you want it to be. You’re able to choose what runs on your computer package by package. &lt;em&gt;To be fair: You could also achieve that, if you use a minimal Debian GNU/Linux installation and do the rest of the setup manually.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Speaking of doing things manually…&lt;br&gt;&lt;br&gt;
The &lt;a href="https://wiki.archlinux.org/index.php/installation_guide" rel="noopener noreferrer"&gt;installation guide of Arch Linux&lt;/a&gt;™ is a step by step tutorial of how to setup a operating system with nothing more than a bootable medium and your own hands. If you ask me, this is not the way it works nowadays. Even though that I’m a software developer, I don’t want to set up all the little bits and pieces for my OS installation. Time is valuable! When should I write Blog posts, if I have to set up my OS manually first?&lt;br&gt;&lt;br&gt;
So I had to find something smarter. A friend of mine recommended &lt;a href="https://arch-anywhere.org/" rel="noopener noreferrer"&gt;Arch anywhere&lt;/a&gt; to me. This project provides a minimal installer for an Arch Linux™ based distribution called &lt;em&gt;Anarchy&lt;/em&gt; with the option of choosing additional packages from the official Arch Linux™ repositories. So I’ll give it a go!&lt;/p&gt;

&lt;p&gt;An additional advantage of Arch Linux™ is, that it’s a &lt;a href="https://en.wikipedia.org/wiki/Rolling_release" rel="noopener noreferrer"&gt;rolling release&lt;/a&gt; distribution. That means that you’ll never have an outdated OS as long as you perform software updates. There is nothing like a support limitation for your OS version. Every update is shipped to every installation out there. This is also interesting in terms of bleeding edge technology. You’ll never have the problem to obtain up to date packages for your OS, because there is no version number limiting the support or compatibility.&lt;/p&gt;

&lt;p&gt;But where light is there is also shadow!&lt;br&gt;&lt;br&gt;
Working with bleeding edge technology harbours the risk of crashing your system because of unstable packages or updated. And this is one of the biggest concerns I’ve with Arch Linux™. I want an OS that is stable in any situation. For me it would be a nightmare to loose one day of work, because my OS crashed by some incompatibilities. So the only way to minimize the risk of breaking your system, is to update frequently and visit the &lt;a href="https://www.archlinux.org/" rel="noopener noreferrer"&gt;official website&lt;/a&gt; and &lt;a href="https://bbs.archlinux.org/" rel="noopener noreferrer"&gt;forums&lt;/a&gt; to find showstopper &lt;strong&gt;before&lt;/strong&gt; you update. This will require at least a bit of time and effort to keep &lt;em&gt;yourself&lt;/em&gt; up to date.&lt;br&gt;&lt;br&gt;
Another point I’m concerned about is that Arch Linux™ is using its own package manager called &lt;a href="https://wiki.archlinux.org/index.php/pacman" rel="noopener noreferrer"&gt;pacman&lt;/a&gt;. So if there is no official support for the software you’re looking for, you may have some trouble. Even though there is the &lt;a href="https://wiki.archlinux.org/index.php/Arch_User_Repository" rel="noopener noreferrer"&gt;Arch User Repository (AUR)&lt;/a&gt; containing a lot of community-driven packages, I’m not sure if I’ll be able to find everything I need there.&lt;/p&gt;

&lt;p&gt;Enough of theory! Let’s start with the “hands on” part in the next Episode of “Traveling through the Arch”.&lt;/p&gt;

&lt;p&gt;You want to read more about Arch Linux™?&lt;br&gt;&lt;br&gt;
Just visit their &lt;a href="https://www.archlinux.org/" rel="noopener noreferrer"&gt;website&lt;/a&gt; for more details!&lt;/p&gt;

&lt;p&gt;This article is originally published at &lt;a href="https://medium.com/@SvenHettwer/traveling-through-the-arch-vol-1-f454e017646" rel="noopener noreferrer"&gt;medium.com/@SvenHettwer&lt;/a&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>experience</category>
      <category>archlinux</category>
    </item>
    <item>
      <title>Why I started!</title>
      <dc:creator>Sven Hettwer</dc:creator>
      <pubDate>Tue, 26 Sep 2017 18:21:31 +0000</pubDate>
      <link>https://forem.com/svettwer/why-i-started-34e8</link>
      <guid>https://forem.com/svettwer/why-i-started-34e8</guid>
      <description>&lt;p&gt;Well, I think it would be a good start for my blog if I explain why I started.&lt;br&gt;&lt;br&gt;
&lt;em&gt;It may sound easy to start with a blog post but it actually cost me four or five attempts to formulate these first words.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I think the main reason for me is a pragmatic one. By the end of this week, I leave the company I worked the last few years for. While I was working there, I was an active member of the software developer community, because I love to share knowledge. I gave tech talks about various topics like &lt;a href="https://en.wikipedia.org/wiki/Reactive_programming"&gt;Reactive programming&lt;/a&gt; with &lt;a href="http://reactivex.io/"&gt;ReactiveX&lt;/a&gt; or clean code, I wrote blog posts about many things worth to share and I created a clean code community to teach others. I would have liked to do some more community work but daily business needs to be done, too.&lt;br&gt;&lt;br&gt;
So because I’m leaving I was looking for a possibility to keep in contact with my old colleagues and continue sharing what I’ve learned and what I work with. And here we are!&lt;/p&gt;

&lt;p&gt;I’ll try to write as much as I can and hope, that you’ll find it interesting.&lt;/p&gt;

&lt;p&gt;This article is originally published at &lt;a href="https://medium.com/@SvenHettwer/why-i-started-e693feb3656a"&gt;medium.com/@SvenHettwer&lt;/a&gt;&lt;/p&gt;

</description>
      <category>blogging</category>
      <category>softwaredevelopment</category>
    </item>
  </channel>
</rss>
