<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Claudio Altamura</title>
    <description>The latest articles on DEV Community by Claudio Altamura (@claudioaltamura).</description>
    <link>https://dev.to/claudioaltamura</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%2F365601%2F3a34a33c-608b-4429-90c7-5a9879dbd525.jpeg</url>
      <title>DEV Community: Claudio Altamura</title>
      <link>https://dev.to/claudioaltamura</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/claudioaltamura"/>
    <language>en</language>
    <item>
      <title>Clean and maintainable Git Histories – Part 2</title>
      <dc:creator>Claudio Altamura</dc:creator>
      <pubDate>Fri, 28 Nov 2025 18:05:26 +0000</pubDate>
      <link>https://dev.to/claudioaltamura/clean-and-maintainable-git-histories-part-2-iip</link>
      <guid>https://dev.to/claudioaltamura/clean-and-maintainable-git-histories-part-2-iip</guid>
      <description>&lt;p&gt;&lt;strong&gt;3 simple tricks for managing git histories&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It took me a while to learn these simple tricks for effectively managing Git histories with just a few commands. In the &lt;a href="https://claudioaltamura.de/devops/ci-cd/clean-and-maintainable-git-histories-part-1" rel="noopener noreferrer"&gt;first article&lt;/a&gt;, I explained why clear, structured Git commit messages and cohesiv commits are important or why temporary commits make the history more difficult to read. This time, I will show you how to organise your commits before merging them. This will give you a clean, easy-to-understand commit history.&lt;/p&gt;

&lt;p&gt;Changes should be reviewed and consolidated into a clear commit history. The aim is to include only changes that are relevant, just like book authors revise drafts before publishing. Consider cleaning up commit history for clarity and maintainability:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add changes directly to the previous commit&lt;/strong&gt;&lt;br&gt;
If you make minor adjustments to the last commit, you can add them directly into the previous commit by utilizing &lt;code&gt;git commit --amend&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consolidate multiple commits into one single commit&lt;/strong&gt;&lt;br&gt;
All changes can be grouped together into a single commit with &lt;br&gt;
&lt;code&gt;git merge --squash&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tidy up your commits&lt;/strong&gt;&lt;br&gt;
Remove temporary commits, combine multiple commits into one or change the content to create a simple, easy-to-read history with &lt;code&gt;git rebase&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Add changes directly to the previous commit&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can make minor corrections or unnecessary changes directly in the last commit using &lt;code&gt;git commit --amend&lt;/code&gt;. This command lets us add new files, remove unwanted files or change the commit message – all without creating a new commit (simplified). Here's how to make changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open your files in the working directory, and then either add new files using &lt;code&gt;git add&lt;/code&gt; or remove files that you don't need any more using &lt;code&gt;git rm&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Now you can adjust a commit by adding the changes to the last one using the &lt;code&gt;git commit --amend&lt;/code&gt; command.&lt;/li&gt;
&lt;li&gt;You can also edit the commit message if you want.&lt;/li&gt;
&lt;li&gt;And when the commit is already been pushed, you'll need to force push to the remote repository with &lt;code&gt;git push --force-with-lease&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Consolidate multiple commits into one single commit&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;During development, you usually work in your feature branch and create several commits like partial steps, WIP commits or bug fixes. Often these intermediate states are not relevant for the main branch and inflate the history. In such a case, the changes can be reduced to one single, clean commit.&lt;/p&gt;

&lt;p&gt;Before merging into the main branch, you can &lt;code&gt;squash&lt;/code&gt; your commits so that only one summary commit appears in the main branch. The detailed intermediate steps in the feature branch are not retained – instead, a clear, complete commit is created that describes the entire change. Here is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout main
git merge --squash &amp;lt;feature-branch&amp;gt;
git commit -m "feat(auth): add JWT authentication"
git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method makes sure you've got a tidy and clear commit history by presenting the whole change as one completed commit – perfect for feature developments with lots of intermediate stages. This makes code reviews a lot of easier. And the main branch is kept simple and free of any unnecessary steps.&lt;/p&gt;

&lt;p&gt;Disadvantages like losing granularity because you lose contextual information, or more complex conflict resolution because squash bundles multiple changes into one large commit, are often not that important.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tidy up your commits&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can use &lt;code&gt;git rebase -i &amp;lt;commit-hash&amp;gt;&lt;/code&gt; to edit the commit history interactively and to tidy up the commits. This is really useful for getting rid of temporary or debug commits, or for merging multiple commits. Let's say we want to edit the last five commits with &lt;code&gt;git rebase -i HEAD~5&lt;/code&gt;. This will show you a list of the last five commits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pick abcdef1 Commit A
pick abcdef2 Commit B
pick abcdef3 Commit C
pick abcdef4 Commit D
pich abcdef5 Commit E
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can edit the commits as you like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Change &lt;strong&gt;pick&lt;/strong&gt; to squash for the commits you want to merge.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;strong&gt;fixup&lt;/strong&gt;, if you want to stick changes or corrections made in later commits into an earlier one, but you don't want to keep the message from the later one.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can use the &lt;strong&gt;drop&lt;/strong&gt; command to get rid of individual commits from the history. This is great for temporary or debug commits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And use &lt;strong&gt;edit&lt;/strong&gt; to make changes to a commit. Git stops at this point in the rebase process, so you can make changes in the working directory, like remove debug output or undo temporary changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then just save those changes and you're all set! Now that you've changed the commit history, I think it's important to mention that you'll need to perform a forced push to update the changes in the remote repository using &lt;code&gt;git push --force-with-lease&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A rebase cleans up the Git history. It makes the history linear, as if all the changes from your feature branch were applied directly to the latest version of the main branch. And there's no merge commit created that is causing any issues.&lt;/p&gt;

&lt;p&gt;Just be careful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If you re-write history, you might lose sight of the original context, especially when and how changes upstream were integrated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you rebase branches that have already been published, you might run into problems because you'll be changing the history. Other team members working on the same branch will run into conflicts and have to readjust their local changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this two-part series of articles, we've taken a close look at keeping Git histories easy to understand and to maintain. This is something that often gets overlooked, but it's actually really important making sure the team works efficiently.&lt;/p&gt;

