<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.0">Jekyll</generator><link href="https://matbooth.co.uk/blog/feeds/all.xml" rel="self" type="application/atom+xml" /><link href="https://matbooth.co.uk/" rel="alternate" type="text/html" /><updated>2026-07-14T12:11:07+01:00</updated><id>https://matbooth.co.uk/blog/feeds/all.xml</id><title type="html">Mat Booth</title><subtitle>Mat Booth is a software engineer providing support, consulting and implementation services for Eclipse plug-ins, Eclipse RCP applications and OSGi-based products.</subtitle><author><name>Mat Booth</name><email>&amp;#x69;&amp;#x6e;&amp;#x66;&amp;#x6f;&amp;#x40;&amp;#x6d;&amp;#x61;&amp;#x74;&amp;#x62;&amp;#x6f;&amp;#x6f;&amp;#x74;&amp;#x68;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#x2e;&amp;#x75;&amp;#x6b;</email></author><entry><title type="html">My Fedora Server is a Spotify Connect Device</title><link href="https://matbooth.co.uk/2025/12/04/fedora-server-spotify-connect.html" rel="alternate" type="text/html" title="My Fedora Server is a Spotify Connect Device" /><published>2025-12-04T15:30:00+00:00</published><updated>2025-12-04T15:30:00+00:00</updated><id>https://matbooth.co.uk/2025/12/04/fedora-server-spotify-connect</id><content type="html" xml:base="https://matbooth.co.uk/2025/12/04/fedora-server-spotify-connect.html"><![CDATA[<p>This article explores how to turn Fedora machines into Spotify Connect devices.</p>

<h2 id="what-is-spotify-connect">What is Spotify Connect?</h2>

<p>Spotify Connect is a protocol and means by which one device can remotely control playback on another device over your home network or wifi.</p>

<p>If you have a device that supports Spotify Connect then no longer are you limited to listening to Spotify on your phone or computer – you can instead use your phone or computer to control music playback on your Spotify Connect compatible smart speaker, TV sound bar, car stereo, etc.</p>

<p>You can see what Spotify Connect devices are available on your network by hitting the <img src="/assets/images/spotify_connect_button.png" alt="connect to a device" style="height: 1.5rem" /> button in an official Spotify client. It will show a list of devices on which you can play music remotely:</p>

<video autoplay="" loop="" muted="" controls="">
  <source src="/assets/video/spotify_connect_device_list.webm" type="video/webm" />
</video>

<p>My problem is that I don’t have a smart speaker or other Spotify Connect compatible device here in my office capable of driving my big floor standing speakers. What I <strong>do</strong> have however, is an old stereo amplifier with spare inputs in the same rack as my server equipment:</p>

<p><img src="/assets/images/spotify_server_amp.jpg" alt="Server rack with amplifier and speakers." /></p>

<p>The server machine in the bottom of that rack happens to have an integrated USB audio adapter so why not connect that to the AUX-in on the amplifier and teach the server how to stream music from Spotify?</p>

<h2 id="installing-spotifyd">Installing Spotifyd</h2>

<p><strong><a href="https://github.com/Spotifyd/spotifyd">Spotifyd</a></strong> is an open source Spotify client that you can run as a daemon and also supports the Spotify Connect protocol, which makes it show up as a device that can be controlled from the official Spotify client.</p>

<p>An RPM packaged version of <strong>Spotifyd</strong> can be found in my COPR repo at <a href="https://copr.fedorainfracloud.org/coprs/mbooth/spotifyd/">mbooth/spotifyd</a>. It’s straightforward to enable the COPR repo and install it:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># dnf copr enable mbooth/spotifyd
# dnf install spotifyd
</code></pre></div></div>

<p><strong>Spotifyd</strong> uses the Avahi mDNS for service discovery, which allows the official Spotify clients to find it on your network. So we need to make sure the mDNS port is open, as well as the port used by the Spotify Connect protocol. On a default installation of Fedora Server, it may be necessary to open both ports using the <code class="language-plaintext highlighter-rouge">firewall-cmd</code> command like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># firewall-cmd --permanent --add-service=mdns
# firewall-cmd --permanent --add-service=spotify-connect
# systemctl reload firewalld
</code></pre></div></div>

<p>Finally, enable and start the <strong>Spotifyd</strong> service in the normal systemd way:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># systemctl enable spotifyd.service
# systemctl start spotifyd.service
</code></pre></div></div>

<p>The server will now show up in official Spotify clients as a device named “spotifyd.” Choosing it from the list will begin playback on that device:</p>

<video autoplay="" loop="" muted="" controls="">
  <source src="/assets/video/spotify_connect_device_select.webm" type="video/webm" />
</video>

<p>If you want to run <strong>Spotifyd</strong> on a Fedora Workstation install, or any setup where you have user sessions with the audio being managed by Wireplumber/Pipewire, then you will need to start it as a user service instead:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ systemctl --user enable spotifyd.service
$ systemctl --user start spotifyd.service
</code></pre></div></div>

<h2 id="configuration">Configuration</h2>

<p>The configuration file for <strong>Spotifyd</strong> can be found at <code class="language-plaintext highlighter-rouge">/etc/spotifyd.conf</code> where the first thing you probably want to do is customise the name that shows in the device list:</p>

<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="py">device_name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s">"Mat's Office"</span>
</code></pre></div></div>

<p>All the configuration options are explained further in the <a href="https://docs.spotifyd.rs/Introduction.html">upstream documentation</a>.</p>

<h2 id="reporting-issues">Reporting Issues</h2>

<p>For issues directly relating to the RPM packaging of <strong>Spotifyd</strong> or installation from my COPR repo, please file bugs at <a href="https://github.com/mbooth101/spotifyd-rpm/issues">github.com/mbooth101/spotifyd-rpm/issues</a>.</p>]]></content><author><name>Mat Booth</name><email>&amp;#x69;&amp;#x6e;&amp;#x66;&amp;#x6f;&amp;#x40;&amp;#x6d;&amp;#x61;&amp;#x74;&amp;#x62;&amp;#x6f;&amp;#x6f;&amp;#x74;&amp;#x68;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#x2e;&amp;#x75;&amp;#x6b;</email></author><category term="linux" /><category term="audio" /><summary type="html"><![CDATA[This article explores how to turn Fedora machines into Spotify Connect devices.]]></summary></entry><entry><title type="html">Configuring Vim Solarized to Follow the System Dark Mode Preference</title><link href="https://matbooth.co.uk/2025/09/16/vim-solarized-follow-system-preference.html" rel="alternate" type="text/html" title="Configuring Vim Solarized to Follow the System Dark Mode Preference" /><published>2025-09-16T11:00:00+01:00</published><updated>2025-09-16T11:00:00+01:00</updated><id>https://matbooth.co.uk/2025/09/16/vim-solarized-follow-system-preference</id><content type="html" xml:base="https://matbooth.co.uk/2025/09/16/vim-solarized-follow-system-preference.html"><![CDATA[<p>I like to switch my system between light and dark modes as lighting conditions change, and I want my terminal windows to always respect my current system preference. This article shows how to configure vim to automatically change between light and dark variants of the Solarized colour scheme, to match the current system dark mode preference.</p>

<video width="100%" autoplay="" loop="" muted="" controls="">
  <source src="/assets/video/vim_working.webm" type="video/webm" />
</video>

<p>I usually go years and years between OS re-installs, so I’ve forgotten how to do this. Hopefully this article will be useful for future me. The first thing to do after installing Fedora on a new machine however, is to switch the default editor back to vim, because I have no muscle memory for nano and I refuse to change. 😅</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ sudo dnf swap nano-default-editor vim-default-editor
</code></pre></div></div>

<p>Now onto the main business of configuring the terminal and vim to use my favourite colour palette, <a href="https://ethanschoonover.com/solarized/">Solarized by Ethan Schoonover</a>.</p>

<h2 id="solarize-the-terminal">Solarize The Terminal</h2>

<p>Ptyxis, the new default terminal in Fedora Workstation Edition, has an excellent set of colour palette options. From the hamburger menu drop-down, select the <strong>Follow System Style</strong> button from the three options at the top. This causes Ptyxis to switch between light and dark modes when you change the system dark mode preference instead of being in dark mode all the time. Then open the <strong>Preferences</strong> dialog to select the Solarized colour palette from the options listed there:</p>

<p><img src="/assets/images/vim_terminal_prefs.png" alt="Screenshot of terminal preferences dialog." /></p>

<h2 id="solarize-vim">Solarize Vim</h2>

<p>This works well for normal terminal operation, but vim’s own default colours can clash terribly with the terminal colour scheme. Sometimes the foreground and background colours are either the same or extremely low contrast, which results in impossible to read text, as shown here after performing a search for the string “init”:</p>

<p><img src="/assets/images/vim_bad_colours.png" alt="Screenshot of search result highlights in vim making text unreadable." /></p>

<p>Fortunately Ethan provides a vim-specific implementation of the Solarized colour palette in his <a href="https://github.com/altercation/vim-colors-solarized">vim-colors-solarized</a> repository. This can be installed by <a href="https://raw.githubusercontent.com/altercation/vim-colors-solarized/refs/heads/master/colors/solarized.vim">downloading the provided vim script</a> into your <code class="language-plaintext highlighter-rouge">.vim/colors</code> directory:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ mkdir -p ~/.vim/colors
$ wget https://raw.githubusercontent.com/altercation/vim-colors-solarized/refs/heads/master/colors/solarized.vim \
    -o ~/.vim/colors/solarized.vim
</code></pre></div></div>

<p>And then configuring the colour scheme in your <code class="language-plaintext highlighter-rouge">.vimrc</code> file by adding the following lines:</p>

<div class="language-vim highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">" Enable Solarized Theme</span>
<span class="nb">syntax</span> enable
<span class="k">colorscheme</span> solarized
</code></pre></div></div>

<p>New vim sessions will now use the correct colours, and are even able to detect whether to use the light or dark variant of Solarized.</p>

<h2 id="dark-mode-detection">Dark Mode Detection</h2>

<p>However, vim is <strong><em>only</em></strong> able to detect whether to use the light or dark variant <strong><em>at start up.</em></strong> This means if I switch the system dark mode preference while vim is open, then I have to close and reopen all my open vim sessions before they will use the correct Solarized variant:</p>

<video width="100%" autoplay="" loop="" muted="" controls="">
  <source src="/assets/video/vim_not_working.webm" type="video/webm" />
</video>

<p>Not even re-sourcing the <code class="language-plaintext highlighter-rouge">.vimrc</code> using the <code class="language-plaintext highlighter-rouge">:so</code> command corrects the colours. We can however edit it such that re-sourcing <em>does</em> fix the colour scheme variant in use without needing to exit and reload vim.</p>

