<?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: Davey</title>
    <description>The latest articles on DEV Community by Davey (@davey).</description>
    <link>https://dev.to/davey</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%2F449301%2Fa95499f4-a8cc-4735-a1eb-672f86486eea.png</url>
      <title>DEV Community: Davey</title>
      <link>https://dev.to/davey</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davey"/>
    <language>en</language>
    <item>
      <title>Configuring Cache Control for S3 Hosted Resources</title>
      <dc:creator>Davey</dc:creator>
      <pubDate>Sat, 01 Jan 2022 21:57:43 +0000</pubDate>
      <link>https://dev.to/aws-builders/configuring-cache-control-for-s3-hosted-resources-7hm</link>
      <guid>https://dev.to/aws-builders/configuring-cache-control-for-s3-hosted-resources-7hm</guid>
      <description>&lt;p&gt;When doing web development, one of the most important aspects is to get a site performing well with SEO (Search Engine Optimisation). One contributing factor to this (there are many), is effective resource caching. In this article, I'm going to show how to achieve this when resources are stored within a S3 bucket.&lt;/p&gt;

&lt;p&gt;Within Chrome, we can generate a Lighthouse report which will identify any images that are not cached correctly.&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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Flighthouse.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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Flighthouse.png" alt="Lighthouse Report"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this image, we can see that the default "cache policy" applied to resources in a S3 bucket is to tell the browser to &lt;em&gt;not&lt;/em&gt; cache the resource.&lt;/p&gt;

&lt;p&gt;To cache an resource, we need to send a &lt;code&gt;Cache-Control&lt;/code&gt; HTTP header with a suitable timeout to cache.  The timeout is measured in seconds and is identified as the &lt;code&gt;max-age&lt;/code&gt; of the resource.&lt;/p&gt;

&lt;p&gt;So for example, to tell the browser to cache resources for 1 day, we would use a max age of 60s * 60m * 24h = 86400.  To tell the browser to cache for 1 week, we would use a max-age of 60s * 60m * 24h * 7d = 604800.&lt;/p&gt;

&lt;p&gt;So, how do we configure S3 to specify a cache time ?&lt;/p&gt;

&lt;p&gt;Within the S3 Console, we can select either an individual resource, or an entire directory and specify this value.  To do this, we select to edit the &lt;code&gt;Metadata&lt;/code&gt; of the selected objects.&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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Feditmetadata.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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Feditmetadata.png" alt="Edit Metadata Report"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the resulting screen, we select the &lt;code&gt;Add Metadata&lt;/code&gt; section and add a &lt;code&gt;System Defined&lt;/code&gt; piece of metadata with a key of &lt;code&gt;Cache-Control&lt;/code&gt; and a &lt;code&gt;value&lt;/code&gt; of &lt;code&gt;max-age=&amp;lt;number of seconds&amp;gt;&lt;/code&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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Faddmetadata.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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Faddmetadata.png" alt="Add Metadata Report"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this image, you can see that I've set the &lt;code&gt;max-age&lt;/code&gt; to 7 days (60s * 60m * 24h * 7d).&lt;/p&gt;

&lt;p&gt;That's all there is to it! Save the changes to the metadata and S3 will start hosting your resources with an effective cache control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@marcojodoin?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Marc-Olivier Jodoin&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/speed?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>aws</category>
      <category>s3</category>
      <category>http</category>
    </item>
    <item>
      <title>Changing Default Search Provider in Firefox on Linux Mint</title>
      <dc:creator>Davey</dc:creator>
      <pubDate>Thu, 09 Dec 2021 22:53:42 +0000</pubDate>
      <link>https://dev.to/davey/changing-default-search-provider-in-firefox-on-linux-mint-4f5p</link>
      <guid>https://dev.to/davey/changing-default-search-provider-in-firefox-on-linux-mint-4f5p</guid>
      <description>&lt;p&gt;On Linux Mint, the default version of Firefox is installed and configured to allow the following search engines to be queried directly from the address bar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Yahoo!&lt;/li&gt;
&lt;li&gt;Startpage&lt;/li&gt;
&lt;li&gt;DuckDuckGo&lt;/li&gt;
&lt;li&gt;Wikipedia&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mint defines these as the default available set of search engines based upon 3 criteria (funding to Linux Mint, privacy support and whether the search engine is non-commercial).&lt;/p&gt;

&lt;p&gt;Other search engines such as Google, Bing or Twitter, etc. can easily be added into the default version of Firefox however.&lt;/p&gt;

&lt;p&gt;To add a different search provider, browse to &lt;a href="https://www.linuxmint.com/searchengines.php"&gt;Search Engines&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the bottom of the page, click on the icon of the requested search engine, then click on the &lt;code&gt;...&lt;/code&gt; button in the URL bar and select the &lt;code&gt;Add Search Engine&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;You then have the option to change the default search engine within Firefox preferences to your new choice.&lt;/p&gt;

</description>
      <category>firefox</category>
      <category>linux</category>
    </item>
    <item>
      <title>An Application Structure for Python REST APIs</title>
      <dc:creator>Davey</dc:creator>
      <pubDate>Tue, 05 Oct 2021 19:28:35 +0000</pubDate>
      <link>https://dev.to/davey/an-application-structure-for-python-rest-apis-km2</link>
      <guid>https://dev.to/davey/an-application-structure-for-python-rest-apis-km2</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this article, I'm going to show the structure that I use for REST based APIs using Python.  In Python, I use &lt;a href="https://flask.palletsprojects.com/en/2.0.x/"&gt;Flask&lt;/a&gt; to create APIs as I find this is easy to use, yet very powerful.  This article isn't a tutorial on using Flask, rather I'm showcasing the project structure I currently use that allows me to develop and test Flask applications easily.&lt;/p&gt;

&lt;p&gt;If you've never used Flask before, its a lightweight framework that allows Python developers to create both Web Applications and Web APIs.  It includes all the tools necessary and allows you to write easily testable applications.  Flask can easily be installed into an application using &lt;code&gt;pip&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;pip &lt;span class="nb"&gt;install &lt;/span&gt;flask
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Top level structure
&lt;/h2&gt;

&lt;p&gt;The basic structure I like to use is shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── application
│   ├── api
│   │   ├── &amp;lt;api definition&amp;gt;
│   │   └── &amp;lt;api definition&amp;gt;
│   ├── factory.py
│   ├── &amp;lt;logic classes&amp;gt;
├── app.py
├── Makefile
├── requirements.txt
└── tests
    ├── api
    │   ├── &amp;lt;api test&amp;gt;
    │   └── &amp;lt;api test&amp;gt;
    ├── context.py
    └── test_&amp;lt;logic classes&amp;gt;.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Within this structure, there are two top level folders, &lt;code&gt;application&lt;/code&gt; and &lt;code&gt;tests&lt;/code&gt;. These are used for storing the application code and the test code respectively.  I like to keep the test code separate from the application code and use this structure rather than placing the tests in the same folder as the application code.&lt;/p&gt;

&lt;p&gt;Within the &lt;code&gt;application&lt;/code&gt; and &lt;code&gt;tests&lt;/code&gt; folders, there are individual files for each api I want to develop.  Each of these corresponds to a different url.&lt;/p&gt;

&lt;h2&gt;
  
  
  Main Python Classes
&lt;/h2&gt;

&lt;p&gt;Within this directory structure, there are 3 Python files that are standard across each application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;app.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;application/factory.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tests/context.py&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lets take a look at each of these in turn.&lt;/p&gt;

&lt;h3&gt;
  
  
  app.py
&lt;/h3&gt;

&lt;p&gt;This is the main file to bootstrap the application and invokes the &lt;code&gt;create_app()&lt;/code&gt; method in the &lt;code&gt;application/factory.py&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;application.factory&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_app&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_app&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  application/factory.py
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;application.api.moon&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;moon&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;application.api.sun&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sun&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_app&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_blueprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url_prefix&lt;/span&gt;&lt;span class="o"&gt;=&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;api1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url_prefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_blueprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url_prefix&lt;/span&gt;&lt;span class="o"&gt;=&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;api2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url_prefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file creates a Flask application and registers the &lt;a href="https://flask.palletsprojects.com/en/2.0.x/blueprints/"&gt;Blueprints&lt;/a&gt; for the different API endpoints.&lt;/p&gt;

&lt;p&gt;Flask describes a blueprint as&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;a set of operations which can be registered on an application, even multiple times.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Essentially in this example, this means that we can register a set of APIs within the application with each API being stored in a separate file.  This allows us to easily create larger applications whilst maintaining smaller testable components.&lt;/p&gt;

&lt;h3&gt;
  
  
  tests/context.py
&lt;/h3&gt;

&lt;p&gt;This file allows the tests to be able to import the application logic when the tests are stored in a different folder to the applicaton source code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;application&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;


&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abspath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;'..'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  An example API
&lt;/h2&gt;

&lt;p&gt;Using the &lt;a href="https://rhodesmill.org/pyephem/"&gt;ephem&lt;/a&gt; library and the basic API structure above, lets see how we can write an API to return the phase of the moon on a given date.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining Endpoints
&lt;/h3&gt;