&lt;p&gt;In this two-part series of articles, we've taken a close look at keeping Git histories easy to understand and to maintain. This is something that often gets overlooked, but it's actually really important making sure the team works efficiently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Rewriting history &lt;a href="https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History" rel="noopener noreferrer"&gt;https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@electerious?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Tobias Reich&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/a-long-hallway-with-a-metal-railing-and-windows-3eB5SVwLtkE?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>programming</category>
    </item>
    <item>
      <title>Clean and maintainable Git Histories – Part 1</title>
      <dc:creator>Claudio Altamura</dc:creator>
      <pubDate>Wed, 09 Jul 2025 19:15:16 +0000</pubDate>
      <link>https://dev.to/claudioaltamura/clean-and-maintainable-git-histories-part-1-1jb5</link>
      <guid>https://dev.to/claudioaltamura/clean-and-maintainable-git-histories-part-1-1jb5</guid>
      <description>&lt;p&gt;&lt;strong&gt;3 methods for keeping histories clean and organized&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this series of articles, I'm going to show you how to get clean and maintainable git histories. In the first part, we look at different methods. If these methods are followed, the history remains clear, facilitates code reviews, debugging and can serve as documentation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Meaningful commit messages&lt;br&gt;
A clear description of the change and its motivation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cohesive commits&lt;br&gt;
Only changes that belong together should be included in a single commit&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoid temporary commits&lt;br&gt;
WIP, temporary or debug commits should not be merged to keep the history clean&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Meaningful commit messages&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Everythings starts with a clear commit message. It should briefly summarize what was changed and why. &lt;strong&gt;Conventional Commits&lt;/strong&gt; offer us a reliable format for commit messages, enhancing the clarity and comprehensibility of source code histories. A commit message should include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Type: The type of change (e.g., fix, feat).&lt;/li&gt;
&lt;li&gt;Scope (optional): The affected area of the project.&lt;/li&gt;
&lt;li&gt;Description: A brief description of the change.&lt;/li&gt;
&lt;li&gt;Body (optional): Additional details about the change.&lt;/li&gt;
&lt;li&gt;Footer (optional): Metadata, e.g., references to issues.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is an example of such a commit message:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;feat(auth): add JWT authentication&lt;br&gt;
This commit introduces JSON Web Token (JWT) based authentication to the login module.&lt;br&gt;
BREAKING CHANGE: The login API now requires a token for authentication.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Cohesive commits&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A commit should be atomic, containing logically related changes that should not be split up. Each commit should represent a standalone change, whether it's a bug fix, a feature enhancement, or a code refactoring. This practice simplifies change tracking and finding errors more quickly. It provides a clear overview of the modifications made and the reasons behind them, also streamlining the code review process. By isolating each change, reviewers can concentrate on specific modifications without feeling overwhelmed by a large number of changes. Moreover, in case of issues, reverting changes becomes significantly more straightforward, minimizing disruptions to the overall project.&lt;/p&gt;

&lt;p&gt;Let’s take the previous example and explain the commits in more detail:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Commit 1: feat(auth): setup JWT library and utility class&lt;br&gt;
Commit 2: feat(auth): configure security with JWT filter&lt;br&gt;
Commit 3: feat(auth): modify login API to return JWT token&lt;br&gt;
Commit 4: test(auth): add unit tests for JWT authentication&lt;br&gt;
Commit 5: docs(auth): update README with authentication instructions&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Commit 1 adds the JWT library and creating the utility class&lt;/li&gt;
&lt;li&gt;Commit 2 includes a JWT Filter into the security configuration&lt;/li&gt;
&lt;li&gt;Commit 3 focuses on the specific change to the API&lt;/li&gt;
&lt;li&gt;Commit 4 is dedicated to tests to ensure that the new functionality is fully covered&lt;/li&gt;
&lt;li&gt;Commit 5 contains only documentation changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aim to create real &lt;strong&gt;cohesive commits&lt;/strong&gt;, not just small, chronological commits. The purpose of commits is to explain what changed and why, not to document every step. This leads to a cleaner Git history, helps to improve code quality and maintainability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Avoid temporary commits&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While in the process of development and debugging, it's important to be mindful of the impact of WIP (Work in Progress) and debug commits on the clarity of a code repository. These types of commits can introduce steps that do not reflect the final implementation, leading to complications in tracking progress on features or bug fixes.&lt;/p&gt;

&lt;p&gt;Take, for example, a common debug commit where a developer adds println statements to monitor variable behavior during code execution. It is essential to clean up these debugging statements once the debugging phase is complete.&lt;/p&gt;

&lt;p&gt;Below are some commit samples that are not suitable for merging:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Commit 1: feat(user): first version UserService&lt;br&gt;
Commit 2: refactor(user): UserService - Tests not working&lt;br&gt;
Commit 3: debug(auth): added printlns to check flow&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To maintain a clear and detailed project history, it is advisable to &lt;strong&gt;rewrite the commit history&lt;/strong&gt; for consolidating work-in-progress commits, eliminating temporary and debug commits prior to merging, ensuring that only important and production-ready updates are integrated into the main branch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These 3 methods help to structure and maintain project histories. This includes clearly defined commit units, meaningful commit messages and that only production-relevant changes are merged into your primary branch. Just like book authors revise drafts before publishing, consider cleaning up commit history before sharing it.&lt;/p&gt;

&lt;p&gt;So stay tuned for the second part, where we delve into techniques for cleaning up and consolidating commits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Conventional Commit &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/#summary" rel="noopener noreferrer"&gt;https://www.conventionalcommits.org/en/v1.0.0/#summary&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@markusspiske?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Markus Spiske&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/tilt-shift-photography-of-html-codes-8OyKWQgBsKQ?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>programming</category>
    </item>
    <item>
      <title>Reinstalling Your Must-Have Dev Tools and Extensions on Mac</title>
      <dc:creator>Claudio Altamura</dc:creator>
      <pubDate>Fri, 09 Aug 2024 12:30:23 +0000</pubDate>
      <link>https://dev.to/claudioaltamura/reinstalling-your-must-have-dev-tools-and-extensions-on-mac-17nh</link>
      <guid>https://dev.to/claudioaltamura/reinstalling-your-must-have-dev-tools-and-extensions-on-mac-17nh</guid>
      <description>&lt;p&gt;A step-by-step guide to bringing your essential development setup back to life.&lt;/p&gt;

&lt;p&gt;So, you’ve got a shiny new Mac, and you’re ready for a fresh start. But where do you begin? Installing the right tools and applications is crucial to get your development environment up and running smoothly. In this guide, I’ll walk you through using Mac terminal commands to streamline the installation process for essential programs like Homebrew, Visual Studio Code or SDKMAN. Let’s get your Mac setup right 💻!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which applications have I installed?&lt;/strong&gt;&lt;br&gt;
If you want to see a list of all the applications installed on your old Mac before you start fresh on a new one, the terminal has a handy command for that. Simply open the Terminal and run the following command:&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="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt; /Applications