<div class="language-vim highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">" Enable Solarized Theme</span>
<span class="nb">syntax</span> enable
<span class="k">let</span> sys_colors<span class="p">=</span><span class="nb">system</span><span class="p">(</span><span class="s1">'gsettings get org.gnome.desktop.interface color-scheme'</span><span class="p">)</span>
<span class="k">if</span> sys_colors <span class="p">=~</span> <span class="s1">'dark'</span>
    <span class="k">set</span> <span class="nb">background</span><span class="p">=</span><span class="nb">dark</span>
<span class="k">else</span>
    <span class="k">set</span> <span class="nb">background</span><span class="p">=</span><span class="nb">light</span>
<span class="k">endif</span>
<span class="k">colorscheme</span> solarized
</code></pre></div></div>

<p>Expanding upon the previous <code class="language-plaintext highlighter-rouge">.vimrc</code> snippet, this explicitly sets vim’s <code class="language-plaintext highlighter-rouge">background</code> setting depending on the output of a <code class="language-plaintext highlighter-rouge">gsettings</code> query for the current system dark mode preference. Now the <code class="language-plaintext highlighter-rouge">:so ~/.vimrc</code> command can be used to fix the colours without having to close and reopen vim.</p>

<h2 id="vimterprocess-communication">Vimterprocess Communication</h2>

<p>It would be even better of course, to have vim automatically re-source the <code class="language-plaintext highlighter-rouge">.vimrc</code> automatically when the system dark mode preference changes.</p>

<p>Vim has a kind of interprocess communication mechanism built in. If it’s started with the <code class="language-plaintext highlighter-rouge">--servername {NAME}</code> option then vim can accept commands from another vim processes running on your machine. To ensure vim is always started with this option, just add this line to your <code class="language-plaintext highlighter-rouge">.bashrc</code> file to create a command alias:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Always start vim as a server</span>
<span class="c"># with a unique name</span>
<span class="nb">alias </span><span class="nv">vi</span><span class="o">=</span><span class="s1">'vi --servername VIM-$(date +%s)'</span>
</code></pre></div></div>

<p>Now when you run vim (or vi) the session will be named with <code class="language-plaintext highlighter-rouge">VIM-&lt;SOME_NUMBER&gt;</code>. Commands can be sent to such named sessions using a specially crafted invocation of vim:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ vim --servername VIM-&lt;SOME_NUMBER&gt; --remote-send ":so ~/.vimrc&lt;CR&gt;"
</code></pre></div></div>

<p>So all we need to do is write a small shell script to find all running vim processes, determine their session names, and execute the above command for each one. Create the script in your user’s local bin directory, e.g. <code class="language-plaintext highlighter-rouge">~/.local/bin/vsignal.sh</code> and make it executable with <code class="language-plaintext highlighter-rouge">chmod +x ~/.local/bin/vsignal.sh</code>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>

<span class="k">function </span>signal_vim<span class="o">()</span> <span class="o">{</span>
	<span class="c"># Signal all running instances of vim</span>
	<span class="nv">PIDS</span><span class="o">=</span><span class="si">$(</span>pgrep <span class="nt">-u</span> <span class="nv">$USER</span> vim<span class="si">)</span>
	<span class="k">for </span>PID <span class="k">in</span> <span class="nv">$PIDS</span> <span class="p">;</span> <span class="k">do
		</span><span class="nv">VIM_ID</span><span class="o">=</span><span class="si">$(</span>ps <span class="nt">--no-headers</span> <span class="nt">-p</span> <span class="nv">$PID</span> <span class="nt">-o</span> args | <span class="nb">cut</span> <span class="nt">-d</span><span class="s1">' '</span> <span class="nt">-f3</span><span class="si">)</span>
		vim <span class="nt">--servername</span> <span class="nv">$VIM_ID</span> <span class="nt">--remote-send</span> <span class="s2">":so ~/.vimrc&lt;CR&gt;"</span>
	<span class="k">done</span>
<span class="o">}</span>

<span class="c"># Wait for color-scheme change</span>
gsettings monitor org.gnome.desktop.interface color-scheme | <span class="se">\</span>
<span class="k">while </span><span class="nb">read</span> <span class="nt">-r</span> COLOR_SCHEME <span class="p">;</span> <span class="k">do
	</span>signal_vim
<span class="k">done</span>
</code></pre></div></div>

<p>Piping the <code class="language-plaintext highlighter-rouge">gsettings monitor</code> command into <code class="language-plaintext highlighter-rouge">read</code> will cause the script to block until the system dark mode preference is changed. When it does, it will issue a call to the <code class="language-plaintext highlighter-rouge">signal_vim</code> function, perform the magic, and then go back to blocking. Now while ever the <code class="language-plaintext highlighter-rouge">vsignal.sh</code> script is running, all active vim sessions will immediately switch to the appropriate Solarized colour scheme variant when the system dark mode preference is changed.</p>

<h2 id="a-systemd-theme-sync-service">A Systemd Theme Sync Service</h2>

<p>It’s a bit incovenient to have to start a script whenever you open a terminal though. The best way to have this script always running is by letting systemd handle it. A new, user-specific service can be created with the following command:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ systemctl edit --user --force --full theme-sync.service
</code></pre></div></div>

<p>The following service definition will cause systemd to start the script when you log into your Gnome session:</p>

<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">[Unit]</span><span class="w">
</span><span class="py">Description</span><span class="p">=</span><span class="s">Dark Mode Sync Service</span>
<span class="w">
</span><span class="nn">[Service]</span><span class="w">
</span><span class="py">ExecStart</span><span class="p">=</span><span class="s">%h/.local/bin/vsignal.sh</span>
<span class="w">
</span><span class="nn">[Install]</span><span class="w">
</span><span class="py">WantedBy</span><span class="p">=</span><span class="s">gnome-session.target</span>
</code></pre></div></div>

<p>And finally, enable and start the service with the following commands:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ systemctl --user enable theme-sync.service
$ systemctl --user start theme-sync.service
</code></pre></div></div>

<p>Now we can switch between light and dark modes to our heart’s content, safe in the knowledge that vim will follow suite. 😌</p>

<video width="100%" autoplay="" loop="" muted="" controls="">
  <source src="/assets/video/vim_working.webm" type="video/webm" />
</video>]]></content><author><name>Mat Booth</name><email>&amp;#x69;&amp;#x6e;&amp;#x66;&amp;#x6f;&amp;#x40;&amp;#x6d;&amp;#x61;&amp;#x74;&amp;#x62;&amp;#x6f;&amp;#x6f;&amp;#x74;&amp;#x68;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#x2e;&amp;#x75;&amp;#x6b;</email></author><category term="linux" /><category term="bash" /><summary type="html"><![CDATA[I like to switch my system between light and dark modes as lighting conditions change, and I want my terminal windows to always respect my current system preference. This article shows how to configure vim to automatically change between light and dark variants of the Solarized colour scheme, to match the current system dark mode preference.]]></summary></entry><entry><title type="html">Project Lockdown Aviary Build</title><link href="https://matbooth.co.uk/2020/09/03/project-lockdown-aviary-build.html" rel="alternate" type="text/html" title="Project Lockdown Aviary Build" /><published>2020-09-03T12:00:00+01:00</published><updated>2020-09-03T12:00:00+01:00</updated><id>https://matbooth.co.uk/2020/09/03/project-lockdown-aviary-build</id><content type="html" xml:base="https://matbooth.co.uk/2020/09/03/project-lockdown-aviary-build.html"><![CDATA[<p>The country is in lockdown, I’m on PTO, my vacation was cancelled and I can’t leave the house. However, the weather is glorious, I can be in the garden, the postie is still working and Amazon is delivering. It was the only sensible thing I could do. I bought a welder and built some stuff.</p>

<h1 id="the-plan">The Plan</h1>

<p>Since we moved into this house the big birdies have been living in the back room, which has a South-facing French door that opens onto the patio. It’s lovely, but the large amount of glass and the flat roof of the extension means it gets extremely hot in this room in the summer time and we can’t open the door without locking the birds away. It means we have to choose between the birds’ freedom to roam the house and our own comfort.</p>

<p><a href="/assets/images/diy/15-french-doors.jpg"><img src="/assets/images/diy/15-french-doors_small.jpg" alt="Wistful longing for an outdoor space." /></a></p>

<p>So we had the idea of building an aviary over the French door so that we can open it and let some breeze into the house without worrying about the birds. Cancelled vacation plans mean I can bring this project forward from Q5 where it was previously scheduled. It is possible to buy pre-fabricated aviary panels of course, but in every case we found they suffered from one of two problems:</p>

<ul>
  <li><strong>Size</strong> – Most commercially available aviary panels are either 6 feet or 8 feet tall. This is problematic because the strip of wall between the top of the French door and the eaves of the roof is a height above the patio that is somewhere between those two dimensions, so the top of the aviary would either interfere with the doors opening or intersect with the eaves. It’s possible to get bespoke units made, but that increases the cost, especially when you require they be made of a specific material, which is the other problem:</li>
  <li><strong>Material</strong> – The majority of aviary panels commercially available are either wood-framed or zinc-galvanised. This wouldn’t matter at all if you were keeping chickens for example, but both of these materials are a problem for keeping parrots and other hook-bills. Parrots are prodigious chewers, which is vital for the maintenance of their beaks but anything made from wood has a short life-span in our house. Galvanised metals are a problem because parrots are also prodigious climbers and they use their beaks as a third hand. Just from climbing about in galvanised cages parrots can ingest a lot of zinc, which is quite toxic. It’s why you should never make a BBQ out of metal fencing mesh – it’s almost always zinc-galvanised and you <strong>will</strong> get heavy metal poisoning.</li>
</ul>

<p>Instead of paying for bespoke panels, obviously it would be way more fun to learn how to weld and fabricate my own. 😀</p>

<p>The two most ideal choices for material are aluminium or stainless steel. Either of these should survive outside corrosion-free, maintenance-free and be both safe and secure for the birdies. Reading online I learned that for various reasons, welding aluminium is a much more dificult process than welding steel. The thermal and electrical properties of steel make it a surprisingly forgiving material to work with, which is why most novice welders begin there.</p>

<p>So even though the raw material is roughly twice as expensive as aluminium I decided that I stood a much better chance of success by constructing the aviary from stainless steel. I ordered some sheets of 8 feet by 4 feet sheets of stainless weld-mesh, with wire spacing close to that of our existing bird cages, from <a href="https://www.fhbrundle.co.uk/">a supplier in Ilkeston</a> and found a great deal on some 3 metre lengths of stainless box section from <a href="https://steelstockholders-sheffield.co.uk/">a local supplier here in Sheffield</a>. I had great experiences with both these suppliers and would definitely use them again in the future.</p>