&lt;p&gt;To obtain the phase of the moon, I'm going to create three endpoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/moon/&lt;/li&gt;
&lt;li&gt;/moon/phase&lt;/li&gt;
&lt;li&gt;/moon/phase/&lt;strong&gt;yyyy&lt;/strong&gt;/&lt;strong&gt;mm&lt;/strong&gt;/&lt;strong&gt;dd&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To create the API, create a file called &lt;code&gt;application/api/moon.py&lt;/code&gt;.  To initialise the API with Flask, we need to register the Blueprint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Blueprint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;ephem&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;..moonphase&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MoonPhase&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;

&lt;span class="n"&gt;moon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Blueprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'moon'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;moon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url_prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'/moon'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a &lt;code&gt;Blueprint&lt;/code&gt; called &lt;code&gt;moon&lt;/code&gt; at the endpoint of &lt;code&gt;/moon&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To create the first of our endpoints (&lt;code&gt;/moon/&lt;/code&gt;), we need to define a method with a route of &lt;code&gt;/&lt;/code&gt; (as the API itself has the url_prefix of &lt;code&gt;/moon&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;moon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Moon API"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;mimetype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;APPLICATION_JSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create our second endpoint (&lt;code&gt;/moon/phase&lt;/code&gt;), we're going to return the Moon phase for the current date.  This can be achieved with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;moon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/phase'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;phase_today&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ephem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Moon&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;today&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;today&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;today&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'%Y/%m/%d'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MoonPhase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;moon_phase&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;today&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;today&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;today&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;__dict__&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                    &lt;span class="n"&gt;mimetype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;APPLICATION_JSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code, the method is decorated with the route &lt;code&gt;/phase&lt;/code&gt; making the url end with &lt;code&gt;/moon/phase&lt;/code&gt;.  This method uses the &lt;code&gt;json.dumps&lt;/code&gt; method to return a JSON representation of an instance of a &lt;code&gt;MoonPhase&lt;/code&gt; class as the response.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;MoonPhase&lt;/code&gt; is a &lt;code&gt;@dataclass&lt;/code&gt; defined within the &lt;code&gt;application/moonphase.py&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MoonPhase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;'''Data object to be passed out from the api to the caller'''&lt;/span&gt;
    &lt;span class="n"&gt;phase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, getting back to &lt;code&gt;moon.py&lt;/code&gt;, the final API endpoint (&lt;code&gt;/moon/phase/yyyy/mm/dd&lt;/code&gt;) can be defined as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;moon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/phase/&amp;lt;year&amp;gt;/&amp;lt;month&amp;gt;/&amp;lt;day&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;phase_specific_day&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ephem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Moon&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MoonPhase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;moon_phase&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;__dict__&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                    &lt;span class="n"&gt;mimetype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;APPLICATION_JSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method is almost identical to the previous, except that the year, month and day are passed in as parameters into the REST API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the API
&lt;/h2&gt;

&lt;p&gt;To test the API, we can use &lt;a href="https://docs.pytest.org/en/6.2.x/"&gt;PyTest&lt;/a&gt; and write a test within the &lt;code&gt;tests/api&lt;/code&gt; folder, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;application.factory&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_app&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pytest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;..context&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;


&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fixture&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;create_app&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;test_client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_home_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/moon/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'Moon API'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Route should return "Moon API"'&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_moon_phase_today&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/moon/phase'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Invalid status code'&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="s"&gt;'phase'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Invalid phase'&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="s"&gt;'year'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Invalid year'&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="s"&gt;'month'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Invalid month'&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="s"&gt;'day'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Invalid day'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;In this article, I've shown a standard template that can be used to develop and test Flask applications.  I've then shown an example of adding an API using this template.&lt;/p&gt;

&lt;p&gt;The code is stored in a modular fashion so the application can easily be enhanced with more APIs.  Also, test application is structured so that tests can easily be written for each of the APIs and other classes within the application.&lt;/p&gt;

&lt;p&gt;The complete source code associated with this article is available on &lt;a href="https://github.com/doobrie/flask-api-template"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@myphotocave?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Raghav Bhasin&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/flask?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Connecting to an AWS MySQL RDS using a Bastion Host</title>
      <dc:creator>Davey</dc:creator>
      <pubDate>Wed, 08 Sep 2021 22:02:22 +0000</pubDate>
      <link>https://dev.to/aws-builders/connecting-to-an-aws-mysql-rds-using-a-bastion-host-265j</link>
      <guid>https://dev.to/aws-builders/connecting-to-an-aws-mysql-rds-using-a-bastion-host-265j</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In my &lt;a href="https://www.davidsalter.com/view/accessing-a-rds-database-locally" rel="noopener noreferrer"&gt;previous article&lt;/a&gt;, I showed how to connect to an Amazon RDS host by changing the security group and allowing direct access to port 3306.  This works but does have security implications in that potentially the entire internet can start pinging your RDS server.&lt;/p&gt;

&lt;p&gt;In this article, I’m going to show how to use a Bastion host which does not need us to expose the database access port (port 3306 in the case of MySQL) to the internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Bastion Host ?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Bastion_host" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt; defines a Bastion Host as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;a special-purpose computer on a network specifically designed and configured to withstand attacks. The computer generally hosts a single application or process&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What this means, in terms of connecting to a MySQL RDS instance, is that MySQL is not installed on the Bastion server, rather we use the Bastion server as a “jump” point to allow us to get to the real database server.&lt;/p&gt;

&lt;p&gt;I'm not going to go into details on how to harden a bastion server, I'm concentrating on how to access MySQL through the server.  Check out &lt;a href="https://aws.amazon.com/blogs/security/controlling-network-access-to-ec2-instances-using-a-bastion-server/" rel="noopener noreferrer"&gt;this blog post&lt;/a&gt; for more details on how to controll network access using a bastion server.&lt;/p&gt;

&lt;p&gt;When using a Bastion server, the network topology looks something like:&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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Frds%2FBastionHost.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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Frds%2FBastionHost.png" alt="Bastion Host Network Topology"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In terms of AWS, to create a Bastion Server, we need to create a EC2 instance (in my case, I created a t2.micro instance).  We need to ensure that the EC2 instance is in the same VPC as the RDS database otherwise they will not be able to connect to each other.  This is a key point.  If the bastion server and the RDS database are not in the same VPC, then this technique will not work.&lt;/p&gt;

&lt;p&gt;For the security groups, the Bastion server should be configured to only allow ssh traffic from a known host(s) which is your local network.  Note that it is &lt;em&gt;not&lt;/em&gt; necessary to allow network traffic into the bastion host on the database port (3306).  The only access required from the global internet is via port 22 (ssh port).&lt;/p&gt;

&lt;p&gt;The security group for the RDS instance should be configured to allow traffic from within the VPC which enables access from the Bastion host.&lt;/p&gt;

&lt;h2&gt;
  
  
  SSH Tunneling
&lt;/h2&gt;

&lt;p&gt;Once we've set up the networking and got an EC2 instance that can be connected via ssh from a local machine, we need to set up a ssh tunnel from our local machine through to the RDS database via the bastion host.  This is achieved with the &lt;code&gt;ssh&lt;/code&gt; command.  If you're a Linux/Mac user, this will most likely already be installed.  For Windows users, it is available from within Powershell.&lt;/p&gt;

&lt;p&gt;An ssh tunnel is basically a way of routing network traffic from one place to another via a ssh host.  In our case, we are routing traffic from our local machine to a RDS instance via a Bastion host.  For more information about ssh tunnelling, check out &lt;a href="https://www.ssh.com/academy/ssh/tunneling" rel="noopener noreferrer"&gt;this article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To create a ssh tunnel, we execute the &lt;code&gt;ssh&lt;/code&gt; command as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; &amp;lt;&lt;span class="nb"&gt;local &lt;/span&gt;port&amp;gt;:&amp;lt;database host name&amp;gt;:&amp;lt;remote port&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &amp;lt;bastion-user&amp;gt;@&amp;lt;bastion-host&amp;gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &amp;lt;bastion-host-key-file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;&amp;lt;local port&amp;gt;&lt;/code&gt; is the source port on the local machine that we can use for connecting to from local applications.  It makes sense to set this the same as the remote port if possible, but this can be set to any free port.  For connection to MySQL, I set this to &lt;code&gt;3306&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;database host name&amp;gt;&lt;/code&gt; is the host name of the RDS instance.  This can be found in the RDS console but will be along the lines of &lt;code&gt;xxx.xxx.us-east-1.rds.amazonaws.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;remote port&amp;gt;&lt;/code&gt; is the port number we want to connect to on the remote RDS instance.  For MySQL, this is usually &lt;code&gt;3306&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;bastion-user&amp;gt;&lt;/code&gt; is the username that can be used to connect to the bastion host.  For a standard EC2 instance, this would usually be &lt;code&gt;ec2-user&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;bastion-host&amp;gt;&lt;/code&gt; is the host name or ip address of the bastion server.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;bastion-host-key-file&amp;gt;&lt;/code&gt; is the full path to the &lt;code&gt;.pem&lt;/code&gt; key file created when the EC2 instance was created.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-N&lt;/code&gt; tells ssh not to execute a remote command, essentially telling it to create a tunnel only and no interactive terminal connection.&lt;/p&gt;

&lt;p&gt;The full ssh command would therfore look something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; 3306:xxx.xxx.us-east-1.rds.amazonrds.com:3306 &lt;span class="se"&gt;\&lt;/span&gt;
  ec2-user@xxx.xxx.xxx.xxx &lt;span class="nt"&gt;-i&lt;/span&gt; ~/bastion_key.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Connection to MySQL
&lt;/h2&gt;

&lt;p&gt;After creating a tunnel, we can connect to MySQL as though the database were running locally.  The host name will be &lt;code&gt;127.0.0.1&lt;/code&gt; and the port will be &lt;code&gt;3306&lt;/code&gt; (&lt;code&gt;127.0.0.1&lt;/code&gt; is implicitly implied by the &lt;code&gt;ssh&lt;/code&gt; command above and &lt;code&gt;3306&lt;/code&gt; is the local port we defined above).&lt;/p&gt;

&lt;p&gt;Note that we have to use &lt;code&gt;127.0.0.1&lt;/code&gt; instead of &lt;code&gt;localhost&lt;/code&gt; when connecting via the ssh tunnel, or the MySQL client will believe we are attempting to connect to a local instance via shared memory or via a Unix socket and will not connect.  For more details check out the &lt;a href="https://dev.mysql.com/doc/refman/5.7/en/connecting.html" rel="noopener noreferrer"&gt;MySQL Documentation&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ ❯ mysqlsh  &lt;span class="nt"&gt;-u&lt;/span&gt; admin &lt;span class="nt"&gt;-h&lt;/span&gt; 127.0.0.1
Please provide the password &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="s1"&gt;'admin@127.0.0.1'&lt;/span&gt;: &lt;span class="k"&gt;**********&lt;/span&gt;
Save password &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="s1"&gt;'admin@127.0.0.1'&lt;/span&gt;? &lt;span class="o"&gt;[&lt;/span&gt;Y]es/[N]o/Ne[v]er &lt;span class="o"&gt;(&lt;/span&gt;default No&lt;span class="o"&gt;)&lt;/span&gt;: v
MySQL Shell 8.0.26

Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt; 2016, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates.
Other names may be trademarks of their respective owners.

Type &lt;span class="s1"&gt;'\help'&lt;/span&gt; or &lt;span class="s1"&gt;'\?'&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="nb"&gt;help&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="s1"&gt;'\quit'&lt;/span&gt; to exit.
Creating a session to &lt;span class="s1"&gt;'admin@127.0.0.1'&lt;/span&gt;
Fetching schema names &lt;span class="k"&gt;for &lt;/span&gt;autocompletion... Press ^C to stop.
Your MySQL connection &lt;span class="nb"&gt;id &lt;/span&gt;is 22
Server version: 8.0.23 Source distribution
No default schema selected&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="se"&gt;\u&lt;/span&gt;se &amp;lt;schema&amp;gt; to &lt;span class="nb"&gt;set &lt;/span&gt;one.
 MySQL  127.0.0.1:3306 ssl  JS &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;In this article, we've seen how we can use the &lt;code&gt;ssh&lt;/code&gt; command to create a tunnel between our local machine and a RDS server via a bastion host.  This allows us to connect to a RDS instance without having to expose the RDS instance directly to the internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@andrewtneel?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Andrew Neel&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/bastion?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>aws</category>
      <category>rds</category>
      <category>mysql</category>
    </item>
    <item>
      <title>Accessing a RDS Database Locally</title>
      <dc:creator>Davey</dc:creator>
      <pubDate>Fri, 27 Aug 2021 21:55:59 +0000</pubDate>
      <link>https://dev.to/aws-builders/accessing-a-rds-database-locally-3m8c</link>
      <guid>https://dev.to/aws-builders/accessing-a-rds-database-locally-3m8c</guid>
      <description>&lt;p&gt;Elastic Beanstalk (EB) is a Platform As A Service from AWS that allows you to easily deploy applications without having to worry about setting up the base infrastructure, such as HTTP servers, or load balancers.  One of the benefits of EB is that is allows us to create a database on RDS when creating a new application, making the entire deployment of an application much easier.&lt;/p&gt;

&lt;p&gt;RDS however does not provide a user interface to execute SQL against a created database (unless its been created as an Aurora Serverless Database), so how can we execute SQL commands against the database?  If we were deploying our application to an EC2 instance, we could simply log onto the instance and connect directly to the database using a tool such as &lt;code&gt;mysql&lt;/code&gt;.  We can’t do this with EB, however, but we can connect to the database from our local PC.&lt;/p&gt;

&lt;p&gt;When creating the database from EB, we get the option of specifying whether we want the database to be publicly accessible.  This is the first step to being able to connect to an RDS database.  So, let’s try and connect and see what happens.&lt;/p&gt;

&lt;p&gt;Browsing to the RDS console, we can see the connection details for all our RDS databases, for example:&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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Frds%2Frds1.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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Frds%2Frds1.png" alt="RDS Connectivity"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On this screen, we can see the endpoint, so let’s try connecting from the MySQL Workbench client. (Don’t try connecting to my database – I’ve deleted it for security purposes so the endpoint in this article doesn’t exist anymore).&lt;/p&gt;

&lt;p&gt;If we enter the endpoint and username and password in MySQL Workbench, we’ll see an error indicating that a connection could not be made to the database.&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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Frds%2Frds2.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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Frds%2Frds2.png" alt="MySQL Workbench Connection Error"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So why do we get this error?  Well, when we created the EB application, AWS created a VPC and added some security groups that explicitly deny access from outside of the VPC.&lt;/p&gt;

&lt;p&gt;From the RDS Console, we can see the &lt;code&gt;Security Group Rules&lt;/code&gt; and can see that we have both an Inbound and Outbound set of rules.&lt;/p&gt;

&lt;p&gt;The outbound rule is set to allow all traffic to any address, however the inbound rule only allows inbound traffic from within the VPC.&lt;/p&gt;

&lt;p&gt;We can change this by editing the Inbound Rules and adding a new rule, specifying the address we will allow inbound data to originate from. &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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Frds%2Frds3.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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Frds%2Frds3.png" alt="Security Group Inbound Rules"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This &lt;code&gt;source&lt;/code&gt; address can be any custom IP address, however, the option &lt;code&gt;My IP&lt;/code&gt; is available to explicitly only allow access from your current IP address.&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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Frds%2Frds4.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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Frds%2Frds4.png" alt="Source IP Address"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note, if you have a dynamic IP address, next time you connect to the internet your IP address may change and you won’t be allowed to access, but the user with your previous IP address will.  Please be aware of this!&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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Frds%2Frds5.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%2Fdavidsalterassets.s3.eu-west-2.amazonaws.com%2Frds%2Frds5.png" alt="Inbound Security Rules"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once we’ve added a new rule, we can connect from MySQL workbench on our local PC and execute the required SQL against the database.&lt;/p&gt;

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

&lt;p&gt;In this post, I’ve shown how you can connect to a RDS instance from a local application (MySQL Workbench in this example).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Please be careful when editing Security Groups in AWS, as you can lock yourself out of your system, or can easily allow access for potentially malicious users&lt;/em&gt;.  For more information, please checkout the documentation at &lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html" rel="noopener noreferrer"&gt;AWS&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@benjaminlehman?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;benjamin lehman&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/database?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>aws</category>
      <category>mysql</category>
    </item>
    <item>
      <title>Creating a VM on Google Cloud Platform</title>
      <dc:creator>Davey</dc:creator>
      <pubDate>Thu, 15 Jul 2021 20:18:32 +0000</pubDate>
      <link>https://dev.to/davey/creating-a-vm-on-google-cloud-platform-43mp</link>
      <guid>https://dev.to/davey/creating-a-vm-on-google-cloud-platform-43mp</guid>
      <description>&lt;p&gt;Google Cloud Platform is a set of services that Google offer to customers providing different type of computing functionality, for example, Virtual Machines, Databases, Message Queues etc. These services are running on the same global infrastructure that Google uses for its products. In this article, I’ll show how to create and connect to a Virtual Machine running on the Google Cloud.&lt;/p&gt;

&lt;p&gt;To complete the actions in this article, you’ll need a Google Cloud Platform account. These can be created at &lt;a href="https://cloud.google.com"&gt;https://cloud.google.com&lt;/a&gt;. There is a charge for using the Google Cloud Platform, but when you sign up you get $300 off free credit. There are also several services that are always free as long as you are within the free usage tier. Information about GCP pricing can be found at &lt;a href="https://cloud.google.com/pricing/"&gt;https://cloud.google.com/pricing/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a VM
&lt;/h2&gt;

&lt;p&gt;The easiest way of creating a VM within GCP is from within the Web Console. Navigate to &lt;a href="https://console.cloud.google.com/"&gt;https://console.cloud.google.com/&lt;/a&gt; to display the web console. Along the top of the page, you see the menu and the name of the project you have selected. When signing up, GCP creates an initial project for you. If you do not have one created, navigate to &lt;a href="https://console.cloud.google.com/projectcreate"&gt;https://console.cloud.google.com/projectcreate&lt;/a&gt; to create a new project and then return to the console home page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--86Z7d4lY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rfwthclpluhhlbpszy9c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--86Z7d4lY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rfwthclpluhhlbpszy9c.png" alt="VM Instances"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The screenshot above shows the GCP console together with the &lt;code&gt;My First Project&lt;/code&gt; selected.&lt;/p&gt;

&lt;p&gt;From within the console, press the menu button at the top left. A menu is displayed down the left hand side of the page showing all of the different options that can be managed from within the console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pmaA3WHD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8pkvv0cp6omlkjs2rtep.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pmaA3WHD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8pkvv0cp6omlkjs2rtep.png" alt="Google Cloud Platform Console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this article, we’re interested in creating a new Virtual Machine. VM’s are part of the GCP &lt;code&gt;Compute Engine&lt;/code&gt;, so select the option Compute Engine from the menu.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WJNPoa5w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jpthlw83lyhssecy0kc1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WJNPoa5w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jpthlw83lyhssecy0kc1.png" alt="VM Instances"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the &lt;code&gt;Compute Engine&lt;/code&gt; page, a list of VM’s is displayed that you have previously created. If this is the first VM you are creating, you will see the welcome page and be presented with the option of creating a new VM. Simply press the &lt;code&gt;Create&lt;/code&gt; button to continue.&lt;/p&gt;

&lt;p&gt;In the following page, we can enter details of the VM we want to create, e.g. we can name it, select the region to create it in, select the amount of RAM and disk space it has as well as all the other options that go to define a VM. For this article, since we’re just creating a basic VM, we’ll go through the common options that are needed to create a VM.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O3N5p7T7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/czd5rtugn95f25ar48st.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O3N5p7T7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/czd5rtugn95f25ar48st.png" alt="VM Details"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Name
&lt;/h3&gt;

&lt;p&gt;This is the name of both the VM when it is running, and the name that is displayed in the console where you manage your instances. The name must be in lowercase but can include numbers or hyphens.&lt;/p&gt;

&lt;h3&gt;
  
  
  Region / Zone
&lt;/h3&gt;

&lt;p&gt;This defines the geographic location of where the VM is created. This defaults to &lt;code&gt;us-east1&lt;/code&gt; which is in South Carolina. For the purposes of this article, we will leave the default region as &lt;code&gt;us-east1&lt;/code&gt; and the default Zone as &lt;code&gt;us-east1-b&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Machine Type
&lt;/h3&gt;

&lt;p&gt;This option allows us to configure the number of cores, memory and GPUs that the VM will possess. Note that GPUs are not presently available in all regions, so if you select a region other than &lt;code&gt;us-east1&lt;/code&gt;, the options may be different from those shown here.&lt;/p&gt;

&lt;p&gt;Selecting the CPU drop down, allows the number of CPUs used by the VM to be defined. Obviously, the more CPUs you select, the higher the cost of the VM per month. The estimated cost of the VM is always displayed on the right hand side of the page whilst customising the VM.&lt;/p&gt;

&lt;p&gt;For this article, select the Machine Type as &lt;code&gt;Micro&lt;/code&gt;. This defaults the VM to 1 shared CPU with 0.6Gb RAM and no GPU. This is the smallest of the VMs that can be created, and this VM type can be run in the free-tier. For more information about the Free Tier, and what you can run in it, see &lt;a href="https://cloud.google.com/free/docs/gcp-free-tier?hl=en_GB&amp;amp;_ga=2.180966501.-319154563.1548685428#always-free"&gt;https://cloud.google.com/free/docs/gcp-free-tier?hl=en_GB&amp;amp;_ga=2.180966501.-319154563.1548685428#always-free&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Boot Disk
&lt;/h3&gt;

&lt;p&gt;Next, we get to define the Boot disk and operating system for the VM.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HgeoM1hb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ip9gbcpq2hdpqyk2xa3i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HgeoM1hb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ip9gbcpq2hdpqyk2xa3i.png" alt="Boot Disk"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Within this section, we can select the OS, the size of the boot disk and a number of different image types. The default option is to use Debian Linux 9 (stretch) with a 10 GB boot disk. This is fine for demonstration purposes, but can be changed to whatever is best for your use case. A variety of different Linux and Windows operating systems can be selected from here if required.&lt;/p&gt;

&lt;h3&gt;
  
  
  Identity and api access
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vVDklHCZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2311f2j0ff4kg007ay9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vVDklHCZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2311f2j0ff4kg007ay9w.png" alt="Identity and API Access"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Identity and api access section allows us to define what account, and therefore what security, the applications running on the VM will use. For this article, we aren’t running any applications on the VM, so we can leave the default settings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Firewall
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aghiWbE8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sv1prj5t62znkpcwrvje.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aghiWbE8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sv1prj5t62znkpcwrvje.png" alt="Firewall"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next section allows us to define whether HTTP and HTTPS traffic are allowed to the instance. Since we’re not deploying a web server, we can leave these settings unchecked.&lt;/p&gt;

&lt;h3&gt;
  
  
  ssh access
&lt;/h3&gt;

&lt;p&gt;Once our VM is running, we’ll want to connect to it via SSH so that we can see that everything is there as expected. To be able to do this, we need to add our SSH public key onto the Virtual Machine. Your public key is usually stored within the &lt;code&gt;~/.ssh/id_rsa.pub&lt;/code&gt; file. If you don’t have a public / private key, now would be a good time to create one :)&lt;/p&gt;