...
Discord.app
Docker.app
GIMP.app
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's worth noting that the list generated by this command includes all applications in your /Applications folder, even those that can be easily reinstalled with Homebrew&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Homebrew&lt;/strong&gt;&lt;br&gt;
You're a using Homebrew? Okay, then you’ll should do is to get a list of the software you have installed on your old Mac. Launch the Terminal, then execute this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew list &lt;span class="nt"&gt;-1&lt;/span&gt;

&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; Formulae
azure-cli
azure-functions-core-tools@4
&lt;span class="nb"&gt;base64
&lt;/span&gt;borgbackup
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Visual Studio Code Extensions&lt;/strong&gt;&lt;br&gt;
To list all the Visual Studio Code extensions you’ve installed, you can easily do so by opening a terminal and typing the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;code &lt;span class="nt"&gt;--list-extensions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will give you a straightforward list of all your extensions. But if you want to take it a step further—you can use the following command to generate a series of commands that will reinstall each extension:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;code &lt;span class="nt"&gt;--list-extensions&lt;/span&gt; | xargs &lt;span class="nt"&gt;-L&lt;/span&gt; 1 &lt;span class="nb"&gt;echo &lt;/span&gt;code &lt;span class="nt"&gt;--install-extension&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates a list where each line is a command to install one of your extensions, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;...
code--install-extension editorconfig.editorconfig
code--install-extension esbenp.prettier-vscode
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this list, you can easily reinstall all your VS Code extensions on your new machine with minimal effort, ensuring your development environment is back to how you like it in no time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SDKMAN!&lt;/strong&gt;&lt;br&gt;
If you're using SDKMAN to manage your JDKs and other SDKs, there's one more handy command worth mentioning. By running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tree &lt;span class="nt"&gt;-L&lt;/span&gt; 2 ~/.sdkman/candidates/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can quickly visualize all the SDKs and JDKs you have installed. This command provides a neat directory tree that displays each SDK along with its version, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;...
├── gradle
│   ├── 8.3
│   ├── 8.4
│   ├── 8.5
│   ├── 8.6
│   └── current -&amp;gt; 8.6
├── java
│   ├── 11.0.16.1-tem
│   ├── 17.0.4.1-tem
│   ├── 17.0.8.1-tem
│   ├── 21.0.1-tem
│   ├── 21.0.2-tem
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This structured view not only shows the versions you have installed but also highlights the one currently in use, marked by the current symlink. It’s a great way to quickly assess your development environment and ensure you have the right versions set up before diving back into coding on your new Mac.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion ✨&lt;/strong&gt;&lt;br&gt;
And with that, we've come to the end of our guide on setting up your new Mac with all the essential development tools. Getting your new Mac set up with the right tools is the first step to a smooth and productive development environment. With some terminal commands you’re well on your way. &lt;/p&gt;

&lt;p&gt;If you found this guide helpful, make sure to follow me for more tips and tricks on software development 😊.&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/de/@nampoh?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Maxim Hopman&lt;/a&gt; on &lt;a href="https://unsplash.com/de/fotos/silbernes-macbook-auf-weissem-tisch-Hin-rzhOdWs?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tooling</category>
      <category>homebrew</category>
      <category>vscode</category>
      <category>sdkman</category>
    </item>
    <item>
      <title>Validate your specs with OpenAPI Style Validator</title>
      <dc:creator>Claudio Altamura</dc:creator>
      <pubDate>Fri, 28 Apr 2023 14:24:12 +0000</pubDate>
      <link>https://dev.to/claudioaltamura/validate-your-specs-with-openapi-style-validator-m6o</link>
      <guid>https://dev.to/claudioaltamura/validate-your-specs-with-openapi-style-validator-m6o</guid>
      <description>&lt;p&gt;OpenAPI Style Validator is a tool to create API specs with understandable descriptions, examples and consistent use of naming conventions. &lt;/p&gt;

&lt;p&gt;The Validator helps developers to identify issues in OpenAPI specifications. With defined rules you can describe exactly how an API specification should look. These specs can be checked automatically and the results can be used in code reviews or even in a build pipeline where rule violations result in a build break.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Complete descriptions and naming conventions&lt;/strong&gt;&lt;br&gt;
The validator checks various objects of the OpenAPI schema, starting with the info object and the associated contact and license object. Often these details are not provided at all. Here you see as an example how the popular Petstore example provides the details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;info&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Swagger Petstore&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A sample API that uses a petstore as an example to demonstrate features in the OpenAPI 3.0 specification&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;termsOfService&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://swagger.io/terms/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contact&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Swagger API Team&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apiteam@swagger.io&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://swagger.io&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;license&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Apache 2.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://www.apache.org/licenses/LICENSE-2.0.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next object we'll take a closer look at is the operation object. But let's start with the paths object. The paths object contains all the paths to existing endpoints (path items). A single path (/pets) contains operations which describe what http methods are allowed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/pets/{id}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;get&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Returns a user based on a single ID, if the user does not have access to the pet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;operationId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;find pet by id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parameters&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;in&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ID of pet to fetch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;schema&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;integer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;format&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;int64&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The OpenAPI Style Validator detects whether certain properties exist For example, the property "summary" is missing in the above listing. In contrast, a "description" is present. The absence of a property is an error, if you have configured it that way.&lt;/p&gt;

&lt;p&gt;Let's look how the OpenAPI Style Validator checks the data type descriptions. Data types are defined in the OpenAPI specification as schema objects that can be referenced in requests or responses (e.g. "$ref": "#/components/schemas/NewPet"). The validator can check if all schema properties like description and example are present and not empty.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;NewPet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;properties&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tag&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we look at the NewPet schema object in the above listing, we do not find descriptions and examples. Examples and descriptions in an API spec make the documentation more understandable.&lt;/p&gt;