<p><img src="/assets/images/diy/15-raw-material.jpg" alt="Living in the Steel City finally pays off." /></p>

<p>I also ordered a cheap welding machine from Amazon, some PPE and a stack of consumable electrodes. I was now committed.</p>

<p><img src="/assets/images/diy/15-welder.jpg" alt="It's black and orange and named after the sound a tiger makes." /></p>

<p>The welding machine I ordered has the capability to do both <a href="https://en.wikipedia.org/wiki/Gas_tungsten_arc_welding">TIG welding</a> and <a href="https://en.wikipedia.org/wiki/Shielded_metal_arc_welding">manual arc welding</a> but since TIG has a much higher initial cost of entry due to the requirement for argon shielding gas, I decided to stick to basic manual arc welding for this project. The consumable electrodes I bought are designated <code class="language-plaintext highlighter-rouge">ER308L</code> and are suitable for welding the type 304 stainless steel I had ordered.</p>

<h2 id="phase-1---first-arcs">Phase 1 - First Arcs</h2>

<p>Time to start welding!</p>

<p>I sensibly ordered enough box section such that I could first get plenty of practice before attempting any part of the real project. Here are photographs of my very first eight arc strikes, as seen after a quick hit with a wire brush (click to view a high-res version):</p>

<p><a href="/assets/images/diy/15-first-arcs-1-and-2.jpg"><img src="/assets/images/diy/15-first-arcs-1-and-2_small.jpg" alt="A one and a two..." /></a>
<a href="/assets/images/diy/15-first-arcs-3-and-4.jpg"><img src="/assets/images/diy/15-first-arcs-3-and-4_small.jpg" alt="And a three and a four..." /></a>
<a href="/assets/images/diy/15-first-arcs-5-and-6.jpg"><img src="/assets/images/diy/15-first-arcs-5-and-6_small.jpg" alt="And heel, toe, heel, toe..." /></a>
<a href="/assets/images/diy/15-first-arcs-7-and-8.jpg"><img src="/assets/images/diy/15-first-arcs-7-and-8_small.jpg" alt="And seven and eight!" /></a></p>

<p>It’s quite obvious that I neither knew what I was doing nor knew what to expect, despite having watched <strong>several</strong> Youtube videos on the subject… 😲 I’m a big fan of my apparent complete inability to move my hands in a straight line and also the apprentice marks that can be seen in sample one where I had welded the electrode to the base metal and then dragged the arc across the surface of the piece after struggling to break it off.</p>

<h2 id="phase-2---butt-joint-practice">Phase 2 - Butt Joint Practice</h2>

<p>After a full day of just striking arcs and forming puddles, I wanted to try welding some pieces together by butting some box section together to form a tee. This is the kind of joint I want to use on the aviary panel frames. Here are the front and back sides of my first ever box section butt joints (click to view a high-res version):</p>

<p><a href="/assets/images/diy/15-first-butts.jpg"><img src="/assets/images/diy/15-first-butts_small.jpg" alt="Butts, hehe." /></a></p>

<p>You can see from sample one here that I had great difficulty in managing the heat that I’m putting into the metal – on the left I did not manage to form a puddle that joined both sides of the joint (not enough heat/moving the electrode too quickly) and on the right I ended up just blowing a hole clean through the box (too much heat/moving the electrode too slowly.) Sample two is a little better, but there is still a hole on the left that is filled with slag instead of metal.</p>

<p>I ended up spending a lot of time discovering through trial and error the right way to move and feed the electrode for this kind of joint of this kind material and by the end of day three I actually started to produce some welds that came out looking sort of not bad (click to view a high-res version):</p>

<p><a href="/assets/images/diy/15-butt-practice-back.jpg"><img src="/assets/images/diy/15-butt-practice-back_small.jpg" alt="Butts, hehe." /></a>
<a href="/assets/images/diy/15-butt-practice-front.jpg"><img src="/assets/images/diy/15-butt-practice-front_small.jpg" alt="More butts, hehe." /></a></p>

<p>The key thing I found to get these welds was that as you zig-zag across the seam to be welded, it is important for the electrode to spend much less time over the bottom end piece than the cross piece because the end piece has no support from underneath. The bottom edge of the cross piece of the tee is supported by a whole side of the box section and can therefore sink away much more heat, which means less chance of melting a hole right through the material.</p>

<p>Pretty welds they are not, but I tested the strength by welding only one side and then trying to persuade the pieces apart with a hammer; I succeeded in bending it apart at the seam only a little. The welds can easy support my body weight and it’s not for anything structural; it should be more than stong enough for what I have in mind.</p>

<p>Through experimentation I have found the beginnings of a technique and independently discovered the rule of thumb that states the machine should be set to the same number of amperes as the thickness of the electrode in thousandths of an inch. My electodes are 1.5mm, which translates to about 60 amps. I also discovered it helps a great deal if you can actually cut the metal squarely. I don’t have a metal-cutting chop-saw or band-saw so I’m just cutting the box section using an angle grinder with an abrasive cut-off disc and then squaring up the pieces on the bench grinder (or hand file where the bench grinder is impractical). Perhaps it’s obvious, but the closer the fit, the smaller the gap you have to fill.</p>

<p>Later, I started to attempt fillet welds in the inside corners of the tee, but that… Didn’t go nearly as well (click to view a high-res version):</p>

<p><a href="/assets/images/diy/15-first-fillets.jpg"><img src="/assets/images/diy/15-first-fillets_small.jpg" alt="Fillet misteaks." /></a></p>

<p>I clearly need way more practice at this; I’m not anywhere near confident enough to do fillet welds on the real panels, so for now I’ll probably do the flat welds only.</p>

<h2 id="phase-3---going-into-production">Phase 3 - Going into Production</h2>

<p>At some point you have to just draw a line in the sand and actually build something for real, so the next day I started cutting the box section to length and figuring out the clamping setup. Here you can see I am leaving some sections a bit long to make it easier to clamp together squarely at the corners of the panels. Once welded, I could flush-trim the excess off with the angle grinder.</p>

<p><a href="/assets/images/diy/15-clamping-up.jpg"><img src="/assets/images/diy/15-clamping-up_small.jpg" alt="Clamping it up." /></a></p>

<p>And once I’d welded the first frame, I could use that as a kind of template for the subsequent ones. But even with a template it was still difficult to keep things square due to the warping as each weld cooled down and the metal contracted. Even just one degree off is actually quite a long way out across nearly 2.5 metres of box section… You just can’t have too many clamps holding it place.</p>

<p>I knew I wanted the weld mesh to sit flat atop the frames so I needed to grind flat my ugly, lumpy welds. A flap-disc on the angle grinder makes short work of that (click to view a high-res version):</p>

<p><a href="/assets/images/diy/15-prod-1.jpg"><img src="/assets/images/diy/15-prod-1_small.jpg" alt="So smooth!" /></a><a href="/assets/images/diy/15-prod-2.jpg"><img src="/assets/images/diy/15-prod-2_small.jpg" alt="Pretty colours!" /></a></p>

<p>I didn’t quite grind out the deepest divets because I didn’t want to remove more material than necessary but even so, I was able to hide a <strong><em>lot</em></strong> of sins with the flap-disc. 😀</p>

<h2 id="phase-4---test-assembly">Phase 4 - Test Assembly</h2>

<p>Once I had all the side panels and roof panels of the aviary welded up, I could start thinking about assembly. I needed to drill some holes in the box section so that it can all be bolted together. This turned out to much more of a chore than I anticipated. Stainless steel is hard as nails and the drills I had were not really up to the task. I had some titanium nitride (TiN) coated high-speed steel (HSS) drills for metal but they required re-sharpening on the bench grinder after every single hole, even though the wall of the box section is only 1.5mm thick. If I did not resharpen the drills then the friction of the dull cutting edge would work-harden the steel and they would would just bind and break. I broke three drills in this way before I caved in and ordered some cobalt HSS drills designed for stainless, which cut the metal like butter in comparison to the others. I highly recommend getting cobalt drills if you have to work with stainless steel.</p>

<p>I drilled 6mm holes for M6 bolts and removed the burr by creating a slight bevel with a countersink bit:</p>

<p><img src="/assets/images/diy/15-bolt-holes.jpg" alt="Holes. For bolts." /></p>

<p>With sufficient bolt holes drilled, I could now do a dry fit of the first segment of the aviary so I could mark and drill holes in the brick-work for the mechanical fixings attaching it to the wall. The half-fabricated frame clamped to the front here is just there for spacing and to lend some rigidity for the test fit:</p>

<p><img src="/assets/images/diy/15-test-assembly.jpg" alt="Testing, testing." /></p>

<p>And it turns out I needn’t have worried too much about squareness because once I bolted the frames to the wall of the house, I discovered my patio is pretty far from level. I am as shocked as you are, but at least I know the rain water drains <em>away</em> from the wall. The side of the frame that is bolted against the wall is resting on the patio. The other side is flapping about in the breeze, a 25mm gap between the underside of the box section and the top of the patio (click to view a high-res version):</p>

<p><a href="/assets/images/diy/15-patio-gap.jpg"><img src="/assets/images/diy/15-patio-gap_small.jpg" alt="Too square for my own good." /></a></p>

<p>Luckily since the gap is approximately one box section dimension large it should not be a big deal because the next frame can be that much lower without resulting in any gap at the top.</p>

<h2 id="phase-5---welding-the-mesh">Phase 5 - Welding the Mesh</h2>

<p>Next thing to attempt is welding the mesh to the assembled frames. Prudence once again dictated that I practice on some off-cuts first, so here’s some practice welds (click to view a high-res version):</p>

<p><a href="/assets/images/diy/15-mesh-practice-1.jpg"><img src="/assets/images/diy/15-mesh-practice-1_small.jpg" alt="Making a mesh of it." /></a><a href="/assets/images/diy/15-mesh-practice-2.jpg"><img src="/assets/images/diy/15-mesh-practice-2_small.jpg" alt="Making lesh of a mesh of it." /></a></p>

<p>What I am trying to accomplish with these “tacks” is to start a puddle on the box section and then bringing the puddle over to touch the mesh wire. I must be careful to avoid putting too much heat into either the box section (and blowing a hole through it) or the mesh wire (and melting it away entirely). You can see in the above I was not quite successful in all cases, but after some practice I was able to acheive what I wanted consistently enough to start welding for real. See below for some better examples (click to view a high-res version):</p>

<p><a href="/assets/images/diy/15-prod-mesh.jpg"><img src="/assets/images/diy/15-prod-mesh_small.jpg" alt="Not making a mesh of it." /></a></p>

<p>Now only about a thousand of these left to do…</p>

<h2 id="phase-6---final-assembly-and-gate">Phase 6 - Final Assembly and Gate</h2>