&lt;p&gt;Take a copy of your public key and paste it into the &lt;code&gt;keydata&lt;/code&gt; box on the &lt;code&gt;Security&lt;/code&gt; tab. If you’re on a Mac, you can copy your public key into the clipboard with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat ~/.ssh/id_rsa.pub | pbcopy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qDCEUpHH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bx7nvqgzu0wz0igun3jv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qDCEUpHH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bx7nvqgzu0wz0igun3jv.png" alt="Upload SSH Key"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting the VM
&lt;/h2&gt;

&lt;p&gt;That’s all that’s needed to get a basic VM up and running. Of course, there are many other options available which I’ll go through in another article. For the moment though, let’s start the VM by clicking the &lt;code&gt;Create&lt;/code&gt; button.&lt;/p&gt;

&lt;p&gt;Upon pressing this button, GCP will start to provision the VM. This will take up to a minute, however when it’s complete, you will see a list of VM’s that you’ve created along with tools to manage the VMs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WJNPoa5w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jpthlw83lyhssecy0kc1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WJNPoa5w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jpthlw83lyhssecy0kc1.png" alt="VM Instances"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting to the VM
&lt;/h2&gt;

&lt;p&gt;In the list of VMs, you can see the name (&lt;code&gt;webserver1&lt;/code&gt; in this example) along with its internal and external ip addresses. To connect to the VM, we need to ssh using the username we defined previously and the public IP address.&lt;/p&gt;