&lt;p&gt;Now let's move on to naming conventions. Naming conventions help to make an API easier to use. The OpenAPI Style Validator supports a number of different conventions that we can apply to paths, path parameters, query parameters, cookies, headers and properties. The naming conventions are: the underscore case (snake_case), camel case as we know it from Java and JavaScript and the so called hyphen case, also known as Kebab Case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Options and launching the OpenAPI Style Validator&lt;/strong&gt;&lt;br&gt;
With the defined rules we have learned now, we can control how an OpenAPI specification has to look. What kind of options do we have? There are boolean options like "validateOperationOperationId", which by a true, requires that each operation has an id. The option "validateOperationSummary" requires that operations also have a description. But there are also string type options like pathNamingConvention, parameterNamingConvention, pathParamNamingConvention and queryParamNamingConvention. With these options, we can determine if elements should follow e.g. the underscore case or camel case naming convention.&lt;/p&gt;

&lt;p&gt;So, how do we launch the validator? The maven command looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mvn openapi-style-validator:validate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Maven the OpenAPI Style Validator plugin must be configured inside the pom.xml Currently, io.swagger.core.v3 dependency must be excluded, otherwise a newer version of the library is used which unfortunately is incompatible with version 1.8 of the OpenAPI Style Validator. As you can in the following listing, each option can be added as a parameter under an XML tag, e.g. "validateOperationSummary" with true or false as text content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;plugin&amp;gt;
&amp;lt;groupId&amp;gt;org.openapitools.openapistylevalidator&amp;lt;/groupId&amp;gt;
&amp;lt;artifactId&amp;gt;openapi-style-validator-maven-plugin&amp;lt;/artifactId&amp;gt;
&amp;lt;version&amp;gt;1.8&amp;lt;/version&amp;gt;
&amp;lt;configuration&amp;gt;
    &amp;lt;inputFile&amp;gt;petstore-expanded.json&amp;lt;/inputFile&amp;gt;
&amp;lt;/configuration&amp;gt;
&amp;lt;dependencies&amp;gt;
    &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;org.openapitools.empoa&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;empoa-swagger-core&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;2.0.0&amp;lt;/version&amp;gt;
        &amp;lt;exclusions&amp;gt;
            &amp;lt;exclusion&amp;gt;
             &amp;lt;groupId&amp;gt;io.swagger.core.v3&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;swagger-models&amp;lt;/artifactId&amp;gt;
            &amp;lt;/exclusion&amp;gt;
        &amp;lt;/exclusions&amp;gt;
    &amp;lt;/dependency&amp;gt;
&amp;lt;/dependencies&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And by the way, with the default configuration we get the following result for the Petstore example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[INFO] --- openapi-style-validator:1.8:validate (default-cli) @ openapitools-validator-mvn-example ---
[INFO] Validating spec: petstore-expanded.json
[ERROR] OpenAPI Specification does not meet the requirements. Issues:

[ERROR]         *ERROR* in Operation GET /pets "summary" -&amp;gt; This field should be present and not empty
[ERROR]         *ERROR* in Operation GET /pets "tags" -&amp;gt; The collection should be present and there should be at least one item in it
[ERROR]         *ERROR* in Operation POST /pets "summary" -&amp;gt; This field should be present and not empty
[ERROR]         *ERROR* in Operation POST /pets "tags" -&amp;gt; The collection should be present and there should be at least one item in it
[ERROR]         *ERROR* in Operation GET /pets/{id} "summary" -&amp;gt; This field should be present and not empty
[ERROR]         *ERROR* in Operation GET /pets/{id} "tags" -&amp;gt; The collection should be present and there should be at least one item in it
[ERROR]         *ERROR* in Operation DELETE /pets/{id} "summary" -&amp;gt; This field should be present and not empty
[ERROR]         *ERROR* in Operation DELETE /pets/{id} "tags" -&amp;gt; The collection should be present and there should be at least one item in it
[ERROR]         *ERROR* in Model "NewPet", property "name", field "example" -&amp;gt; This field should be present and not empty
[ERROR]         *ERROR* in Model "NewPet", property "name", field "description" -&amp;gt; This field should be present and not empty
[ERROR]         *ERROR* in Model "NewPet", property "tag", field "example" -&amp;gt; This field should be present and not empty
[ERROR]         *ERROR* in Model "NewPet", property "tag", field 'description' -&amp;gt; This field should be present and not empty
[ERROR]         *ERROR* in Model "Error", property "code", field 'example' -&amp;gt; This field should be present and not empty
[ERROR]         *ERROR* in Model "Error", property "code", field 'description' -&amp;gt; This field should be present and not empty
[ERROR]         *ERROR* in Model "Error", property "message", field "example" -&amp;gt; This field should be present and not empty
[ERROR]         *ERROR* in Model "Error", property "message", field "description" -&amp;gt; This field should be present and not empty
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  3.342 s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/OpenAPITools/openapi-style-validator" rel="noopener noreferrer"&gt;OpenAPI Style Validator&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/OAI/OpenAPI-Specification/blob/main/examples/v3.0/petstore-expanded.json" rel="noopener noreferrer"&gt;Petstore Beispiel&lt;/a&gt;&lt;br&gt;
&lt;a href="https://bit.ly/3HoiW77" rel="noopener noreferrer"&gt;Validation example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@yassine_khalfalli?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Yassine Khalfalli&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/I3ZzOkiAbTI?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>openapi</category>
      <category>java</category>
    </item>
    <item>
      <title>Project Pilot - Short Notes</title>
      <dc:creator>Claudio Altamura</dc:creator>
      <pubDate>Wed, 28 Dec 2022 13:51:26 +0000</pubDate>
      <link>https://dev.to/claudioaltamura/project-pilot-short-notes-4675</link>
      <guid>https://dev.to/claudioaltamura/project-pilot-short-notes-4675</guid>
      <description>&lt;p&gt;Series on Software Design Practices – Part 3&lt;/p&gt;

&lt;p&gt;In this small series on design practices, I write about various practices. In every article, I give a brief and simple explanation. In &lt;a href="https://claudioaltamura.de/architecture/short-notes-on-design-practices-pt-2-prototype" rel="noopener noreferrer"&gt;part 2&lt;/a&gt; I wrote about prototypes. This time I present project pilots as another software development design practice.&lt;/p&gt;

&lt;p&gt;We already talked about &lt;a href="https://claudioaltamura.de/architecture/short-notes-on-design-practices-pt1-spike-solutions" rel="noopener noreferrer"&gt;spikes&lt;/a&gt;, which help you to find approaches for a technical problem, or &lt;a href="https://claudioaltamura.de/architecture/short-notes-on-design-practices-pt-2-prototype" rel="noopener noreferrer"&gt;prototypes&lt;/a&gt; to test a specific concept. What these concepts have in common is that they should not be used in production. Spikes may not be good enough or prototypes only focus on feasibility.&lt;/p&gt;