<p>After fabricating and welding the mesh onto seven frames, the final frame I wanted to be a gate so that we can still get into and out of the aviary from the outside. This meant I needed to construct some kind of latch mechanism to keep it closed. For the hinge side, I just bought and attached some stainless rise-and-fall hinges, so the gate will naturally want to close itself. For the latch mechanism, I fabricated a small enclosure out of some box section and cut out the mesh where it would be placed in the gate (click to view a high-res version):</p>

<p><a href="/assets/images/diy/15-latch-front.jpg"><img src="/assets/images/diy/15-latch-front_small.jpg" alt="There's no catch." /></a><a href="/assets/images/diy/15-latch-rear.jpg"><img src="/assets/images/diy/15-latch-rear_small.jpg" alt="There's no catch yet." /></a></p>

<p>This enclosure will house the latch tongue, handle and return spring. I had to buy the spring, but the latch tongue and handle I made from some stainless steel round stock:</p>

<p><a href="/assets/images/diy/15-latch-materials.jpg"><img src="/assets/images/diy/15-latch-materials_small.jpg" alt="There's a catch to it." /></a></p>

<p>The holes you see drilled in the enclosure above holds the latch tongue captive. The spring surrounds the latch tongue and acts on the latch handle to force the tongue into a corresponding hole in the gate frame, as demonstrated below:</p>

<video controls="" width="100%">
    <source src="/assets/images/diy/15-latch-demo.webm" type="video/webm" />
</video>
<p style="font-size:0.75em"><em>Demo of the gate latch mechanism.</em></p>

<p>I tried to fix the handle to the latch tongue with a set screw, but of course this stainless steel was too much for my cheap taps and I inevitably snapped the tap mid way cutting the threads:</p>

<p><a href="/assets/images/diy/15-broken-tap.jpg"><img src="/assets/images/diy/15-broken-tap_small.jpg" alt="I tried to faucet." /></a></p>

<p>I don’t know what I expected, I almost certainly should have just used a roll pin. Never mind, I just trimmed off the pointy excess and now the tap <strong><em>is</em></strong> the set screw. 😀</p>

<p>I also needed a “door stop” to prevent the gate from being opened backwards and straining the hinges. This was easily made with a piece of stainless sheet metal salvaged from an old cooker extraction hood pop-riveted onto the frame:</p>

<p><a href="/assets/images/diy/15-gate-stop.jpg"><img src="/assets/images/diy/15-gate-stop_small.jpg" alt="Push, not pull." /></a></p>

<h1 id="epilogue">Epilogue</h1>

<p>I was right, learning to weld <strong>was</strong> a great deal more fun than just buying some custom made aviary panels. The whole project took my two full weeks of PTO working every day, plus something like the next six following weekends, so it was expensive and laborious but a great learning experience.</p>

<p>Due to assembling the aviary with the mesh welds on the <em>outside</em>, the only welds you see from the inside are ones that are ground flat which I think looks great. And the birds seem to enjoy having the extra space too:</p>

<p><a href="/assets/images/diy/15-happy-birds.jpg"><img src="/assets/images/diy/15-happy-birds_small.jpg" alt="Happy birds." /></a></p>

<p>This guy especially loves taking showers out there when it rains:</p>

<p><a href="/assets/images/diy/15-happy-birds-2.jpg"><img src="/assets/images/diy/15-happy-birds-2_small.jpg" alt="Squawking in the rain." /></a></p>

<p>In this time of crisis, I leave you with this appropriately heartwarming message that came with my welding gloves:</p>

<p><img src="/assets/images/diy/15-gloves-message.jpg" alt="Adorable." /></p>

<p><em>“The last but most important, please don’t forget to take a good rest and spend time staying with family in busy work.”</em></p>]]></content><author><name>Mat Booth</name><email>&amp;#x69;&amp;#x6e;&amp;#x66;&amp;#x6f;&amp;#x40;&amp;#x6d;&amp;#x61;&amp;#x74;&amp;#x62;&amp;#x6f;&amp;#x6f;&amp;#x74;&amp;#x68;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#x2e;&amp;#x75;&amp;#x6b;</email></author><category term="diy" /><summary type="html"><![CDATA[The country is in lockdown, I’m on PTO, my vacation was cancelled and I can’t leave the house. However, the weather is glorious, I can be in the garden, the postie is still working and Amazon is delivering. It was the only sensible thing I could do. I bought a welder and built some stuff.]]></summary></entry><entry><title type="html">Using the remote OSGi console with Equinox</title><link href="https://matbooth.co.uk/2020/04/23/remote-osgi-console-with-equinox.html" rel="alternate" type="text/html" title="Using the remote OSGi console with Equinox" /><published>2020-04-23T15:00:00+01:00</published><updated>2020-04-23T15:00:00+01:00</updated><id>https://matbooth.co.uk/2020/04/23/remote-osgi-console-with-equinox</id><content type="html" xml:base="https://matbooth.co.uk/2020/04/23/remote-osgi-console-with-equinox.html"><![CDATA[<p>You may be familiar with the OSGi shell you get when you pass the <code class="language-plaintext highlighter-rouge">-console</code> option to Equinox on the command line. Did you know you can also use this console over Telnet sessions or SSH sessions? This article shows you the bare minimum needed to do so.</p>

<p>To recap, the minimal bundle set needed to start Equinox with the console is as follows:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>org.apache.felix.gogo.command_1.0.2.v20170914-1324.jar
org.apache.felix.gogo.runtime_1.1.0.v20180713-1646.jar
org.apache.felix.gogo.shell_1.1.0.v20180713-1646.jar
org.eclipse.equinox.console_1.4.0.v20190819-1430.jar
org.eclipse.osgi_3.15.200.v20200214-1600.jar
</code></pre></div></div>

<p>All of these bundles are available in the <strong>Equinox SDK</strong> zip file available from the <a href="https://download.eclipse.org/equinox/">Equinox Downloads</a> site. As of writing the latest release is <a href="https://download.eclipse.org/equinox/drops/R-4.15-202003050155/download.php?dropFile=equinox-SDK-4.15.zip">Equinox SDK 4.15</a>.</p>

<p>Extract these bundles into a directory, then inside that directory create a <code class="language-plaintext highlighter-rouge">configuration/config.ini</code> file with the following content:</p>

<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="py">osgi.bundles</span><span class="p">=</span><span class="se">\
</span><span class="w">    </span><span class="s">org.apache.felix.gogo.runtime,</span><span class="se">\
</span><span class="w">    </span><span class="s">org.apache.felix.gogo.command,</span><span class="se">\
</span><span class="w">    </span><span class="s">org.apache.felix.gogo.shell,</span><span class="se">\
</span><span class="w">    </span><span class="s">org.eclipse.equinox.console</span>
</code></pre></div></div>

<p>Now you can start this minimal Equinox, with console, by passing the <code class="language-plaintext highlighter-rouge">-console</code> option, for example:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>java <span class="nt">-jar</span> org.eclipse.osgi_<span class="k">*</span>.jar <span class="nt">-console</span>
<span class="gp">osgi&gt;</span><span class="w"> </span>ss
<span class="go">"Framework is launched."


id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.15.200.v20200214-1600
1       ACTIVE      org.apache.felix.gogo.runtime_1.1.0.v20180713-1646
2       ACTIVE      org.apache.felix.gogo.command_1.0.2.v20170914-1324
3       ACTIVE      org.apache.felix.gogo.shell_1.1.0.v20180713-1646
4       ACTIVE      org.eclipse.equinox.console_1.4.0.v20190819-1430
</span><span class="gp">osgi&gt;</span><span class="w"> </span><span class="nb">exit</span>
<span class="gp">Really want to stop Equinox? (y/n;</span><span class="w"> </span><span class="nv">default</span><span class="o">=</span>y<span class="o">)</span>  
</code></pre></div></div>

<h3 id="over-telnet">Over Telnet</h3>

<p>Starting the console in a Telnet session instead is very easy, you just need to pass a port number with the <code class="language-plaintext highlighter-rouge">-console</code> option, for example:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>java <span class="nt">-jar</span> org.eclipse.osgi_<span class="k">*</span>.jar <span class="nt">-console</span> 1234
</code></pre></div></div>

<p>From another terminal, you can then connect to the Telnet session like this, using the port you specified above:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>telnet localhost 1234
<span class="go">Trying ::1...
Connected to localhost.
Escape character is '^]'.
</span><span class="gp">osgi&gt;</span><span class="w"> </span>ss
<span class="go">"Framework is launched."


id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.15.200.v20200214-1600
1       ACTIVE      org.apache.felix.gogo.runtime_1.1.0.v20180713-1646
2       ACTIVE      org.apache.felix.gogo.command_1.0.2.v20170914-1324
3       ACTIVE      org.apache.felix.gogo.shell_1.1.0.v20180713-1646
4       ACTIVE      org.eclipse.equinox.console_1.4.0.v20190819-1430
</span><span class="gp">osgi&gt;</span><span class="w"> </span>disconnect
<span class="gp">Disconnect from console? (y/n;</span><span class="w"> </span><span class="nv">default</span><span class="o">=</span>y<span class="o">)</span> 
<span class="go">Connection closed by foreign host.
</span></code></pre></div></div>

<p>Notice the use of the <code class="language-plaintext highlighter-rouge">disconnect</code> command this time, which allows you to end the console session without causing Equinox to exit. You can of course still use <code class="language-plaintext highlighter-rouge">exit</code> if you wish to terminate Equinox remotely.</p>

<p>You may also set the port in the <code class="language-plaintext highlighter-rouge">configuration/config.ini</code> file with the addition of this line:</p>

<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="py">osgi.console</span><span class="p">=</span><span class="s">1234</span>
</code></pre></div></div>

<p>And that will start the console as a Telnet session automatically on port 1234 without needing to pass <code class="language-plaintext highlighter-rouge">-console</code> at all, but if you do pass <code class="language-plaintext highlighter-rouge">-console</code> it will override any setting you have in the <code class="language-plaintext highlighter-rouge">configuration/config.ini</code> file.</p>

<h3 id="over-ssh">Over SSH</h3>

<p>To start a console session in an SSH session, a few more bundles are needed:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>org.apache.felix.gogo.command_1.0.2.v20170914-1324.jar
org.apache.felix.gogo.runtime_1.1.0.v20180713-1646.jar
org.apache.felix.gogo.shell_1.1.0.v20180713-1646.jar
org.apache.sshd.osgi_2.4.0.v20200318-1614.jar
org.eclipse.equinox.console_1.4.0.v20190819-1430.jar
org.eclipse.equinox.console.jaas.fragment_1.0.300.v20200111-0718.jar
org.eclipse.equinox.console.ssh-1.2.600-SNAPSHOT.jar
org.eclipse.osgi_3.15.200.v20200214-1600.jar
org.slf4j.api_1.7.2.v20121108-1250.jar
</code></pre></div></div>