&lt;p&gt;From the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;david$ ssh david@104.196.139.230
The authenticity of host '104.196.139.230 (104.196.139.230)' can't be established.
ECDSA key fingerprint is SHA256:cxuubyAwHqGG6SDyGdHHlVtPLnQsYJNpT57E2mok4Dg.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '104.196.139.230' (ECDSA) to the list of known hosts.
Linux webserver1 4.9.0-8-amd64 #1 SMP Debian 4.9.130-2 (2018-10-27) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
david@webserver1:~$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Destroying the VM
&lt;/h2&gt;

&lt;p&gt;That’s all there is to it. We’ve created a Debian VM, and connected to it. We can now use the VM for whatever we need.&lt;/p&gt;

&lt;p&gt;Finally, to delete the VM (and ensure there are no recurring costs), select the VM in the list of instances and press the Trash Can Icon. Remember, VMs are charged by usage, so if you’re not using it, delete it to stop recurring costs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@jordanharrison?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Jordan Harrison&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/server?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>googlecloud</category>
    </item>
    <item>
      <title>Creating MicroProfile Applications From The Command Line</title>
      <dc:creator>Davey</dc:creator>
      <pubDate>Tue, 13 Jul 2021 21:16:07 +0000</pubDate>
      <link>https://dev.to/davey/creating-microprofile-applications-from-the-command-line-2aba</link>
      <guid>https://dev.to/davey/creating-microprofile-applications-from-the-command-line-2aba</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://microprofile.io/"&gt;MicroProfile&lt;/a&gt; initiative provides the excellent web based &lt;a href="https://start.microprofile.io/"&gt;Starter&lt;/a&gt; application to allow developers to easily scaffold MicroProfile based applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  MicroProfile Starter REST Interface
&lt;/h2&gt;

&lt;p&gt;Recently, a new version of the Starter has been published that exposes a REST interface allowing MicroProfile applications to be easily created from the command line. In this post, we’ll show how this can be used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supported Servers
&lt;/h2&gt;

&lt;p&gt;To create a project with the default settings, a HTTP GET request must be made to the following url: &lt;code&gt;https://start.microprofile.io/api/1/project?supportedServer=&amp;lt;SERVER&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This url takes as a minimum one parameter, &lt;code&gt;&amp;lt;SERVER&amp;gt;&lt;/code&gt;, which specifies which application server (that supports MicroProfile) to use.&lt;/p&gt;