&lt;p&gt;Right here comes in the so-called &lt;strong&gt;project pilot&lt;/strong&gt;. You add additional points regarding production readiness, that you are able to test the viability and how likely it is that the software succeed. So it's the first phase in a larger project with a defined productive scope. And very importantly, project pilots provide you valuable feedback on ideas and concepts.&lt;/p&gt;

&lt;p&gt;Project pilots are another good strategy for managing risk. The concept helps you to uncover potential flaws ahead of a full launch. Use this feedback to identify issues and correct them in advance.&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@benjaminelliott?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Benjamin Elliott&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/gMb6mDSWUOU?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>writing</category>
      <category>learning</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Prototype - Short Notes</title>
      <dc:creator>Claudio Altamura</dc:creator>
      <pubDate>Wed, 30 Nov 2022 20:50:34 +0000</pubDate>
      <link>https://dev.to/claudioaltamura/prototype-short-notes-5d3h</link>
      <guid>https://dev.to/claudioaltamura/prototype-short-notes-5d3h</guid>
      <description>&lt;p&gt;Series on Software Design Practices - Part 2&lt;/p&gt;

&lt;p&gt;In this small series on software design practices, I write about various practices. In every article, I give a brief and simple explanation. In &lt;a href="https://dev.to/claudioaltamura/spike-solutions-short-notes-4la1"&gt;part 1&lt;/a&gt; I wrote about &lt;a href="https://dev.to/claudioaltamura/spike-solutions-short-notes-4la1"&gt;Spike Solutions&lt;/a&gt;. This time I present prototypes as a software development design practice.&lt;/p&gt;

&lt;p&gt;A prototype is a &lt;strong&gt;simplified, functional model of a planned product or component&lt;/strong&gt;. It serves as a preparation for production, but can also be used to illustrate a specific concept. The prototype is often the first milestone in a project to test the suitability and acceptance of a new technology, application or process.&lt;/p&gt;

&lt;p&gt;The prototype is an &lt;strong&gt;essential development step&lt;/strong&gt; regarding the future solution. However, it &lt;strong&gt;should not be used in production&lt;/strong&gt; after the feasibility check. The building blocks, on the other hand, can be used and improved in the final solution.&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@halacious?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Hal Gatewood&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/prototype?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>learning</category>
    </item>
    <item>
      <title>Spike Solutions - Short Notes</title>
      <dc:creator>Claudio Altamura</dc:creator>
      <pubDate>Mon, 31 Oct 2022 16:40:31 +0000</pubDate>
      <link>https://dev.to/claudioaltamura/spike-solutions-short-notes-4la1</link>
      <guid>https://dev.to/claudioaltamura/spike-solutions-short-notes-4la1</guid>
      <description>&lt;p&gt;Series on Software Design Practices - Part 1&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this small series on software design practices, I write about various practices. In every article, I give a brief and simple explanation. This is part 1. Let's start with spike solutions.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For me a spike is a &lt;strong&gt;way to figure out answers to a technical or design problem&lt;/strong&gt;. It's a solution to explore potential solutions. You make a spike to reduce the risk of a technical problem or to achieve a better estimate for a user story.&lt;/p&gt;

&lt;p&gt;Spike solutions could be technical or functional. &lt;strong&gt;Functional spikes&lt;/strong&gt; help you to analyze an overall solution. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is to be done? &lt;/li&gt;
&lt;li&gt;How do we break the work into smaller pieces? &lt;/li&gt;
&lt;li&gt;Where is the complexity hidden? &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Technical spikes&lt;/strong&gt; on the other side are a way to find different approaches for a problem, e.g. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;specific technical implementation &lt;/li&gt;
&lt;li&gt;or to get confidence that the chosen strategy works out.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Experience has shown that first you should focus on the problem with the spike and ignore other concerns, second not all spike solution are good enough to deploy in production. And at last, demos and discussions about the approaches are highly valuable steps.&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/photos/Lks7vei-eAg" rel="noopener noreferrer"&gt;charlesdeluvio&lt;/a&gt; on &lt;a href="https://unsplash.com/" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>softwaredesign</category>
      <category>programming</category>
    </item>
    <item>
      <title>AZ-900 Azure Fundamentals Resources</title>
      <dc:creator>Claudio Altamura</dc:creator>
      <pubDate>Wed, 25 May 2022 09:45:47 +0000</pubDate>
      <link>https://dev.to/claudioaltamura/az-900-azure-fundamentals-resources-3nbc</link>
      <guid>https://dev.to/claudioaltamura/az-900-azure-fundamentals-resources-3nbc</guid>
      <description>&lt;p&gt;My curated list&lt;/p&gt;

&lt;p&gt;There are plenty of resources out there to help you study for the AZ-900 exam. The exam is for candidates who are just beginning to work with cloud-based solutions and services.&lt;/p&gt;