<p>All of these bundles are available in the <strong>Equinox SDK</strong> zip file available from the <a href="https://download.eclipse.org/equinox/">Equinox Downloads</a> site. As of writing the latest release is <a href="https://download.eclipse.org/equinox/drops/R-4.15-202003050155/download.php?dropFile=equinox-SDK-4.15.zip">Equinox SDK 4.15</a>.</p>

<p>Extract these bundles into a directory, then inside that directory create a <code class="language-plaintext highlighter-rouge">configuration/config.ini</code> file with the following content:</p>

<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="py">osgi.bundles</span><span class="p">=</span><span class="se">\
</span><span class="w">    </span><span class="s">org.apache.felix.gogo.runtime,</span><span class="se">\
</span><span class="w">    </span><span class="s">org.apache.felix.gogo.command,</span><span class="se">\
</span><span class="w">    </span><span class="s">org.apache.felix.gogo.shell,</span><span class="se">\
</span><span class="w">    </span><span class="s">org.apache.sshd.osgi,</span><span class="se">\
</span><span class="w">    </span><span class="s">org.eclipse.equinox.console,</span><span class="se">\
</span><span class="w">    </span><span class="s">org.eclipse.equinox.console.jaas.fragment,</span><span class="se">\
</span><span class="w">    </span><span class="s">org.eclipse.equinox.console.ssh@start,</span><span class="se">\
</span><span class="w">    </span><span class="s">org.slf4j.api</span>
<span class="py">osgi.console.ssh</span><span class="p">=</span><span class="s">127.0.0.1:1234</span>
<span class="py">osgi.console.ssh.useDefaultSecureStorage</span><span class="p">=</span><span class="s">true</span>
<span class="w">
</span></code></pre></div></div>

<p>Equinox uses <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/jaas/JAASRefGuide.html">JAAS</a> to authenticate SSH sessions, the default provider of which must be configured by creating a JAAS configuration file, for example <code class="language-plaintext highlighter-rouge">configuration/console.authentication.config</code> with the following content:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>equinox_console {
    org.eclipse.equinox.console.jaas.SecureStorageLoginModule REQUIRED;
};
</code></pre></div></div>

<p>Then when starting Equinox you need to tell it where the JAAS configuration is by setting the <code class="language-plaintext highlighter-rouge">java.security.auth.login.config</code> system property. The default JAAS implementation stores its credentials in a file you must specify with the <code class="language-plaintext highlighter-rouge">org.eclipse.equinox.console.jaas.file</code> system property:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>java <span class="nt">-Dssh</span>.server.keystore<span class="o">=</span>configuration/hostkey.ser <span class="se">\</span>
<span class="go">       -Dorg.eclipse.equinox.console.jaas.file=configuration/store \
       -Djava.security.auth.login.config=configuration/console.authentication.config -jar org.eclipse.osgi_*.jar
</span></code></pre></div></div>

<p>The default JAAS provider creates one default user account with username/password credentials of equinox/equinox. After you log in with these credentials, you will be prompted to create a new account and the default account will be removed.</p>

<p>Once Equinox is started, from another terminal you can connect to the SSH session like this:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>ssh <span class="nt">-p</span> 1234 equinox@127.0.0.1
<span class="go">The authenticity of host '[127.0.0.1]:1234 ([127.0.0.1]:1234)' can't be established.
RSA key fingerprint is SHA256:7x3eOsDRM5lyL5vRsVREy8hIawIfqRiZ7CBnk6GkfRA.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[127.0.0.1]:1234' (RSA) to the list of known hosts.
Password authentication
Password: 
</span><span class="gp">Currently the default user is the only one;</span><span class="w"> </span>since it will be deleted after first login, create a new user:
<span class="go">username: mbooth
password: 
Confirm password: 
roles: admin
</span><span class="gp">osgi&gt;</span><span class="w"> </span>disconnect
<span class="gp">Disconnect from console? (y/n;</span><span class="w"> </span><span class="nv">default</span><span class="o">=</span>y<span class="o">)</span> 
<span class="go">Connection to 127.0.0.1 closed.
</span></code></pre></div></div>

<p>On subsequent connections you will be required to supply the newly created credentials:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>ssh <span class="nt">-p</span> 1234 mbooth@127.0.0.1
<span class="go">Password authentication
Password: 
</span><span class="gp">osgi&gt;</span><span class="w"> </span>disconnect
<span class="gp">Disconnect from console? (y/n;</span><span class="w"> </span><span class="nv">default</span><span class="o">=</span>y<span class="o">)</span> 
<span class="go">Connection to 127.0.0.1 closed.
</span></code></pre></div></div>

<p>Once logged in there are various commands for managing user accounts, passwords and roles. Type <code class="language-plaintext highlighter-rouge">help</code> at the OSGi console prompt to find out about these commands. It is possible to implement custom JAAS providers that can use different credential stores, but that is out of the scope of this article.</p>

<h3 id="public-key-authentication">Public Key Authentication</h3>

<p>It’s common to want to use public key authentication with SSH and you may configure Equinox to do that instead of using JAAS authentication. First create your SSH key-pair as normal and create a file that contains the list of authorised keys that Equinox should consult when you attempt to connect:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>ssh-keygen <span class="nt">-f</span> ~/.ssh/equinox
<span class="go">Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/mbooth/.ssh/equinox
Your public key has been saved in /home/mbooth/.ssh/equinox.pub
The key fingerprint is:
SHA256:0k7MSbLLzhhzI7Gw6oSYEx8Fv5UpNHMPTdOUDj8rplQ mbooth@thinkpad-p50
The key's randomart image is:
+---[RSA 3072]----+
|  . + oooo..     |
|   + + =o.o      |
|    + = o+       |
|   . + BE.+      |
|. o o o.S  o     |
|o+ + +.=o .      |
|=.o =.=o..       |
|.o   O..         |
|o.  . o          |
+----[SHA256]-----+

</span><span class="gp">$</span><span class="w"> </span><span class="nb">cat</span> ~/.ssh/equinox.pub <span class="o">&gt;</span> configuration/equinox_authorized_keys
</code></pre></div></div>

<p>Next you will need to remove the following line from your <code class="language-plaintext highlighter-rouge">configuration/config.ini</code> file:</p>

<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Remove this line
</span><span class="py">osgi.console.ssh.useDefaultSecureStorage</span><span class="p">=</span><span class="s">true</span>
</code></pre></div></div>

<p>Now when you start Equinox, instead of telling it about the JAAS configuration, you must tell it about the authorised keys file:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>java <span class="nt">-Dssh</span>.server.keystore<span class="o">=</span>configuration/hostkey.ser <span class="se">\</span>
<span class="go">       -Dssh.server.authorized_keys=configuration/equinox_authorized_keys -jar org.eclipse.osgi_*.jar
</span></code></pre></div></div>

<p>And that allows you to use your SSH key instead of a username/password pair when connecting to the SSH console session:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>ssh <span class="nt">-i</span> ~/.ssh/equinox <span class="nt">-p</span> 1234 localhost
<span class="go">The authenticity of host '[localhost]:1234 ([127.0.0.1]:1234)' can't be established.
RSA key fingerprint is SHA256:m2JKy2fRZA1aqvxHBBe+Awsgk98ryI29fH03Rg7jeHw.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[localhost]:1234' (RSA) to the list of known hosts.
</span><span class="gp">osgi&gt;</span><span class="w"> </span>disconnect
<span class="gp">Disconnect from console? (y/n;</span><span class="w"> </span><span class="nv">default</span><span class="o">=</span>y<span class="o">)</span> 
<span class="go">Connection to localhost closed.
</span></code></pre></div></div>

<p>Pretty nifty, eh?</p>]]></content><author><name>Mat Booth</name><email>&amp;#x69;&amp;#x6e;&amp;#x66;&amp;#x6f;&amp;#x40;&amp;#x6d;&amp;#x61;&amp;#x74;&amp;#x62;&amp;#x6f;&amp;#x6f;&amp;#x74;&amp;#x68;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#x2e;&amp;#x75;&amp;#x6b;</email></author><category term="eclipse" /><category term="osgi" /><summary type="html"><![CDATA[You may be familiar with the OSGi shell you get when you pass the -console option to Equinox on the command line. Did you know you can also use this console over Telnet sessions or SSH sessions? This article shows you the bare minimum needed to do so.]]></summary></entry><entry><title type="html">Eclipse and Handling Content Types on Linux</title><link href="https://matbooth.co.uk/2020/02/06/eclipse-handling-content-types.html" rel="alternate" type="text/html" title="Eclipse and Handling Content Types on Linux" /><published>2020-02-06T15:00:00+00:00</published><updated>2020-02-06T15:00:00+00:00</updated><id>https://matbooth.co.uk/2020/02/06/eclipse-handling-content-types</id><content type="html" xml:base="https://matbooth.co.uk/2020/02/06/eclipse-handling-content-types.html"><![CDATA[<p>One of the ways we achieve nice desktop integration on Linux by packaging Eclipse in RPMs or as a Flatpak application is by providing a desktop entry file (using the Freedesktop <a href="https://specifications.freedesktop.org/desktop-entry-spec/latest/">Desktop Entry Specification</a>) to allow desktop environments to list Eclipse in their application launchers and menus.</p>

<p>In this file we may also declare what content types Eclipse supports so that we also get nice integration with file managers. This results in users discovering that files may be edited with Eclipse before they even start up their IDE. For example, if you install the <a href="https://flathub.org/apps/details/org.eclipse.Java">Flatpak version of Eclipse</a>, you may now see this nice context menu entry when you right-click on Java, Maven POM or Gradle Build files:</p>

<p><img src="/assets/images/open_with.png" alt="Open with Eclipse" /></p>

<p>However there seems to be (surprisingly to me, at least) no Freedesktop standard way to do any post-installation manipulation of the information supplied by desktop entry files; an application that has the ability to install plug-ins through it’s own integral Marketplace client like Eclipse does has no ability to tell the host system about the new content type support that new plug-ins add.</p>

<p>Apparently this is not really a common use-case, and applications generally do one of two things:</p>

<h2 id="thing-1-be-greedy">Thing 1 (Be Greedy)</h2>

<p>Just declare that they support all the file types, and fail gracefully if the support is missing. E.g. a video player will just declare that it supports all the different kinds of videos and if a codec is missing it just warns the user when it fails. The user can then install that codec at their leisure and try again.</p>