&lt;p&gt;So, how do we get a valid &lt;code&gt;&amp;lt;SERVER&amp;gt;&lt;/code&gt;. Well, not all application servers provide the same level of support for different versions on MicroProfile, so first, we must decide which version of MicroProfile we wish to target. Once we know that, we can select an appropriate application server and then create a project.&lt;/p&gt;

&lt;p&gt;The first stage therefore, is to get a list of different versions of MicroProfile. We can then query the service to establish which application servers support the requested version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supported Versions
&lt;/h2&gt;

&lt;p&gt;To get a list of MicroProfile versions, we must perform a HTTP GET request to &lt;code&gt;https://start.microprofile.io/api/1/mpVersion&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;david ~ $ curl https://start.microprofile.io/api/1/mpVersion
["MP22","MP21","MP20","MP14","MP13","MP12"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells us that there are currently 6 versions of MicroProfile that are supported by the REST service: from MicroProfile 1.2 through to MicroProfile 2.2&lt;/p&gt;

&lt;p&gt;As different application servers support different versions of MicroProfile, we can query the service to establish which application servers are supported for a specified version of MicroProfile. For example, to get a list of application servers that support MicroProfile 2.0, we would execute the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;david ~ $ curl https://start.microprofile.io/api/1/mpVersion/MP20
{"supportedServers":["KUMULUZEE","LIBERTY","PAYARA_MICRO","TOMEE"],"specs":["CONFIG","FAULT_TOLERANCE","JWT_AUTH","METRICS","HEALTH_CHECKS","OPEN_API","OPEN_TRACING","REST_CLIENT"]}
This api call tells us that Kumuluzee, Open Liberty, Payara Micro and TomEE support version 2.0 of MicroProfile and they support the MicroProfile APIs:
Fault Tolerance
JWT Authentication
Metrics
Health Checks
Open API
Open Tracing
REST Client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We now have sufficient information to create a basic MicroProfile 2.0 application. In this example, we’ll use the TomEE application server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating an Application
&lt;/h2&gt;

&lt;p&gt;So, to create a basic MicroProfile application, execute the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;david ~ $ curl -O -J https://start.microprofile.io/api/1/project?supportedServer=TOMEE
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 12555  100 12555    0     0  44818      0 --:--:-- --:--:-- --:--:-- 44679
curl: Saved to filename 'demo.zip'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-O&lt;/code&gt; parameter tells curl to download a file rather than output to the console. The &lt;code&gt;-J&lt;/code&gt; parameter tells curl to correctly name the file after it is downloaded, in this case, &lt;code&gt;demo.zip&lt;/code&gt;. If the -J parameter was not specified, the downloaded file would be called &lt;code&gt;project?supportedServer=TOMEE&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So, what does the created project look like? A bit 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;demo/src/test/java/.gitkeep
demo/src/main/webapp/WEB-INF/beans.xml
demo/src/main/java/com/example/demo/HelloController.java
demo/pom.xml
demo/src/main/java/com/example/demo/health/ServiceHealthCheck.java
demo/src/main/resources/META-INF/microprofile-config.properties
demo/src/main/java/com/example/demo/resilient/ResilienceController.java
demo/src/main/webapp/.gitkeep
demo/src/test/java/com/example/demo/JWTClient.java
demo/src/main/java/com/example/demo/config/ConfigTestController.java
demo/src/test/resources/privateKey.pem
demo/src/main/java/com/example/demo/DemoRestApplication.java
demo/readme.md
demo/src/main/resources/.gitkeep
demo/src/main/java/com/example/demo/secure/ProtectedController.java
demo/src/test/java/com/example/demo/MPJWTToken.java
demo/src/main/resources/publicKey.pem
demo/src/main/webapp/index.html
demo/src/main/java/com/example/demo/metric/MetricController.java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing you notice here is that the package names are of the format &lt;code&gt;com.example.demo&lt;/code&gt;. We can easily refactor this in an IDE, or we could specify the Maven Group and Artifact Id’s and have the project created exactly as we want it, by appending the &lt;code&gt;groupId&lt;/code&gt; and &lt;code&gt;artifactId&lt;/code&gt; arguments to the call.&lt;/p&gt;

&lt;p&gt;For example, to create the project with a &lt;code&gt;groupId&lt;/code&gt; of &lt;code&gt;com.acme&lt;/code&gt; and an &lt;code&gt;artifactId&lt;/code&gt; of &lt;code&gt;customer-service&lt;/code&gt;, we would append the &lt;code&gt;groupId&lt;/code&gt; and &lt;code&gt;artifactId&lt;/code&gt; parameters as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;david ~ $ curl -O -J 'https://start.microprofile.io/api/1/project?supportedServer=TOMEE&amp;amp;groupId=com.acme&amp;amp;artifactId=customer-service'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 13420  100 13420    0     0  45698      0 --:--:-- --:--:-- --:--:-- 45802
curl: Saved to filename 'customer-service.zip'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, note that the download is called &lt;code&gt;customer-service.zip&lt;/code&gt; and its contents are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;customer-service/src/main/java/com/acme/customer/service/metric/MetricController.java
customer-service/src/main/java/com/acme/customer/service/resilient/ResilienceController.java
customer-service/pom.xml
customer-service/src/main/java/com/acme/customer/service/CustomerserviceRestApplication.java
customer-service/src/main/webapp/index.html
customer-service/src/main/webapp/WEB-INF/beans.xml
customer-service/src/main/java/com/acme/customer/service/HelloController.java
customer-service/src/main/java/com/acme/customer/service/config/ConfigTestController.java
customer-service/src/main/webapp/.gitkeep
customer-service/src/main/resources/META-INF/microprofile-config.properties
customer-service/src/main/resources/.gitkeep
customer-service/src/test/resources/privateKey.pem
customer-service/src/test/java/com/acme/customer/service/JWTClient.java
customer-service/src/main/java/com/acme/customer/service/health/ServiceHealthCheck.java
customer-service/src/main/resources/publicKey.pem
customer-service/src/main/java/com/acme/customer/service/secure/ProtectedController.java
customer-service/src/test/java/.gitkeep
customer-service/readme.md
customer-service/src/test/java/com/acme/customer/service/MPJWTToken.java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the starter web application, we can also request to add examples for the different MicroProfile specifications (such as Config or Fault Tolerance) into the generated application. We can also do this with the REST client by utilizing the &lt;code&gt;selectedSpecs&lt;/code&gt; parameter. The values used for this parameter are those returned in the curl shown at the beginning of this post.&lt;/p&gt;

&lt;p&gt;So for example, to add an example for Config and Fault Tolerance, we would use the following curl:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;david ~ $ curl -O -J 'https://start.microprofile.io/api/1/project?supportedServer=TOMEE&amp;amp;groupId=com.acme&amp;amp;artifactId=customer-service&amp;amp;selectedSpecs=CONFIG&amp;amp;selectedSpecs=FAULT_TOLERANCE'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  6107  100  6107    0     0  17580      0 --:--:-- --:--:-- --:--:-- 17548
curl: Saved to filename 'customer-service.zip'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this post, we’ve seen how we can easily utilize the MicroProfile Starter REST interface to easily create projects.&lt;/p&gt;

&lt;p&gt;Happy MicroProfiling !&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@athulca?utm_source=medium&amp;amp;utm_medium=referral"&gt;Athul Cyriac Ajay&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>microprofile</category>
    </item>
    <item>
      <title>Creating a MongoDB Capped Collection In Java</title>
      <dc:creator>Davey</dc:creator>
      <pubDate>Tue, 13 Jul 2021 21:02:53 +0000</pubDate>
      <link>https://dev.to/davey/creating-a-mongodb-capped-collection-in-java-2df5</link>
      <guid>https://dev.to/davey/creating-a-mongodb-capped-collection-in-java-2df5</guid>
      <description>&lt;p&gt;In MongoDB, it’s possible to preserve the insertion order of documents into a collection in a circular fashion.  These types of collections are called Capped Collections in MongoDB.  The MongoDB documentation describes Capped Collections:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Capped collections are fixed-size collections that support high-throughput operations that insert, retrieve, and delete documents based on insertion order. Capped collections work in a way similar to circular buffers: once a collection fills its allocated space, it makes room for new documents by overwriting the oldest documents in the collection.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;OK, so we know what a capped collection is, but how to we create one?&lt;/p&gt;

&lt;p&gt;From the MongoDB shell, we would create a capped collection using the &lt;code&gt;db.createCollection&lt;/code&gt; command:&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createCollection&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"logs"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;capped:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                             &lt;span class="nl"&gt;size:&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                             &lt;span class="nl"&gt;max:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command tells MongoDB to create a collection called “logs” with a maximum size of 4096 bytes which can hold a maximum of 5 documents. When the 6th document is added, the first document is removed form the collection ensuring that there is only ever a maximum of 5 documents in the collection. The “size” parameter is mandatory, however the “max” parameter is optional.&lt;/p&gt;

&lt;p&gt;In Java, there are two common ways to communicate with MongoDB; the MongoDB &lt;a href="https://github.com/mongodb/mongo-java-driver/wiki"&gt;Java Driver&lt;/a&gt; and with &lt;a href="https://github.com/mongodb/morphia/wiki"&gt;Morphia&lt;/a&gt; (the lightweight type-safe mapping library for mapping Java objects to/from MongoDB).&lt;/p&gt;

&lt;p&gt;First, let’s first look at using the Java Driver.&lt;/p&gt;

&lt;h2&gt;
  
  
  Java Driver
&lt;/h2&gt;

&lt;p&gt;With the Java Driver, again, we use the &lt;code&gt;db.createCollection&lt;/code&gt; command, this time passing a &lt;code&gt;BasicDBObject&lt;/code&gt; as the parameter.  This parameter has the fields “capped”, “size” and “max” which specify that the collection is capped, the maximum size of the collection in bytes and the maximum number of entries in the collection.  The following code snippet shows how to connect to a local instance of MongoDB and create a capped collection.&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;MongoClient&lt;/span&gt; &lt;span class="n"&gt;mongoClient&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;MongoClient&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;MongoClientURI&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"mongodb://localhost"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="no"&gt;DB&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mongoClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDB&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;DBCollection&lt;/span&gt; &lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;collectionExists&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cappedLogsJavaDriver"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;BasicDBObject&lt;/span&gt; &lt;span class="n"&gt;options&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;BasicDBObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"capped"&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;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"size"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"max"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;collection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createCollection&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cappedLogsJavaDriver"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;collection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCollection&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cappedLogsJavaDriver"&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;Once we’ve created a collection, we can insert documents into it to ensure that it is working as expected. The following code snippet shows how to insert 8 documents into the collection (remember, only the last 5 of these will be stored as it’s a capped collection).&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="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;BasicDBObject&lt;/span&gt; &lt;span class="n"&gt;logEntry&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;BasicDBObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"logId"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;insert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logEntry&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;Using the MongoDB interactive shell, we can verify the documents that are now stored in the collection are as expected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;db.cappedLogsJavaDriver.find()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ObjectId(&lt;/span&gt;&lt;span class="s2"&gt;"54a1ca44a82617da4f72e025"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"logId"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ObjectId(&lt;/span&gt;&lt;span class="s2"&gt;"54a1ca44a82617da4f72e026"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"logId"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ObjectId(&lt;/span&gt;&lt;span class="s2"&gt;"54a1ca44a82617da4f72e027"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"logId"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ObjectId(&lt;/span&gt;&lt;span class="s2"&gt;"54a1ca44a82617da4f72e028"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"logId"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ObjectId(&lt;/span&gt;&lt;span class="s2"&gt;"54a1ca44a82617da4f72e029"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"logId"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Morphia
&lt;/h2&gt;

&lt;p&gt;Now that we’ve seen how to create a collection via the Java Driver, let’s see how we can accomplish the same thing by using Morphia.&lt;/p&gt;

&lt;p&gt;The essence of Morphia is to map Java classes to/from MongoDB. Classes that we wish to persist in MongoDB are annotated with the &lt;code&gt;@Entity&lt;/code&gt; annotation, which are then stored within a collection usually named after the class being annotated. To create a capped collection, we must add additional values onto the &lt;code&gt;@Entity&lt;/code&gt; annotation to specify the maximum number of entries in the collection and the size of the collection. Modelling the same type of object as used in the example for the Java Driver, we would create a LogEntry class as follows:&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;@Entity&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="s"&gt;"cappedLogsMorphia"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nd"&gt;@CappedAt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&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="mi"&gt;4096&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LogEntry&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;logId&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Id&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;ObjectId&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;LogEntry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;logId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;logId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logId&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;getLogId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;logId&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setLogId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;logId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;logId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logId&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;We can see that this class is annotated with &lt;code&gt;@Entity&lt;/code&gt; specifying that the collection should be capped with a maximum of 5 documents and a size of 4096 bytes.&lt;/p&gt;

&lt;p&gt;With Morphia, the capped collection is created at start-up time by invoking the &lt;code&gt;.ensureCaps()&lt;/code&gt; method on the Morphia &lt;code&gt;Datastore&lt;/code&gt; as shown below.&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;MongoClient&lt;/span&gt; &lt;span class="n"&gt;mongoClient&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;MongoClient&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;MongoClientURI&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"mongodb://localhost"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="no"&gt;DB&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mongoClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDB&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;Morphia&lt;/span&gt; &lt;span class="n"&gt;morphia&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;Morphia&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;morphia&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;LogEntry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;Datastore&lt;/span&gt; &lt;span class="n"&gt;datastore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;morphia&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createDatastore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mongoClient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;datastore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ensureCaps&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, as before, we can insert 8 documents into the collection to verify that only the last 5 are stored.&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="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;LogEntry&lt;/span&gt; &lt;span class="n"&gt;logEntry&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;LogEntry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;datastore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logEntry&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;db.cappedLogsMorphia.find()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ObjectId(&lt;/span&gt;&lt;span class="s2"&gt;"54a1ce9da82629642c64f5d9"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"className"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"com.cloudblogaas.cappedcollection.LogEntry"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"logId"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ObjectId(&lt;/span&gt;&lt;span class="s2"&gt;"54a1ce9da82629642c64f5da"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"className"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"com.cloudblogaas.cappedcollection.LogEntry"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"logId"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ObjectId(&lt;/span&gt;&lt;span class="s2"&gt;"54a1ce9da82629642c64f5db"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"className"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"com.cloudblogaas.cappedcollection.LogEntry"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"logId"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ObjectId(&lt;/span&gt;&lt;span class="s2"&gt;"54a1ce9da82629642c64f5dc"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"className"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"com.cloudblogaas.cappedcollection.LogEntry"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"logId"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ObjectId(&lt;/span&gt;&lt;span class="s2"&gt;"54a1ce9da82629642c64f5dd"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"className"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"com.cloudblogaas.cappedcollection.LogEntry"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"logId"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Checking a collection status
&lt;/h2&gt;

&lt;p&gt;Once we’ve created a capped collection in MongoDB, we can check its status by executing the &lt;code&gt;.stats()&lt;/code&gt; method on the collection from within the Mongo DB interactive shell.&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="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cappedLogsJavaDriver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stats&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;ns&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;test.cappedLogsJavaDriver&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;count&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;size&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;avgObjSize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;storageSize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;numExtents&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nindexes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lastExtentSize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;paddingFactor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;systemFlags&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userFlags&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;totalIndexSize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8176&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;indexSizes&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;_id_&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8176&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;capped&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;max&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ok&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we can see that the collection is indeed capped (“capped”=true) and that the maximum number of entries in the collection is 5 (“max”=5).&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@jontyson?utm_source=medium&amp;amp;utm_medium=referral"&gt;Jon Tyson&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>mongodb</category>
      <category>morphia</category>
    </item>
    <item>
      <title>Custom JDK Versions Per Project With SDKMAN!</title>
      <dc:creator>Davey</dc:creator>
      <pubDate>Tue, 13 Jul 2021 20:57:24 +0000</pubDate>
      <link>https://dev.to/davey/custom-jdk-versions-per-project-with-sdkman-52m4</link>
      <guid>https://dev.to/davey/custom-jdk-versions-per-project-with-sdkman-52m4</guid>
      <description>&lt;p&gt;&lt;a href="https://sdkman.io"&gt;SDKMAN!&lt;/a&gt; allows us to easily install and use different JDKs.  It can become frustrating to have to change JDK versions manually for different projects.  Fortunately, SDKMAN! has a solution to this in the form of the &lt;code&gt;sdk env&lt;/code&gt; command.  This command allows us to define a different JDK per project which can be easily switched to, without having to remember the JDK version.  Additionally, it can be configured to automatically change to the required JDK when changing directories.&lt;/p&gt;

&lt;p&gt;For more information about installing and using SDKMAN!, check out my article - &lt;a href="https://dave-s.medium.com/managing-jdk-versions-with-sdkman-bb20618c854e"&gt;Managing JDK Versions With SDKMAN!&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Updating SDKMAN!
&lt;/h2&gt;

&lt;p&gt;Before we can start using the &lt;code&gt;sdk env&lt;/code&gt; command, we must first ensure we are using the latest version of SDKMAN!  The software can be updated by using the &lt;code&gt;sdk selfupdate&lt;/code&gt; command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% sdk selfupdate
No update available at this time.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Specifying a JDK Version For A Project
&lt;/h2&gt;

&lt;p&gt;SDKMAN! uses a hidden file called &lt;code&gt;.sdkmanrc&lt;/code&gt; which contains a parameter specifying which JDK version to use for a project.  To configure and use this file is a simple 3 step process.&lt;/p&gt;

&lt;p&gt;1 &lt;strong&gt;Create the &lt;code&gt;.sdkmanrc&lt;/code&gt; file&lt;/strong&gt;.  This can easily be created by navigating to the required directory and executing &lt;code&gt;sdk env init&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;% sdk &lt;span class="nb"&gt;env &lt;/span&gt;init
.sdkmanrc created.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 &lt;strong&gt;Configure the version&lt;/strong&gt;. Once we've created the file, edit it and add a line &lt;code&gt;java=x.x.x.x&lt;/code&gt; specifying the version of Java to use.  For example to use Adopt Open JDK version 11, the file would look like:&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;cat&lt;/span&gt; .sdkman
&lt;span class="nv"&gt;java&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;11.0.2.hs-adpt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3 &lt;strong&gt;Initialize the environment&lt;/strong&gt;.  After editing the &lt;code&gt;.sdkmanrc&lt;/code&gt; fille, we can configure the environment by executing the &lt;code&gt;sdk env&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% sdk &lt;span class="nb"&gt;env

&lt;/span&gt;Using java version 11.0.2-open &lt;span class="k"&gt;in &lt;/span&gt;this shell.
%
% java &lt;span class="nt"&gt;-version&lt;/span&gt;
openjdk version &lt;span class="s2"&gt;"11.0.2"&lt;/span&gt; 2019-01-15
OpenJDK Runtime Environment 18.9 &lt;span class="o"&gt;(&lt;/span&gt;build 11.0.2+9&lt;span class="o"&gt;)&lt;/span&gt;
OpenJDK 64-Bit Server VM 18.9 &lt;span class="o"&gt;(&lt;/span&gt;build 11.0.2+9, mixed mode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Specifying a JDK Automatically
&lt;/h2&gt;

&lt;p&gt;Finally, we can get SDKMAN! to automatically change JDK to the version defined within &lt;code&gt;.sdkmanrc&lt;/code&gt; by changing configuration.  To do this, edit the &lt;code&gt;~/.sdkman/etc/config&lt;/code&gt; file and add/edit the property &lt;code&gt;sdkman_auto_env=true&lt;/code&gt;.  This will probably already exist and be set to &lt;code&gt;false&lt;/code&gt;, so make sure you edit this setting if it is there rather than duplicating it.&lt;/p&gt;

&lt;p&gt;Now, whenever you change into a directory containing a &lt;code&gt;.sdkmanrc&lt;/code&gt; file in it, the JDK will automatically be changed to your desired version.  Fantastic !&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;cd &lt;/span&gt;project1 

Using java version 11.0.2-open &lt;span class="k"&gt;in &lt;/span&gt;this shell.
%
% &lt;span class="nb"&gt;cd &lt;/span&gt;project2

Using java version 14.0.1-open &lt;span class="k"&gt;in &lt;/span&gt;this shell.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@octadan?utm_source=medium&amp;amp;utm_medium=referral"&gt;Octavian Dan&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>jdk</category>
      <category>sdkman</category>
    </item>
    <item>
      <title>Managing JDK Versions With SDKMAN!</title>
      <dc:creator>Davey</dc:creator>
      <pubDate>Thu, 08 Jul 2021 19:32:23 +0000</pubDate>
      <link>https://dev.to/davey/managing-jdk-versions-with-sdkman-4dp9</link>
      <guid>https://dev.to/davey/managing-jdk-versions-with-sdkman-4dp9</guid>
      <description>&lt;p&gt;SDKMAN! describes itself as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;a tool for managing parallel versions of multiple Software Development Kits on most Unix based systems. It provides a convenient Command Line Interface (CLI) and API for installing, switching, removing and listing Candidates.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What this means, is that it is a powerful tool that allows you to easily change between different versions of the JDK without having to modify &lt;code&gt;JAVA_HOME&lt;/code&gt; or other environment variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing SDKMAN!
&lt;/h2&gt;

&lt;p&gt;Installation is as simple as running a bash command.  For Linux and Mac users, simply execute the following command and follow the on-screen instructions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"https://get.sdkman.io"&lt;/span&gt; | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Windows users, the recommended way of installation is via WSL.  This is covered in the &lt;a href="https://sdkman.io/install"&gt;installation documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing a JDK
&lt;/h2&gt;

&lt;p&gt;After installing SDKMAN!, the next stage is to decide which JDK versions you wish to install.  SDKMAN! allows you to install different version of the JDK by different vendors.  To get a complete list of the different JDK's available, execute the &lt;code&gt;sdk list java&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% sdk list java
&lt;span class="o"&gt;================================================================================&lt;/span&gt;
Available Java Versions
&lt;span class="o"&gt;================================================================================&lt;/span&gt;
 Vendor        | Use | Version      | Dist    | Status     | Identifier
&lt;span class="nt"&gt;--------------------------------------------------------------------------------&lt;/span&gt;
 AdoptOpenJDK  |     | 14.0.1.j9    | adpt    |            | 14.0.1.j9-adpt      
               |     | 14.0.1.hs    | adpt    |            | 14.0.1.hs-adpt      
               |     | 13.0.2.j9    | adpt    |            | 13.0.2.j9-adpt      
               |     | 13.0.2.hs    | adpt    |            | 13.0.2.hs-adpt      
               |     | 12.0.2.j9    | adpt    |            | 12.0.2.j9-adpt      
               |     | 12.0.2.hs    | adpt    |            | 12.0.2.hs-adpt      
               |     | 11.0.7.j9    | adpt    |            | 11.0.7.j9-adpt      
               |     | 11.0.7.hs    | adpt    |            | 11.0.7.hs-adpt      
               |     | 8.0.252.j9   | adpt    |            | 8.0.252.j9-adpt     
               |     | 8.0.252.hs   | adpt    |            | 8.0.252.hs-adpt     
 Amazon        |     | 11.0.7       | amzn    |            | 11.0.7-amzn         
               |     | 8.0.252      | amzn    |            | 8.0.252-amzn        
               |     | 8.0.202      | amzn    |            | 8.0.202-amzn        
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will list all the different vendors and all the different JDK's available from each vendor.&lt;/p&gt;

&lt;p&gt;In the snippet above, you can see, for example, that Amazon provides (amongst others) Java version 11.0.7 and AdoptOpenJDK supports version 14.0.1 (again amongst others).&lt;/p&gt;

&lt;p&gt;To install a specific JDK, we use the &lt;code&gt;sdk install java&lt;/code&gt; command, noting the Identifier column.  This is used to uniquely specify vendor and JDK version.&lt;/p&gt;

&lt;p&gt;So, for example to install AdoptOpenJDK version 14, we would execute &lt;code&gt;sdk install java 14.0.1.hs-adpt&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;% sdk &lt;span class="nb"&gt;install &lt;/span&gt;java 14.0.1.hs-adpt 

Downloading: java 14.0.1.hs-adpt

In progress...

&lt;span class="c"&gt;#################### 100.0%&lt;/span&gt;
&lt;span class="c"&gt;#################### 100.0%&lt;/span&gt;

Repackaging Java 14.0.1.hs-adpt...

Done repackaging...
Cleaning up residual files...

Installing: java 14.0.1.hs-adpt
Done installing!

Do you want java 14.0.1.hs-adpt to be &lt;span class="nb"&gt;set &lt;/span&gt;as default? &lt;span class="o"&gt;(&lt;/span&gt;Y/n&lt;span class="o"&gt;)&lt;/span&gt;: y

Setting java 14.0.1.hs-adpt as default.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now check the Java version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; % java &lt;span class="nt"&gt;-version&lt;/span&gt;
openjdk version &lt;span class="s2"&gt;"14.0.1"&lt;/span&gt; 2020-04-14
OpenJDK Runtime Environment AdoptOpenJDK &lt;span class="o"&gt;(&lt;/span&gt;build 14.0.1+7&lt;span class="o"&gt;)&lt;/span&gt;
OpenJDK 64-Bit Server VM AdoptOpenJDK &lt;span class="o"&gt;(&lt;/span&gt;build 14.0.1+7, mixed mode, sharing&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we selected to install this version of Java as the default.  What if we just want to specify a different version of the JDK to use rather than installing a version?&lt;/p&gt;

&lt;h2&gt;
  
  
  Changing JDK Version
&lt;/h2&gt;

&lt;p&gt;To use a specific JDK version, you must first install it as shown in the previous section.  Then, simply execute the &lt;code&gt;sdk use java ...&lt;/code&gt; command to change the current shell to be a specific version.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% sdk use java 11.0.7.hs-adpt

Using java version 11.0.7.hs-adpt &lt;span class="k"&gt;in &lt;/span&gt;this shell.
david@Davids-MacBook-Air ~ % java &lt;span class="nt"&gt;-version&lt;/span&gt;
openjdk version &lt;span class="s2"&gt;"11.0.7"&lt;/span&gt; 2020-04-14
OpenJDK Runtime Environment AdoptOpenJDK &lt;span class="o"&gt;(&lt;/span&gt;build 11.0.7+10&lt;span class="o"&gt;)&lt;/span&gt;
OpenJDK 64-Bit Server VM AdoptOpenJDK &lt;span class="o"&gt;(&lt;/span&gt;build 11.0.7+10, mixed mode&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we want to permanently change the JDK version, we can use the &lt;code&gt;sdk default java ...&lt;/code&gt; command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% sdk default java 11.0.7.hs-adpt

Default java version &lt;span class="nb"&gt;set &lt;/span&gt;to 11.0.7.hs-adpt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when we open a new shell or terminal, the default JDK will have changed to the one we just specified.  We can use the &lt;code&gt;sdk current java&lt;/code&gt; command to display the currently selected JDK version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Its not Just Java though!
&lt;/h2&gt;

&lt;p&gt;Throughout this article, we've made reference to specifying different versions of the Java JDK.  SDKMAN! is much more than a tool to change Java versions - it can do the same job for different SDK's and tools, for example, Apache Ant, Maven or Spring Boot.&lt;/p&gt;

&lt;p&gt;To get a full list of managed SDKs, execute &lt;code&gt;sdk list&lt;/code&gt;, or visit the prioject &lt;a href="https://sdkman.io/sdks"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;In this article, we've seen how to install SDKMAN! and how to install and select different JDK versions.  This is only one way of defining different JDKs, but its very powerful and very simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@tomhermans?utm_source=medium&amp;amp;utm_medium=referral"&gt;Tom Hermans&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>sdk</category>
      <category>jdk</category>
    </item>
    <item>
      <title>Accessing Multiple Databases From a Spring Boot Application</title>
      <dc:creator>Davey</dc:creator>
      <pubDate>Thu, 08 Jul 2021 19:13:38 +0000</pubDate>
      <link>https://dev.to/davey/accessing-multiple-databases-from-a-spring-boot-application-1293</link>
      <guid>https://dev.to/davey/accessing-multiple-databases-from-a-spring-boot-application-1293</guid>
      <description>&lt;p&gt;When developing any application, it’s quite common to have to access multiple databases. Out of the box, Spring Boot provides easy access to a single datasource, in the simplest case just by specifying the JDBC driver on the class path!&lt;/p&gt;

&lt;p&gt;Accessing multiple databases however, is still straightforward with Spring Boot. This article shows how to connect to two different MySql datasources from a Spring Boot application.&lt;/p&gt;

&lt;p&gt;To showcase how to connect to to different databases, consider a products database and a customer database, with the following simplistic schema and data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database One - Products Database
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Schema
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;PRODUCT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Data
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;PRODUCT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;values&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;XBox&lt;/span&gt;&lt;span class="s1"&gt;');
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Database Two - Customer Database
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Schema
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;CUSTOMER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Data
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;CUSTOMER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;values&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Daphne Jefferson’);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To access the databases, we need to declare a &lt;code&gt;JdbcTemplate&lt;/code&gt; for each database. In Spring, JdbcTemplates are created from a &lt;code&gt;DataSource&lt;/code&gt; which has a set of connection properties (url, username, password etc.)&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;DataSourceConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="nc"&gt;Bean&lt;/span&gt;
  &lt;span class="nd"&gt;@Qualifier&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"customerDataSource"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nd"&gt;@Primary&lt;/span&gt;
  &lt;span class="nd"&gt;@ConfigurationProperties&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"customer.datasource"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nc"&gt;DataSource&lt;/span&gt; &lt;span class="nf"&gt;customerDataSource&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;DataSourceBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&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="nd"&gt;@Qualifier&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"productDataSource"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nd"&gt;@ConfigurationProperties&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"product.datasource"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nc"&gt;DataSource&lt;/span&gt; &lt;span class="nf"&gt;productDataSource&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;DataSourceBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&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="nd"&gt;@Qualifier&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"customerJdbcTemplate"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nc"&gt;JdbcTemplate&lt;/span&gt; &lt;span class="nf"&gt;customerJdbcTemplate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Qualifier&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"customerDataSource"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nc"&gt;DataSource&lt;/span&gt; &lt;span class="n"&gt;customerDataSource&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;JdbcTemplate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customerDataSource&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="nd"&gt;@Qualifier&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"productJdbcTemplate"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nc"&gt;JdbcTemplate&lt;/span&gt; &lt;span class="nf"&gt;productJdbcTemplate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Qualifier&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"productDataSource"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nc"&gt;DataSource&lt;/span&gt; &lt;span class="n"&gt;productDataSource&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;JdbcTemplate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;productDataSource&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;In the above code we can see that a &lt;code&gt;@Configuration&lt;/code&gt; bean has been declared that defines a &lt;code&gt;customerDatasource&lt;/code&gt; and a &lt;code&gt;customerJdbcTemplate&lt;/code&gt;. Each of these beans are annotated with the &lt;code&gt;@Qualifier('customer...')&lt;/code&gt; to identify them as relating to the customer database.&lt;/p&gt;

&lt;p&gt;Similarly, the above code defines a &lt;code&gt;productDataSource&lt;/code&gt; and a &lt;code&gt;productJdbcTemplate&lt;/code&gt;. Again these are annotated with &lt;code&gt;@Qualifier('product...')&lt;/code&gt; to identify them as relating to the product database.&lt;/p&gt;

&lt;p&gt;Finally, each &lt;code&gt;DataSource&lt;/code&gt; Bean is annotated with the &lt;code&gt;@ConfigurationProperties(prefix="...datasource")&lt;/code&gt; annotation. This tells Spring Boot what properties within the &lt;code&gt;application.properties&lt;/code&gt; file should be used for connecting to each database. The &lt;code&gt;application.properties&lt;/code&gt; file therefore looks like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;product.datasource.url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;jdbc:mysql://localhost:3306/dbOne&lt;/span&gt;
&lt;span class="py"&gt;product.datasource.username&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;user1&lt;/span&gt;
&lt;span class="py"&gt;product.datasource.password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;password&lt;/span&gt;
&lt;span class="py"&gt;product.datasource.driverClassName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;com.mysql.jdbc.Driver&lt;/span&gt;

&lt;span class="py"&gt;customer.datasource.url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;jdbc:mysql://localhost:3306/dbTwo&lt;/span&gt;
&lt;span class="py"&gt;customer.datasource.username&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;user2&lt;/span&gt;
&lt;span class="py"&gt;customer.datasource.password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;password&lt;/span&gt;
&lt;span class="py"&gt;customer.datasource.driverClassName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;com.mysql.jdbc.Driver&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we've seen how to create a &lt;code&gt;DataSource&lt;/code&gt; and &lt;code&gt;JdbcTemplate&lt;/code&gt;, the &lt;code&gt;JdbcTemplate&lt;/code&gt; can be injected into a &lt;code&gt;@Repository&lt;/code&gt; for use, e.g.&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;@Repository&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;CustomerRepository&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;SELECT_SQL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"select NAME from CUSTOMER where ID=?"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 
  &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
  &lt;span class="nd"&gt;@Qualifier&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"customerJdbcTemplate"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nc"&gt;JdbcTemplate&lt;/span&gt; &lt;span class="n"&gt;customerJdbcTemplate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getCustomerName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;customerJdbcTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;queryForObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;SELECT_SQL&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;Object&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;},&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;name&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;Again, note the use of the &lt;code&gt;@Qualifier&lt;/code&gt; annotation to specify which &lt;code&gt;JdbcTemplate&lt;/code&gt; is required for the different repositories.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ProductRepository&lt;/code&gt; is similarly written to access the &lt;code&gt;productJdbcTemplate&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="nd"&gt;@Repository&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;ProductRepository&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;SELECT_SQL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"select NAME from PRODUCT where ID=?"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 
  &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
  &lt;span class="nd"&gt;@Qualifier&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"productJdbcTemplate"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nc"&gt;JdbcTemplate&lt;/span&gt; &lt;span class="n"&gt;productJdbcTemplate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getProductName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;productJdbcTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;queryForObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;SELECT_SQL&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;Object&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;},&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;name&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 few simple steps, Spring Boot allows us to easily connect to multiple databases when using JdbcTemplates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@jankolar?utm_source=medium&amp;amp;utm_medium=referral"&gt;Jan Antonin Kolar&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>database</category>
    </item>
    <item>
      <title>Debugging SpringBoot Application In IntelliJ Idea CE</title>
      <dc:creator>Davey</dc:creator>
      <pubDate>Thu, 08 Jul 2021 18:58:17 +0000</pubDate>
      <link>https://dev.to/davey/debugging-springboot-application-in-intellij-idea-ce-22j9</link>
      <guid>https://dev.to/davey/debugging-springboot-application-in-intellij-idea-ce-22j9</guid>
      <description>&lt;p&gt;When debugging a SpringBoot application in IntelliJ Idea Community Edition, additional steps need to be taken.&lt;/p&gt;

&lt;p&gt;If you have defined your run configuration as &lt;code&gt;spring-boot:run&lt;/code&gt;, you will find that the application runs, but does not stop at breakpoints as expected.&lt;/p&gt;

&lt;p&gt;An easy way to resolve this is to set the &lt;code&gt;spring-boot.run.fork&lt;/code&gt; property to &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This can be set wither within the &lt;code&gt;pom.xml&lt;/code&gt; file, or within the run configuration. To set the run configuration, set the "Command line:" within the Run Configuration to be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring-boot:run -Dspring-boot.run.fork=false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default value of this property is &lt;code&gt;true&lt;/code&gt;, which is usually the best setting, but not when debugging from IntelliJ Idea CE. If the application is forked, then the relevant JVM properties are not passed on to the forked process and debugging does not work as expected.&lt;/p&gt;

&lt;p&gt;Changing the value of this property all the time can cause problems with Spring Boot DevTools, so its only recommended to set at runtime and not in the &lt;code&gt;pom.xml&lt;/code&gt; file where it will be used every time the application is started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@zanilic?utm_source=medium&amp;amp;utm_medium=referral"&gt;Zan&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>intellij</category>
      <category>springboot</category>
    </item>
  </channel>
</rss>