&lt;p&gt;It’s an opportunity to gather knowledge of cloud concepts, services, workloads, security, privacy, pricing and support. Here comes my list:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloud Concepts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Benefits&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/learn/modules/fundamental-azure-concepts/benefits-of-cloud-computing" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/learn/modules/fundamental-azure-concepts/benefits-of-cloud-computing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Elastic&lt;br&gt;
&lt;a href="https://azure.microsoft.com/en-us/overview/what-is-elastic-computing/" rel="noopener noreferrer"&gt;https://azure.microsoft.com/en-us/overview/what-is-elastic-computing/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Consumption and fixed cost models&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/architecture/framework/cost/design-price" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/architecture/framework/cost/design-price&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Shared responsibility&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/security/fundamentals/shared-responsibility" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/security/fundamentals/shared-responsibility&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cloud Computing&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/learn/modules/fundamental-azure-concepts/types-of-cloud-computing" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/learn/modules/fundamental-azure-concepts/types-of-cloud-computing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;IAAS&lt;br&gt;
&lt;a href="https://azure.microsoft.com/en-us/overview/what-is-iaas/" rel="noopener noreferrer"&gt;https://azure.microsoft.com/en-us/overview/what-is-iaas/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PAAS&lt;br&gt;
&lt;a href="https://azure.microsoft.com/en-us/overview/what-is-paas/" rel="noopener noreferrer"&gt;https://azure.microsoft.com/en-us/overview/what-is-paas/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SAAS&lt;br&gt;
&lt;a href="https://azure.microsoft.com/en-us/overview/what-is-saas/" rel="noopener noreferrer"&gt;https://azure.microsoft.com/en-us/overview/what-is-saas/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cloud Models&lt;br&gt;
&lt;a href="https://azure.microsoft.com/en-us/overview/what-are-private-public-hybrid-clouds/" rel="noopener noreferrer"&gt;https://azure.microsoft.com/en-us/overview/what-are-private-public-hybrid-clouds/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Public cloud&lt;br&gt;
&lt;a href="https://azure.microsoft.com/en-gb/overview/what-is-a-public-cloud/" rel="noopener noreferrer"&gt;https://azure.microsoft.com/en-gb/overview/what-is-a-public-cloud/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Geographies&lt;br&gt;
&lt;a href="https://azure.microsoft.com/en-us/global-infrastructure/geographies/#overview" rel="noopener noreferrer"&gt;https://azure.microsoft.com/en-us/global-infrastructure/geographies/#overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Region and availability zones&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/learn/modules/azure-architecture-fundamentals/regions-availability-zones" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/learn/modules/azure-architecture-fundamentals/regions-availability-zones&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Compute&lt;br&gt;
&lt;a href="https://azure.microsoft.com/en-us/product-categories/compute/" rel="noopener noreferrer"&gt;https://azure.microsoft.com/en-us/product-categories/compute/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Virtual machines&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/learn/modules/azure-compute-fundamentals/azure-virtual-machines" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/learn/modules/azure-compute-fundamentals/azure-virtual-machines&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Serverless&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/learn/modules/azure-compute-fundamentals/azure-functions" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/learn/modules/azure-compute-fundamentals/azure-functions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Previews&lt;br&gt;
&lt;a href="https://azure.microsoft.com/en-us/support/legal/preview-supplemental-terms/" rel="noopener noreferrer"&gt;https://azure.microsoft.com/en-us/support/legal/preview-supplemental-terms/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pricing&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/learn/modules/plan-manage-azure-costs/" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/learn/modules/plan-manage-azure-costs/&lt;/a&gt; &lt;a href="https://azure.microsoft.com/en-us/pricing/calculator/" rel="noopener noreferrer"&gt;https://azure.microsoft.com/en-us/pricing/calculator/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://azure.microsoft.com/en-us/pricing/tco/calculator/" rel="noopener noreferrer"&gt;https://azure.microsoft.com/en-us/pricing/tco/calculator/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core Solutions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Big Data&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/architecture/guide/architecture-styles/big-data" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/architecture/guide/architecture-styles/big-data&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;IoT&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/iot-fundamentals/iot-introduction" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/iot-fundamentals/iot-introduction&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cognitive Services&lt;br&gt;
&lt;a href="https://azure.microsoft.com/en-us/services/cognitive-services/" rel="noopener noreferrer"&gt;https://azure.microsoft.com/en-us/services/cognitive-services/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Goverance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Strategy&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/learn/modules/build-cloud-governance-strategy-azure/" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/learn/modules/build-cloud-governance-strategy-azure/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Resource Groups&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/overview#resource-groups" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/overview#resource-groups&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Azure Management Groups&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/governance/management-groups/overview" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/governance/management-groups/overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Policy&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/governance/policy/overview" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/governance/policy/overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Blueprints&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/learn/modules/build-cloud-governance-strategy-azure/8-govern-subscriptions-azure-blueprints" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/learn/modules/build-cloud-governance-strategy-azure/8-govern-subscriptions-azure-blueprints&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Identity &amp;amp; Access&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Azure AD&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-whatis" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-whatis&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SSO&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/what-is-single-sign-on" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/what-is-single-sign-on&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MFA&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/authentication/concept-mfa-howitworks" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/active-directory/authentication/concept-mfa-howitworks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Management Tools&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Azure Advisor&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/advisor/" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/advisor/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Azure Cloud Shell&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/cloud-shell/overview" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/cloud-shell/overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Azure Cost Management&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/learn/paths/az-900-describe-azure-cost-management-service-level-agreements/" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/learn/paths/az-900-describe-azure-cost-management-service-level-agreements/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Azure Key Vault&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/key-vault/" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/key-vault/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Azure Monitor&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/azure-monitor/overview" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/azure-monitor/overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Azure Resource Manager&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/overview" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Azure Service Health&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/service-health/overview" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/service-health/overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Azure Service Trust&lt;br&gt;
&lt;a href="https://servicetrust.microsoft.com/" rel="noopener noreferrer"&gt;https://servicetrust.microsoft.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Network &amp;amp; Security&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Network&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/security/fundamentals/network-overview" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/security/fundamentals/network-overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CDN &lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/cdn/cdn-overview" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/cdn/cdn-overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Load Balancing &lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/architecture/guide/technology-choices/load-balancing-overview" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/architecture/guide/technology-choices/load-balancing-overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Defense in depth &lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/learn/modules/secure-network-connectivity-azure/2-what-is-defense-in-depth" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/learn/modules/secure-network-connectivity-azure/2-what-is-defense-in-depth&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Perimeter networks &lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/perimeter-networks" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/perimeter-networks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;VPN &lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/learn/modules/azure-networking-fundamentals/express-route-fundamentals" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/learn/modules/azure-networking-fundamentals/express-route-fundamentals&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Network Security &lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/networking-options" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/networking-options&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Network Security Groups &lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/virtual-network/network-security-groups-overview" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/virtual-network/network-security-groups-overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;DDoS &lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/ddos-protection/ddos-protection-overview" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/ddos-protection/ddos-protection-overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope this list helps you. 😀&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>azure</category>
    </item>
    <item>
      <title>How to test a Quarkus GraphQL API</title>
      <dc:creator>Claudio Altamura</dc:creator>
      <pubDate>Fri, 01 Oct 2021 14:43:38 +0000</pubDate>
      <link>https://dev.to/claudioaltamura/how-to-test-a-quarkus-graphql-api-2029</link>
      <guid>https://dev.to/claudioaltamura/how-to-test-a-quarkus-graphql-api-2029</guid>
      <description>&lt;p&gt;&lt;strong&gt;With curl, the GraphQL tool, insomnia and Rest-assured&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the previous &lt;a href="https://dev.to/claudioaltamura/graphql-apis-with-quarkus-3a6e"&gt;article&lt;/a&gt; I described the Quarkus GraphQL support and we discussed some GraphQL topics. Now  I’ll show you how to test your GraphQL API with curl, the GraphQL tool, insomnia and Rest-assured. As an example I use my superhero project from my last article, which &lt;a href="https://github.com/claudioaltamura/quarkus-graphql-superheroes" rel="noopener noreferrer"&gt;can be found on GitHub for you to run and play around with&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  curl