<p>In Eclipse’s case, I don’t think we can know up front all the possible content types for which people can author plug-ins, however each Marketplace entry advertises (or should advertise) what content types are supported by its plug-ins. By collecting this information for Marketplace entries that support the release of Eclipse we are building (e.g., 2019-12) we could generate a monster desktop file that contains all the types the Marketplace knows about at that time.</p>

<h3 id="pros">Pros</h3>

<p>This allows users to discover that Eclipse can support a type even before the user has even opened Eclipse, or installed any plug-ins, simply by attempting to open a file in their file manager.</p>

<h3 id="cons">Cons</h3>

<p>New Marketplace entries created after Eclipse is built would be omitted from this list, but that might not a be big problem in real life. A rebuild would be required to update the content type list.</p>

<p>We also would not be able to generate this list at build time for RPM or Flatpak type distributions of Eclipse since these build environments allow no connection to the outside world – it would require the packager to maintain/pre-build such a list.</p>

<p>It might be okay for e.g., VLC to do this since it only “claims” audio/video files, but there would be no limit to the kinds of files that Eclipse might “claim” and this might be too intrusive or annoying for the user.</p>

<h2 id="thing-2-be-honest">Thing 2 (Be Honest)</h2>

<p>When installed, extensions deliver additional desktop entry files that contain the additional content types and actions to open them, but are with a flag set to make them “hidden” to allow file managers to present it as an option when opening files but avoid duplicate entries in the desktop environment’s applications menu. This means an application will only advertise its current capabilities. For example, even though you have the <code class="language-plaintext highlighter-rouge">libreoffice-core</code> package installed, you might not get an “open with” option for spreadsheets until you install <code class="language-plaintext highlighter-rouge">libreoffice-calc</code>.</p>

<p>In Eclipse’s case we know what content types a plug-in supports because each one contributes to the extension registry about which file extensions it knows, so Eclipse could be taught to generate new desktop entries file after a p2 install/uninstall operation.</p>

<h3 id="pros-1">Pros</h3>

<p>No need to know about all the content types up-front, so saves on packaging work and not all Marketplace entries are correctly annotated with their supported content types anyway.</p>

<p>Wouldn’t clutter up the user’s file manager with options they might not ever care about for files they might never edit in Eclipse and after all, Eclipse can still prompt users to install plug-ins from the Marketplace when it detects a content type for which a plug-in is available.</p>

<p>Plug-in installation is user-specific for read-only installations like RPM and Flatpak, so this has the nice side-effect on multi-user systems of showing the option to open a file with Eclipse only to users who have the relevant plug-ins installed.</p>

<h3 id="cons-1">Cons</h3>

<p>Eclipse needs to know how to generate new desktop files when a plug-in is installed that adds support for a new content type.</p>

<p>Users have to actually open a file in Eclipse before discovering there is a Marketplace entry that supports that content type, instead of being prompted by their file manager before Eclipse is launched. Eclipse is still doing plug-in discovery, so this isn’t a huge concern for me.</p>

<h2 id="feedback">Feedback</h2>

<p>If you would like to see more nice desktop integrations like this, <a href="https://twitter.com/FOSS_mbooth">let me know on Twitter</a> or by <a href="https://github.com/flathub/org.eclipse.Java/issues">filing a bug against Eclipse on Flathub</a>.</p>]]></content><author><name>Mat Booth</name><email>&amp;#x69;&amp;#x6e;&amp;#x66;&amp;#x6f;&amp;#x40;&amp;#x6d;&amp;#x61;&amp;#x74;&amp;#x62;&amp;#x6f;&amp;#x6f;&amp;#x74;&amp;#x68;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#x2e;&amp;#x75;&amp;#x6b;</email></author><category term="linux" /><category term="eclipse" /><summary type="html"><![CDATA[One of the ways we achieve nice desktop integration on Linux by packaging Eclipse in RPMs or as a Flatpak application is by providing a desktop entry file (using the Freedesktop Desktop Entry Specification) to allow desktop environments to list Eclipse in their application launchers and menus.]]></summary></entry><entry><title type="html">Eclipse Now Available From Flathub</title><link href="https://matbooth.co.uk/2020/01/20/eclipse-now-in-flathub.html" rel="alternate" type="text/html" title="Eclipse Now Available From Flathub" /><published>2020-01-20T16:00:00+00:00</published><updated>2020-01-20T16:00:00+00:00</updated><id>https://matbooth.co.uk/2020/01/20/eclipse-now-in-flathub</id><content type="html" xml:base="https://matbooth.co.uk/2020/01/20/eclipse-now-in-flathub.html"><![CDATA[<p>Good news! Eclipse is now available from <a href="https://flathub.org/apps/search/eclipse%20ide">Flathub</a>, the central application repository for Flatpak applications.</p>

<p><img src="/assets/images/eclipse-logo.jpg" alt="Eclipse IDE Logo" /></p>

<p>Two flavours of Eclipse IDE are now available from Flathub:</p>

<ul>
  <li><a href="https://flathub.org/apps/details/org.eclipse.Java">Eclipse IDE for Java Developers</a> – The essential tooling for any Java developer.</li>
  <li><a href="https://flathub.org/apps/details/org.eclipse.Committers">Eclipse IDE for Eclipse Committers</a> – Tooling for development of Eclipse itself at Eclipse.org.</li>
</ul>

<p>See the TL;DR section at the bottom of this article if you want to quickly get started now!</p>

<h2 id="why-flatpak">Why Flatpak?</h2>

<p>If you don’t already know, <a href="https://flatpak.org/">Flatpak</a> is the new way to build and distribute desktop applications for Linux. You can use <a href="https://flathub.org/">Flathub</a> to gain access to a growing collection of Flatpak applications, including Eclipse IDE. You just need to <a href="https://flatpak.org/setup/">follow the setup instructions</a> for your Linux distribution.</p>

<p>I’ve discussed before on this blog about the <a href="/2015/12/09/benefits-of-distro-packaging.html">benefits of packaging software for Linux distributions</a> but from the upstream project’s point of view, there are two big problems that distro packaging does not solve:</p>

<ul>
  <li>There are so many Linuxes!</li>
</ul>

<p>After all the hard work of packaging your application, it is still only available for only one distro. Keeping Eclipse RPMs maintained in Fedora is almost a full time job, it would be almost impossible for me to duplicate that work for Ubuntu, for example, where a completely different packaging format is used.</p>

<ul>
  <li>Forwards and backwards compatibility.</li>
</ul>

<p>Different Linux distributions package different versions of your dependencies, which makes it difficult to ensure that your application works on them all. Eclipse SWT supports a large range of GTK versions for this reason and it has historically been a lot of work for the SWT contributors. It would be unfair only support the latest versions of GTK on cutting edge platforms like Fedora and Ubuntu at the expense of users on slow-moving enterprise-style distros like RHEL or SLES; or vice-versa.</p>

<h2 id="yes-but-why-flatpak">Yes, but why Flatpak?</h2>

<p>Flatpak solves both these problems whilst keeping the polished, tight integration with the host system that traditional Linux distro packaging provides. It does this by providing common runtime environments that work on every Linux distribution that supports Flatpak.</p>

<p>The implication this has for Eclipse is that we can make the IDE available everywhere Flatpak is supported at almost no additional cost in resources and users can even get the same shiny new version of the IDE on older versions of Linux distros where it would have been impossible to upgrade the in-distro packages. If SWT raises the draw-bridge on old versions of GTK and you can’t upgrade your Linux distro, or you want to use Eclipse on a yet-to-be-released version of your Linux distro which has a version of GTK untested by Eclipse, then it’s not longer a problem because the Flatpak runtime provides a stable and predictable runtime environment. No longer do we have to worry about API/ABI breakage caused by the distro upgrading dependencies too quickly, or not quickly enough, for Eclipse.</p>

<p>Having such a predictable runtime environment for Eclipse will also help a great deal in diagnosing reported problems. A consistent Flatpak runtime across Linux distributions will greatly reduce the chances that we are bitten, for example, by Ubuntu-specific bugs that cannot be reproduced on Fedora.</p>

<h2 id="tldr---instructions-for-the-impatient">TL;DR - Instructions for the Impatient</h2>

<p>Enable the Flathub repository:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
</code></pre></div></div>

<p>Install the IDE:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ flatpak install flathub org.eclipse.Java
</code></pre></div></div>

<p>Or:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ flatpak install flathub org.eclipse.Committers
</code></pre></div></div>

<h2 id="bugs">Bugs?</h2>

<p>If you encounter any bugs that you suspect are specific to the Flatpak version of Eclipse IDE, please consider <a href="https://github.com/flathub/org.eclipse.Java/issues">reporting them at the Github repo</a> where it is maintained. Thanks!</p>]]></content><author><name>Mat Booth</name><email>&amp;#x69;&amp;#x6e;&amp;#x66;&amp;#x6f;&amp;#x40;&amp;#x6d;&amp;#x61;&amp;#x74;&amp;#x62;&amp;#x6f;&amp;#x6f;&amp;#x74;&amp;#x68;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#x2e;&amp;#x75;&amp;#x6b;</email></author><category term="linux" /><category term="eclipse" /><summary type="html"><![CDATA[Good news! Eclipse is now available from Flathub, the central application repository for Flatpak applications.]]></summary></entry><entry><title type="html">Simple Hammer Repair</title><link href="https://matbooth.co.uk/2019/09/03/simple-hammer-repair.html" rel="alternate" type="text/html" title="Simple Hammer Repair" /><published>2019-09-03T12:00:00+01:00</published><updated>2019-09-03T12:00:00+01:00</updated><id>https://matbooth.co.uk/2019/09/03/simple-hammer-repair</id><content type="html" xml:base="https://matbooth.co.uk/2019/09/03/simple-hammer-repair.html"><![CDATA[<p>You may recall from my <a href="/2019/01/29/broken-tools.html">previous post about broken tools</a> that I broke my favourite hammer by using the claw to break down what turned out to be some <strong>really</strong> sturdy cupboardry. In this post I document the manufacture of a new handle from scratch.</p>

<h3 id="starting-from-scrap">Starting from Scrap</h3>

<p>I’ve had this piece of hardwood offcut in my scrap drawer for a while and thought it would be ideal for this project. Unfortunately I’m not a woodologist so I can’t tell you what species this is but the grain is much finer and straighter than the original handle. Let’s assume that’s a good thing for this application.</p>

<p><img src="/assets/images/diy/11-1-table-saw-blank_small.jpg" alt="One Man's Rubbish..." /></p>

<p>I cut out a handle blank that is a bit larger in all dimensions than the original handle using the table saw, then with a hand saw I cut a tenon in one end so that it was a snug fit into the hammer head.</p>

<p><img src="/assets/images/diy/11-2-hammer-head-tenon_small.jpg" alt="Not a Shark" /></p>

<h3 id="taking-shape">Taking Shape</h3>