&lt;/h2&gt;

&lt;p&gt;If you would like to try the GraphQL API by yourself, start the Quarkus Project with mvn quarkus:dev and write the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    curl --request POST \
    --url http://localhost:8080/graphql \
    --header 'Content-Type: application/json' \
    --data '{"query":"{allCities{name}}"}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is quite simple. All we’ll need is to create a JSON payload, e.g. with a single element query with our query as its value. And as a result, you get this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"data":{"allCities":[{"name":"Gotham City"},{"name":"New York City"}]}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  GraphQL Tool
&lt;/h2&gt;

&lt;p&gt;Let's move on to the GraphQL tool. You can do the same query with the Quarkus GraphQL tool. Just enter &lt;a href="http://localhost:8080/q/graphql-ui/" rel="noopener noreferrer"&gt;http://localhost:8080/q/graphql-ui/&lt;/a&gt;. On the left side type in the query. Press the button with the triangle, and then you can see the result on the right side.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdt6kr111p7wies59eylo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdt6kr111p7wies59eylo.png" alt="GraphQL Tool" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Insomnia
&lt;/h2&gt;

&lt;p&gt;I think it's pretty cool that you can test both REST and GraphQL APIs with Insomnia. To create a GraphQL query, you have to switch from Body to GraphQL on the far left. And that's it.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnyr5k87zb7iu2pc6gtd6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnyr5k87zb7iu2pc6gtd6.png" alt="Insomnia" width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Rest-assured
&lt;/h2&gt;

&lt;p&gt;If you want to write automated tests, you could use Rest-Assured as we have already discovered. For the sake of completeness, I repeat the example from the last article. The response is plain JSON, so we can assert on the data returned by the API in the exact same manner with REST Assured as with REST APIs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@QuarkusTest
public class SuperheroTest {