<p>Sharp corners are no good for a handle, so the next job was to take a hand file and start adding some contours. I used the file to bring the shoulders of the tenon in to where the wood meets the metal.</p>

<p><img src="/assets/images/diy/11-3-hand-filed-shoulder_small.jpg" alt="Those Curves!" /></p>

<p>That nice straight grain meant that as soon as I added some curves, pretty patterns immediately appeared. Below is a shot of the whole thing after sanding some ergonomics into the rest of the handle.</p>

<p><img src="/assets/images/diy/11-4-shaped-handle_small.jpg" alt="Hit Stuff in Comfort" /></p>

<p>The two metal wedges you can see in the bottom right of the above picture are the wedges that were retaining the old handle in the head of the hammer. In the end I decided not to re-use these and instead made a wooden wedge from the same stock as the new handle.</p>

<h3 id="finishing">Finishing</h3>

<p>After giving it some sanding with slightly higher grit I gave it a couple coats of a hard-wearing poly-urethane varnish. This is a tool I expect to use often, so I want it to be able to resist some punishment.</p>

<p><img src="/assets/images/diy/11-5-varnish-leather_small.jpg" alt="Hit Stuff in Style" /></p>

<p>You can see I also drilled a hole in the end of the handle and tied on a loop of scrap leather. I’ve no idea yet if I will find this feature useful. Maybe it’ll be handy to be able to hang it somewhere when I’m up a ladder. Maybe I’ll just swing it around like Thor…</p>

<p>The final step is to permanently affix the head onto the handle.</p>

<p><img src="/assets/images/diy/11-6-wedge-just-the-tip_small.jpg" alt="And Only for a Minute" /></p>

<p>I made a one-saw-kerf-width slot in the tenon and fashioned a crude wedge on the belt sander from a slice of the same stock as I used for the handle. Once I was ready to commit, I applied some PVA and hammered the wedge home. After letting the glue dry I was able to trim off the excess with a hand saw and sand it flush.</p>

<p><img src="/assets/images/diy/11-7-wedge-trimmed-flush_small.jpg" alt="Feeling Flush" /></p>

<p>Here is the finished article side-by-side with the old handle. I’m pretty happy with it. Table saw scale for, er, scale.</p>

<p><img src="/assets/images/diy/11-8-finished-comparison_small.jpg" alt="No Bananas, Sorry" /></p>

<h3 id="bonus-nine-month-update">Bonus Nine Month Update!</h3>

<p>Since I managed to procrastinate writing this post for more than half a year, and I’ve used this hammer most weekends since January (it is September now) for various projects, including ripping out my bathroom (I will likely talk about that in a future post) I can tell you how well my repair went!</p>

<p>It has put up with a fair amount of abuse and there are plenty of dings and dents in the finish to show for it, but there is no actual damage to the handle, which is good. I’m pleased with the shape and the extra length in the handle too as compared to the original; it’s quite comfortable to use.</p>

<p>One thing that did happen however is that after a few weeks of really beating on a cold chisel to remove some tiling and plaster work, the head was starting to work its way loose. Not because the wedge was becoming unstuck though, it seems like the wood fibres in the tenon had just compressed a bit after some amount of bedding in. I disassembled the hammer by drilling out the original wedge and reinforced it by cutting two more saw-kerfs into the tenon and making three new wooden wedges. Here it is after the glue has set and the wedges sawn flush.</p>

<p><img src="/assets/images/diy/11-9-update-wedges_small.jpg" alt="It's Called &quot;Character&quot;" /></p>

<p>It has been completely solid ever since. Sure, it’s a bit uglier now because the end of the tenon sits a little bit below the top of the hammer head preventing sanding, but who cares; it’s a tool for using not for looking at. And that loop of leather at the end of the handle? Ultimately pointless, I do just swing it about like Thor after all…</p>]]></content><author><name>Mat Booth</name><email>&amp;#x69;&amp;#x6e;&amp;#x66;&amp;#x6f;&amp;#x40;&amp;#x6d;&amp;#x61;&amp;#x74;&amp;#x62;&amp;#x6f;&amp;#x6f;&amp;#x74;&amp;#x68;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#x2e;&amp;#x75;&amp;#x6b;</email></author><category term="diy" /><summary type="html"><![CDATA[You may recall from my previous post about broken tools that I broke my favourite hammer by using the claw to break down what turned out to be some really sturdy cupboardry. In this post I document the manufacture of a new handle from scratch.]]></summary></entry><entry><title type="html">The State of Java in Flathub</title><link href="https://matbooth.co.uk/2019/07/22/openjdk-in-flathub.html" rel="alternate" type="text/html" title="The State of Java in Flathub" /><published>2019-07-22T16:00:00+01:00</published><updated>2019-07-22T16:00:00+01:00</updated><id>https://matbooth.co.uk/2019/07/22/openjdk-in-flathub</id><content type="html" xml:base="https://matbooth.co.uk/2019/07/22/openjdk-in-flathub.html"><![CDATA[<h3 id="latest-versus-lts-openjdks">“Latest” versus “LTS” OpenJDKs</h3>

<p>I am now maintaining two streams of OpenJDK SDK extensions in Flathub:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">org.freedesktop.Sdk.Extension.openjdk11</code> – this is supplying the <strong>LTS</strong> (long-term support) OpenJDK 11.</li>
  <li><code class="language-plaintext highlighter-rouge">org.freedesktop.Sdk.Extension.openjdk</code> – this is supplying whatever the current short-lived <strong>Latest</strong> OpenJDK is; it is currently OpenJDK 12. (Note the ommission of a version number suffix in the extension ID, this is intentional.)</li>
</ul>

<p>When OpenJDK 13 is released, OpenJDK 12 will be deprecated and the <code class="language-plaintext highlighter-rouge">org.freedesktop.Sdk.Extension.openjdk</code> extension will be re-based to OpenJDK 13 – this is why the version number suffix is omitted from the extension ID.</p>

<p>The idea of this is to satisfy two use-cases:</p>

<ul>
  <li><strong>Stability</strong> – if you want stability, you may continue rely on the on the <strong>LTS</strong> version supplied by the <code class="language-plaintext highlighter-rouge">org.freedesktop.Sdk.Extension.openjdk11</code> extension.</li>
  <li><strong>Early Adopters</strong> – if you want to take advantage of the latest and greatest features and enhancements in OpenJDK, then you can consume the <strong>Latest</strong> version supplied by the <code class="language-plaintext highlighter-rouge">org.freedesktop.Sdk.Extension.openjdk</code> extension, which will have periodic major updates when new major versions are released by the OpenJDK project.</li>
</ul>

<p>For maintainers of Java-based applications in Flathub, it’s worth noting that even if you consume the <strong>Latest</strong> OpenJDK extension in your application, users will not be broken by major updates because OpenJDK is bundled into your Flatpak. The implication of this for users is that they won’t see updates to their Java version until the application maintainer rebuilds the application in Flathub.</p>

<p>If you maintain a Java-based Flatpak application on Flathub, you can consume the latest version of your chosen OpenJDK stream (either <strong>LTS</strong> or <strong>Latest</strong>) simply by rebuilding; the latest version of that OpenJDK steam will be pulled in automatically.</p>

<h3 id="new-openjdk-version-updates">New OpenJDK Version Updates</h3>

<p>Speaking of updates, I recently updated OpenJDK 11 to version <strong>11.0.4</strong> and the OpenJDK 12 to version <strong>12.0.2</strong>; these versions are available now from Flathub.</p>

<p>It’s easy to check which version of Java is shipped with a Flatpak application, using BlueJ as an example:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>flatpak run <span class="nt">--command</span><span class="o">=</span><span class="s1">'java'</span> org.bluej.BlueJ <span class="nt">-version</span>
<span class="go">openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment (build 11.0.2+9)
OpenJDK 64-Bit Server VM (build 11.0.2+9, mixed mode)
</span></code></pre></div></div>

<p>From the above we can see that BlueJ contains <strong>11.0.2</strong>, an old version of the <strong>LTS</strong> stream. The application needs rebuilding to take advantage of bug fixes in version <strong>11.0.4</strong>.</p>

<p>I recommend that all Java-based Flatpak applications are rebuilt to take advantage of fixes in the latest builds of OpenJDK.</p>

<h3 id="using-openjdk-in-a-new-application">Using OpenJDK in a New Application</h3>

<p>I suspect most people figure it out by looking at existing Flatpak manifests, but it’s probably worth quickly mentioning how to go about using the OpenJDK platform extensions to ship a Java application in Flathub. In the vast majority of cases, it is probably sufficient to add the SDK extension to the manifest and calling the JRE installation script. For example:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"id"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"org.example.MyApp"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"branch"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"1.0"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"runtime"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"org.freedesktop.Platform"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"runtime-version"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"18.08"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"sdk"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"org.freedesktop.Sdk"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"sdk-extensions"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="s2">"org.freedesktop.Sdk.Extension.openjdk11"</span><span class="w"> </span><span class="p">],</span><span class="w">
  </span><span class="nl">"modules"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"name"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"openjdk"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"buildsystem"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"simple"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"build-commands"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="s2">"/usr/lib/sdk/openjdk11/install.sh"</span><span class="w"> </span><span class="p">]</span><span class="w">
  </span><span class="p">},</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"name"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"myapp"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"buildsystem"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"simple"</span><span class="p">,</span><span class="w">
    </span><span class="err">....</span><span class="w">
  </span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w">
  </span><span class="err">....</span><span class="w">
  </span><span class="nl">"finish-args"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="s2">"--env=PATH=/app/jre/bin:/usr/bin"</span><span class="w"> </span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>And the JRE will be available in the <code class="language-plaintext highlighter-rouge">/app/jre</code> directory. (In this example, <code class="language-plaintext highlighter-rouge">/app/jre/bin</code> has also been added to the PATH environment variable.)</p>

<p>Alternatively, if your application requires a full JDK rather than a JRE, then you can substitute <code class="language-plaintext highlighter-rouge">installjdk.sh</code> for <code class="language-plaintext highlighter-rouge">install.sh</code> and the JDK will be available in the <code class="language-plaintext highlighter-rouge">/app/jdk</code> directory.</p>

<h3 id="deprecated-openjdks">Deprecated OpenJDKs</h3>

<p>And finally…</p>

<p>If your Flatpak application was built against either the <code class="language-plaintext highlighter-rouge">org.freedesktop.Sdk.Extension.openjdk9</code> extension or the <code class="language-plaintext highlighter-rouge">org.freedesktop.Sdk.Extension.openjdk10</code> extension and therefore ships OpenJDK 9 or 10, then you should know that since the release of OpenJDK 11, these are <strong><em>DEPRECATED</em></strong>. These JDKs are no longer receiving any maintenance or security updates and are considered <strong><em>EOL</em></strong> by the upstream OpenJDK project.</p>

<p>Please <strong><em>DO NOT</em></strong> use these OpenJDKs for new applications being submitted to Flathub, and please migrate any existing applications to a newer, more supported OpenJDK, preferably 11 or 12 as appropriate.</p>

<p>At some point I will probably go through Flathub and file bugs against any applications that are still shipping deprecated OpenJDKs, but I would appreciate it if I didn’t have to file any. Thanks in advance!</p>]]></content><author><name>Mat Booth</name><email>&amp;#x69;&amp;#x6e;&amp;#x66;&amp;#x6f;&amp;#x40;&amp;#x6d;&amp;#x61;&amp;#x74;&amp;#x62;&amp;#x6f;&amp;#x6f;&amp;#x74;&amp;#x68;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#x2e;&amp;#x75;&amp;#x6b;</email></author><category term="linux" /><category term="java" /><summary type="html"><![CDATA[“Latest” versus “LTS” OpenJDKs]]></summary></entry><entry><title type="html">Don’t Know My Own Strength</title><link href="https://matbooth.co.uk/2019/01/29/broken-tools.html" rel="alternate" type="text/html" title="Don’t Know My Own Strength" /><published>2019-01-29T15:00:00+00:00</published><updated>2019-09-03T12:00:00+01:00</updated><id>https://matbooth.co.uk/2019/01/29/broken-tools</id><content type="html" xml:base="https://matbooth.co.uk/2019/01/29/broken-tools.html"><![CDATA[<p>I like to subscribe to Adam Savage’s philosophy on buying tools, which goes something along the lines of, <a href="https://www.reddit.com/r/maker/comments/4hv3an/maker_ama_series_i_am_adam_savage_maker/d2slfgb/">“buy cheap tools until you know know what you really need from them, then buy the best version you can afford.”</a></p>

<p>With that in mind I tend to buy the cheapest thing possible for the job I need to do and use it until it breaks, wears out, or otherwise fails before replacing it with a more expensive version. The idea is that I’ll have no idea how much use I will get out of a tool so this way, if I end up using a tool just once or twice or year then I haven’t wasted any money on expensive tools that I barely use and if I’ve used a tool so much that I have broken it or worn it out, then I have a good excuse to buy a more expensive tool and will have a much better idea of what to look out for when doing so.</p>

<p>Here’s a compilation of some tools I’ve broken recently and my plans for their replacement.</p>

<h3 id="rolson-quality-tools-screwdriver">Rolson Quality Tools Screwdriver</h3>

<p>When they have to write “quality” on the product, you just know that’s exactly what it isn’t.</p>

<p>With this screwdriver I was removing some fitted cupboardry from my porch that was attached to the stone floor with, it turns out, 120mm <a href="https://en.wikipedia.org/wiki/Unobtainium">unobtainium</a> wood screws – I’m honestly surprised that the handle gave up before stripping the screw head. The handle appears to be made entirely of some kind of rubber polymer and just sheared off the driver shaft in my hands.</p>

<p><img src="/assets/images/diy/07-broken_screwdriver_small.jpg" alt="A &quot;Quality&quot; Screwdriver" /></p>

<p>Since I have no special requirements for screwdrivers and this Rolson already lasted for years, I just replaced it with another budget brand driver from the big, orange DIY retailer. This one however appears to have a PA6 Nylon handle (with some rubber overmolding for comfort) so hopefully it holds up better.</p>

<h3 id="macallister-clamp">MacAllister Clamp</h3>

<p>Although it looks like I squeezed the handle off this clamp, I can’t take all the credit for breaking this – it was mostly a bit of plywood. I was moving a full sheet of 18mm plywood and didn’t see that this clamp was on the floor when I set it down, but I did hear the tell-tale crack of snapping plastic. MacAllister is the power tool own-brand from the big, orange DIY retailer, so I don’t expect the greatest quality, but I didn’t expect the handles to just snap off when subjected to a bit of side-load.</p>

<p><img src="/assets/images/diy/07-broken_clamp_small.jpg" alt="A Squeeze Too Far" /></p>

<p>Since this clamp came in a set from the reduced bin, and you can’t have too many clamps, I have a bunch of them knocking about so I haven’t needed to buy any replacements yet.</p>

<h3 id="this-anonymous-clawhammer">This Anonymous Clawhammer</h3>

<p>We’ve had this old clawhammer for so long I don’t remember where it came from originally, but it has been a faithful servant for years until one day when I was (ab)using the claw and exerted what was obviously too much force and the handle finally gave up and snapped in two.</p>

<p><img src="/assets/images/diy/07-broken_hammer_small.jpg" alt="The Final Blow" /></p>

<p>I really liked this hammer, so instead of buying a replacement, I will be making a new handle from a nice piece of slow-grown hardwood and repairing it. <a href="/2019/09/03/simple-hammer-repair.html">A future blog post</a> will detail this process.</p>

<h3 id="macallister-miniature-bench-vice">MacAllister Miniature Bench Vice</h3>

<p>We bought a couple of these cheap, miniature bench vices for work-holding in the sewing room. Unfortunately the plastic knobs on the handles came pre-cracked from the factory and fell off as soon as the vice was out of the box. This means that they are, unsurprisingly, quite difficult to use due to the handle bar falling onto the floor and rolling under the bench whenever you turn it.</p>

<p><img src="/assets/images/diy/07-broken_vice_hand_small.jpg" alt="A Bad Habit" /></p>

<p>Since there seems to be nothing wrong with the vices themselves (qualified with a “yet,” since they are still brand new) I’ll be making some new vice handles in a future blog post so that we can give them a fair try.</p>]]></content><author><name>Mat Booth</name><email>&amp;#x69;&amp;#x6e;&amp;#x66;&amp;#x6f;&amp;#x40;&amp;#x6d;&amp;#x61;&amp;#x74;&amp;#x62;&amp;#x6f;&amp;#x6f;&amp;#x74;&amp;#x68;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#x2e;&amp;#x75;&amp;#x6b;</email></author><category term="diy" /><summary type="html"><![CDATA[I like to subscribe to Adam Savage’s philosophy on buying tools, which goes something along the lines of, “buy cheap tools until you know know what you really need from them, then buy the best version you can afford.”]]></summary></entry><entry><title type="html">Benefits of Linux Distro Packaging</title><link href="https://matbooth.co.uk/2015/12/09/benefits-of-distro-packaging.html" rel="alternate" type="text/html" title="Benefits of Linux Distro Packaging" /><published>2015-12-09T11:00:00+00:00</published><updated>2015-12-09T11:00:00+00:00</updated><id>https://matbooth.co.uk/2015/12/09/benefits-of-distro-packaging</id><content type="html" xml:base="https://matbooth.co.uk/2015/12/09/benefits-of-distro-packaging.html"><![CDATA[<p>Recently, I have been adding a lot of patches to the version of Eclipse (Mars.1) that is packaged in Fedora Linux. This post attempts to explain why.</p>

<p>In my opinion, one of the chief benefits to packaging your software for a Linux distribution is the ability of the distribution to carry patches. These patches generally come in two flavours:</p>

<p><strong>1. Bug-fixes back-ported from the upstream project.</strong></p>

<p>This is useful when the upstream project fixes a bug that affects their users, but have not yet released a new version of their software. Some projects have very long or infrequent release cycles, so the Linux distro may want to cherry-pick fixes and carry the patches until the the upstream project releases a fixed version, at which time the patches can be dropped.</p>

<p><strong>2. Bug-fixes that have yet to be merged into the upstream project.</strong></p>

<p>This is useful when the Linux distro fixes a bug that affects their users that the upstream project does not yet know about. Maybe it was missed upstream because they develop mostly on Mac or Windows, or maybe the bug only manifests on this particular distro. Either way, the Linux distro can carry the patch and work with the upstream project to get it merged. Once again, when upstream releases a version containing a fix, the distro can drop the patch.</p>

<p><strong>In both cases, the end result is a better user experience for your software on Linux.</strong></p>

<p>Which brings me back to Eclipse… Since GTK was updated to 3.18 on Fedora there have been some extremely visible rendering bugs in various parts of the Eclipse IDE on Fedora. Most of these bugs have been fixed upstream in Eclipse’s master branch, but it’s going to be a long time until Eclipse does another release that includes these fixes, even if they are chosen to be cherry-picked for the Mars.2 release. In Fedora, we chose to back-port them to current release Mars.1.</p>

<p>The following screenshot shows the difference it has made to the background colours in the workspace chooser dialog. Eclipse downloaded from eclipse.org is on the left, Eclipse from the Fedora package is on the right:</p>

<p><img src="/assets/images/workspace_chooser_colors.png" alt="Workspace Chooser" /></p>

<p>You should see the same difference in other dialogs too, such as wizard dialogs and the EGit commit dialog.</p>

<p>The next screenshot shows the difference it has made to the form editor, where text labels used to be positioned incorrectly or oddly truncated. Again, Eclipse downloaded from eclipse.org is on the left, Eclipse from the Fedora package is on the right:</p>

<p><img src="/assets/images/form_editor_text.png" alt="Form Editor" /></p>

<p>Many thanks to <a href="https://twitter.com/yyzericwill">Eric Williams</a> for getting these highly visible SWT/GTK bugs fixed and committed upstream at eclipse.org and thus allowing me to back-port them to Fedora. I’m sure our users will appreciate it!</p>

<p>If you are an Eclipse on Fedora user, you can get the latest patches when version <strong>4.5.1-6</strong> of the Eclipse packages hit the “updates-testing” repository either today or tomorrow:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span><span class="nb">sudo </span>dnf <span class="nt">--enablerepo</span><span class="o">=</span>updates-testing update eclipse<span class="se">\*</span>
</code></pre></div></div>

<p>And if you have time, please <a href="https://bodhi.fedoraproject.org/updates/FEDORA-2015-c3a395d3f7">leave feedback</a> (positive or negative) by <a href="https://bodhi.fedoraproject.org/updates/FEDORA-2015-c3a395d3f7">adding a comment</a> in Bodhi, the Fedora updates system.</p>]]></content><author><name>Mat Booth</name><email>&amp;#x69;&amp;#x6e;&amp;#x66;&amp;#x6f;&amp;#x40;&amp;#x6d;&amp;#x61;&amp;#x74;&amp;#x62;&amp;#x6f;&amp;#x6f;&amp;#x74;&amp;#x68;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#x2e;&amp;#x75;&amp;#x6b;</email></author><category term="linux" /><category term="eclipse" /><summary type="html"><![CDATA[Recently, I have been adding a lot of patches to the version of Eclipse (Mars.1) that is packaged in Fedora Linux. This post attempts to explain why.]]></summary></entry></feed>