    @Test
    void allCities() {
        final Response response = given()
                .contentType(ContentType.JSON)
                .body("{\"query\":\"{\\n allCities{\\n name\\n}\\n}\"}")
                .when()
                .post("/graphql")
                .then()
                    .assertThat()
                    .statusCode(200)
                .and()
                    .extract()
                    .response();

        final List&amp;lt;City&amp;gt; allCities = response.jsonPath().getList("data.allCities", City.class);
        assertThat(allCities)
                .isNotEmpty()
                .hasSize(2)
                .extracting(City::getName)
                .contains("Gotham City", "New York City");
    }

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

&lt;/div&gt;



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

&lt;p&gt;As you have seen in this article, it is quite simple to test a GraphQL API. You can use curl for a quick check or the GraphQL Tool / Insomnia if you need more convenience. It's even possible to use REST Assured to write automated tests because the response is pure JSON. &lt;/p&gt;

&lt;p&gt;Links&lt;br&gt;
Github &lt;a href="https://github.com/claudioaltamura/quarkus-graphql-superheroes" rel="noopener noreferrer"&gt;https://github.com/claudioaltamura/quarkus-graphql-superheroes&lt;/a&gt;&lt;br&gt;
Quarkus SmallRye GraphQL &lt;a href="https://quarkus.io/guides/smallrye-graphql" rel="noopener noreferrer"&gt;https://quarkus.io/guides/smallrye-graphql&lt;/a&gt;&lt;br&gt;
Insomnia &lt;a href="https://insomnia.rest/" rel="noopener noreferrer"&gt;https://insomnia.rest/&lt;/a&gt;&lt;br&gt;
Rest-assured &lt;a href="https://rest-assured.io/" rel="noopener noreferrer"&gt;https://rest-assured.io/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>graphql</category>
      <category>testing</category>
    </item>
    <item>
      <title>GraphQL APIs with Quarkus</title>
      <dc:creator>Claudio Altamura</dc:creator>
      <pubDate>Mon, 30 Aug 2021 07:54:35 +0000</pubDate>
      <link>https://dev.to/claudioaltamura/graphql-apis-with-quarkus-3a6e</link>
      <guid>https://dev.to/claudioaltamura/graphql-apis-with-quarkus-3a6e</guid>
      <description>&lt;p&gt;&lt;strong&gt;A query language for your API&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this article, I'll show you Quarkus GraphQL support. As an example, I use the Superheroes application from my previous articles. We will discuss some GraphQL topics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code, dependencies and model
&lt;/h2&gt;

&lt;p&gt;The source code for this app is available on &lt;a href="https://github.com/claudioaltamura/quarkus-graphql-superheroes" rel="noopener noreferrer"&gt;Github&lt;/a&gt;. If you like, you can try the examples by yourself. As dependencies, I included e.g. SmallRye GraphQL and lombok. Here you can have a detailed look at the &lt;a href="https://github.com/claudioaltamura/quarkus-graphql-superheroes/blob/main/pom.xml" rel="noopener noreferrer"&gt;pom.xml&lt;/a&gt; file.&lt;/p&gt;

&lt;p&gt;Quarkus helps you to create GraphQL APIs. The GraphQL schema is going to be generated. You just have to define your model. Here I show you as an example the Superhero data transfer object. I use DTOs to expose data from an API. Lombok &lt;code&gt;@Data&lt;/code&gt; takes care of getter, setter, toString, and the equals and hashCode methods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import lombok.Data;

@Data
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class Superhero {

    String name;
    City city;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fetching data
&lt;/h2&gt;

&lt;p&gt;To query all cities you just have to send a command like this to the GraphiQL UI &lt;a href="http://localhost:8080/q/graphql-ui/" rel="noopener noreferrer"&gt;http://localhost:8080/q/graphql-ui/&lt;/a&gt; .&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    allCities {
        name
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And with GraphQL it's quite easy to fetch object graphs. For example, we could query a city with their superheroes like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query getCity {
     city(cityId: 0) {
         name
         symbol
         superheroes {
             name
         }
     }
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Resolver and mutations on the server-side
&lt;/h2&gt;

&lt;p&gt;A resolver is responsible for defining queries. All Queries are located in &lt;code&gt;SuperheroResolver&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@GraphQLApi
public class SuperheroResolver {

    @Inject
    SuperheroService superheroService;

    @Query("allCities")
    @Description("Get all cities.")
    public List&amp;lt;City&amp;gt; getAllCities() {
        return superheroService.getAllCities();
    }
 ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have separated the mutations from the queries. Mutations are write operations like create, update or delete. Here I show the create() method from &lt;code&gt;SuperheroMutation&lt;/code&gt; with SuperheroInput as an input object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@GraphQLApi
public class SuperheroMutation {

    @Inject
    SuperheroService superheroService;

    @Mutation
    public Superhero createSuperhero(@Name("superhero") SuperheroInput superheroInput) {
        var superhero = new Superhero(superheroInput.getName(), superheroInput.getCity());
        superheroService.addSuperhero(superhero);
        return superhero;
    }
...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing GraphQL APIs
&lt;/h2&gt;

&lt;p&gt;It's pretty cool that Quarkus automatically generates a GraphQL schema based on your source code. To display the schema, just invoke &lt;a href="http://localhost:8080/graphql/schema.graphql" rel="noopener noreferrer"&gt;http://localhost:8080/graphql/schema.graphql&lt;/a&gt; . Here I want to show you quickly, how to write automated tests. How do we test a GraphQL API? Here comes &lt;a href="https://rest-assured.io/" rel="noopener noreferrer"&gt;Rest-Assured&lt;/a&gt; to the rescue. You can write tests in a manner as you already know from REST.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@QuarkusTest
public class SuperheroTest {

    @Test
    void allCities() {
        final Response response = given()
                .contentType(ContentType.JSON)
                .body("{\"query\":\"{\\n allCities{\\n name\\n}\\n}\"}")
                .when()
                .post("/graphql")
                .then()
                    .assertThat()
                    .statusCode(200)
                .and()
                    .extract()
                    .response();

        final List&amp;lt;City&amp;gt; allCities = response.jsonPath().getList("data.allCities", City.class);
        assertThat(allCities)
                .isNotEmpty()
                .hasSize(2)
                .extracting(City::getName)
                .contains("Gotham City", "New York City");
    }

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

&lt;/div&gt;



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

&lt;p&gt;I like the GraphQL support from Quarkus. It's great that the GraphQL schema is generated automatically through code and annotations. In the next part I'll show you how to test you GraphQL API with curl, the GraphiQL tool and insomnia.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@les_photos_de_raph?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Raphaël Biscaldi&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/graph?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/claudioaltamura/quarkus-graphql-superheroes" rel="noopener noreferrer"&gt;https://github.com/claudioaltamura/quarkus-graphql-superheroes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://quarkus.io/guides/smallrye-graphql" rel="noopener noreferrer"&gt;https://quarkus.io/guides/smallrye-graphql&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rest-assured.io/" rel="noopener noreferrer"&gt;https://rest-assured.io/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>graphql</category>
    </item>
    <item>
      <title>Document your database</title>
      <dc:creator>Claudio Altamura</dc:creator>
      <pubDate>Thu, 31 Dec 2020 19:03:01 +0000</pubDate>
      <link>https://dev.to/claudioaltamura/document-your-database-1cf9</link>
      <guid>https://dev.to/claudioaltamura/document-your-database-1cf9</guid>
      <description>&lt;p&gt;Simply and easily with SchemaSpy&lt;/p&gt;

&lt;p&gt;It has never been easier to document you db. SchemaSpy analyzes your database with tables, columns, types and indexes. It even creates diagrams with relationships of your existing database.&lt;/p&gt;

&lt;p&gt;The installation is super easy. You just have to download SchemaSpy &lt;a href="https://github.com/schemaspy/schemaspy/releases" rel="noopener noreferrer"&gt;https://github.com/schemaspy/schemaspy/releases&lt;/a&gt; and your database driver. Even Graphviz is no longer required. The configuration is really simple. Here I show a config.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;You run the tool with "java -jar schemaspy-6.1.0.jar -configFile config.properties". Then you get a HTML documenation and the diagrams look like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn7rxhi6p8sf34gw4c4zv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn7rxhi6p8sf34gw4c4zv.png" alt="relationship" width="800" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And a really cool trick is to integrate SchemaSpy in your CI/CD pipeline. &lt;/p&gt;

&lt;p&gt;I really like this tool.&lt;/p&gt;

</description>
      <category>database</category>
      <category>documentation</category>
    </item>
    <item>
      <title>Writing key values from Java to Consul</title>
      <dc:creator>Claudio Altamura</dc:creator>
      <pubDate>Fri, 11 Dec 2020 13:23:37 +0000</pubDate>
      <link>https://dev.to/claudioaltamura/writing-key-values-from-java-to-consul-58ik</link>
      <guid>https://dev.to/claudioaltamura/writing-key-values-from-java-to-consul-58ik</guid>
      <description>&lt;p&gt;How to write key values to Consul&lt;/p&gt;

&lt;p&gt;In the first example we are going to use the HTTP API directly, in the second one we are going to use the Java Consul API ecwid. On &lt;a href="https://github.com/claudioaltamura/spring-cloud-consul-example" rel="noopener noreferrer"&gt;Github&lt;/a&gt; you'll find all the examples. So, let's start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTP API&lt;/strong&gt;&lt;br&gt;
In this example we store the value "buon giorno" with the key "message". And all you have to do is a REST PUT operation with &lt;code&gt;v1/kv&lt;/code&gt; as a path. Here, Consul is reachable at &lt;code&gt;http://127.0.0.1:8500&lt;/code&gt;. That's it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"buon giorno"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;keyValuePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/config/consul-example/greetings/message"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;resourceUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://127.0.0.1:8500/v1/kv"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;keyValuePath&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;HttpRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newBuilder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resourceUrl&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PUT&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BodyPublishers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&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="nc"&gt;HttpClient&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newBuilder&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="na"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BodyHandlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofString&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Java Consul API&lt;/strong&gt;&lt;br&gt;
The library is quite easy. First you have to create a ConsulClient with an URL. You use that ConsulClient for reading and writing. It's just set* (with a key and the value) and get* methods. With the getKVValue() you get a Response instance. And for the real value you have to call getDecodedValue().  :-)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ConsulClient&lt;/span&gt; &lt;span class="n"&gt;consulClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ConsulClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://127.0.0.1:8500"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;consulClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setKVValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/config/blueprint/greetings/note"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;GetValue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;consulClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getKVValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/config/blueprint/greetings/note"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"value: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getValue&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getDecodedValue&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.consul.io/api-docs#http-methods" rel="noopener noreferrer"&gt;https://www.consul.io/api-docs#http-methods&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/Ecwid/consul-api" rel="noopener noreferrer"&gt;https://github.com/Ecwid/consul-api&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>consul</category>
    </item>
  </channel>
</rss>
