<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Open Source on Sven Ruppert</title><link>https://svenruppert.com/tags/open-source/</link><description>Sven Ruppert — Java Veteran, Speaker, Trainer &amp; Bushcrafter. Articles, talks, workshops and videos on Core Java, Cybersecurity, Vaadin and Developer Relations.</description><generator>Hugo</generator><language>en</language><managingEditor>sven.ruppert@gmail.com (Sven Ruppert)</managingEditor><webMaster>sven.ruppert@gmail.com (Sven Ruppert)</webMaster><copyright>© 2026 Sven Ruppert</copyright><atom:link href="https://svenruppert.com/tags/open-source/index.xml" rel="self" type="application/rss+xml"/><image><url>https://svenruppert.com/img/sven-ruppert.jpg</url><title>Sven Ruppert</title><link>https://svenruppert.com/tags/open-source/</link></image><lastBuildDate>Tue, 04 Jun 2019 00:00:00 +0000</lastBuildDate><item><title>Nano Vaadin Jetty</title><link>https://svenruppert.com/projects/nano-vaadin-jetty/</link><pubDate>Tue, 04 Jun 2019 00:00:00 +0000</pubDate><author>sven.ruppert@gmail.com (Sven Ruppert)</author><dc:creator>Sven Ruppert</dc:creator><guid isPermaLink="true">https://svenruppert.com/projects/nano-vaadin-jetty/</guid><description>A tiny Java 26 / Vaadin Flow launcher on embedded Jetty 12 (EE11). Spin up a Vaadin servlet from a single executable JAR — no Spring, no app server, just a minimal API.</description><content:encoded>&lt;![CDATA[<p>A small library that lets you embed Vaadin Flow in a<strong>single executable JAR</strong> —
spun up against embedded Jetty with a minimal API. No Spring, no application
server, no XML. Just a couple of static method calls.</p><h2 id="why-this-exists">Why this exists</h2><p>Vaadin&rsquo;s default packaging path leans on Spring Boot or a servlet container
running a WAR. For tiny tools, internal dashboards, or one-shot utilities
that&rsquo;s overkill — you want a<code>java -jar foo.jar</code> and be done.</p><p>The catch: embedded Jetty&rsquo;s annotation scanner only walks JARs and<code>WEB-INF/classes</code>. When the app runs from an IDE or<code>mvn exec:java</code>, your<code>@Route</code> classes live in plain classpath directories that Jetty&rsquo;s scanner
ignores. Vaadin&rsquo;s<code>RouteRegistryInitializer</code> then sees zero routes and your
&ldquo;Hello World&rdquo; 404s.</p><p>Nano Vaadin Jetty solves that without forcing you into framework-land.</p><h2 id="the-whole-api-in-three-calls">The whole API in three calls</h2><div class="code-wrap"><div class="code-wrap__bar"><span class="code-wrap__lang">java</span><button type="button" class="code-wrap__copy" aria-label="Copy code">Copy</button></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">import</span><span class="w"/><span class="nn">com.svenruppert.vaadin.nano.CoreUIServiceJava</span><span class="p">;</span><span class="w"/></span></span><span class="line"><span class="cl"><span class="w"/></span></span><span class="line"><span class="cl"><span class="c1">// 1. Plain start — caller wires routes elsewhere</span><span class="w"/></span></span><span class="line"><span class="cl"><span class="n">Server</span><span class="w"/><span class="n">server</span><span class="w"/><span class="o">=</span><span class="w"/><span class="n">CoreUIServiceJava</span><span class="w"/></span></span><span class="line"><span class="cl"><span class="w"/><span class="p">.</span><span class="na">startServer</span><span class="p">(</span><span class="s">"127.0.0.1"</span><span class="p">,</span><span class="w"/><span class="n">8080</span><span class="p">)</span><span class="w"/></span></span><span class="line"><span class="cl"><span class="w"/><span class="p">.</span><span class="na">getOrThrow</span><span class="p">();</span><span class="w"/></span></span><span class="line"><span class="cl"><span class="w"/></span></span><span class="line"><span class="cl"><span class="c1">// 2. Explicit routes — registered race-free before the first request</span><span class="w"/></span></span><span class="line"><span class="cl"><span class="n">Server</span><span class="w"/><span class="n">server</span><span class="w"/><span class="o">=</span><span class="w"/><span class="n">CoreUIServiceJava</span><span class="w"/></span></span><span class="line"><span class="cl"><span class="w"/><span class="p">.</span><span class="na">startServer</span><span class="p">(</span><span class="s">"127.0.0.1"</span><span class="p">,</span><span class="w"/><span class="n">8080</span><span class="p">,</span><span class="w"/><span class="n">List</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">MyView</span><span class="p">.</span><span class="na">class</span><span class="p">,</span><span class="w"/><span class="n">AdminView</span><span class="p">.</span><span class="na">class</span><span class="p">))</span><span class="w"/></span></span><span class="line"><span class="cl"><span class="w"/><span class="p">.</span><span class="na">getOrThrow</span><span class="p">();</span><span class="w"/></span></span><span class="line"><span class="cl"><span class="w"/></span></span><span class="line"><span class="cl"><span class="c1">// 3. Scanned routes — classgraph walks given packages on the runtime classpath</span><span class="w"/></span></span><span class="line"><span class="cl"><span class="n">Server</span><span class="w"/><span class="n">server</span><span class="w"/><span class="o">=</span><span class="w"/><span class="n">CoreUIServiceJava</span><span class="w"/></span></span><span class="line"><span class="cl"><span class="w"/><span class="p">.</span><span class="na">startServer</span><span class="p">(</span><span class="s">"127.0.0.1"</span><span class="p">,</span><span class="w"/><span class="n">8080</span><span class="p">,</span><span class="w"/></span></span><span class="line"><span class="cl"><span class="w"/><span class="n">CoreUIServiceJava</span><span class="p">.</span><span class="na">scanForRoutes</span><span class="p">(</span><span class="s">"com.example.views"</span><span class="p">,</span><span class="w"/><span class="s">"com.example.admin"</span><span class="p">))</span><span class="w"/></span></span><span class="line"><span class="cl"><span class="w"/><span class="p">.</span><span class="na">getOrThrow</span><span class="p">();</span></span></span></code></pre></div></div><p>That&rsquo;s the surface. Everything else is config-as-code.</p><h2 id="first-class-failure-handling">First-class failure handling</h2><p><code>startServer(...)</code> returns a<code>Result&lt;Server, Exception&gt;</code> (from<a href="https://github.com/svenruppert/functional-reactive">functional-reactive</a>),
so a port-bind failure or missing config is a first-class return value
rather than a thrown checked exception:</p><div class="code-wrap"><div class="code-wrap__bar"><span class="code-wrap__lang">java</span><button type="button" class="code-wrap__copy" aria-label="Copy code">Copy</button></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">CoreUIServiceJava</span><span class="p">.</span><span class="na">startServer</span><span class="p">(</span><span class="s">"127.0.0.1"</span><span class="p">,</span><span class="w"/><span class="n">8080</span><span class="p">)</span><span class="w"/></span></span><span class="line"><span class="cl"><span class="w"/><span class="p">.</span><span class="na">peek</span><span class="p">(</span><span class="n">srv</span><span class="w"/><span class="o">-&gt;</span><span class="w"/><span class="n">logger</span><span class="p">().</span><span class="na">info</span><span class="p">(</span><span class="s">"listening on {}"</span><span class="p">,</span><span class="w"/><span class="n">srv</span><span class="p">.</span><span class="na">getURI</span><span class="p">()))</span><span class="w"/></span></span><span class="line"><span class="cl"><span class="w"/><span class="p">.</span><span class="na">peekFailure</span><span class="p">(</span><span class="n">err</span><span class="w"/><span class="o">-&gt;</span><span class="w"/><span class="n">logger</span><span class="p">().</span><span class="na">error</span><span class="p">(</span><span class="s">"startup failed"</span><span class="p">,</span><span class="w"/><span class="n">err</span><span class="p">));</span></span></span></code></pre></div></div><h2 id="fail-fast-bundle-probe">Fail-fast bundle probe</h2><p>The library probes the classpath for<code>META-INF/VAADIN/webapp/index.html</code><strong>before</strong> booting Jetty. If the frontend bundle is missing,<code>startServer(...)</code> short-circuits to a<code>Result.failure(IllegalStateException)</code>
with a message naming the missing path and pointing at the right Maven
goal — you don&rsquo;t have to debug Vaadin&rsquo;s runtime<code>HTTP 500 / Unable to find index.html</code> mystery anymore.</p><h2 id="when-to-use-it">When to use it</h2><p>✅ Internal tooling, ops dashboards, one-shot utilities
✅ Demos where Spring Boot is overkill
✅ Anything you want to ship as a single<code>java -jar</code> binary
✅ Embedded scenarios (Raspberry Pi, IoT gateways)</p><p>❌ Production apps where you already have Spring/Quarkus in the stack — use those
❌ When you need a full WAR deployment lifecycle</p><h2 id="status">Status</h2><p>Active. Updated regularly as Vaadin Flow and Jetty release new versions.
Currently tracking<strong>Vaadin Flow on Jetty 12 (EE11) with Java 26</strong>.</p><p>License is<strong>EUPL-1.2</strong> — copyleft-style, EU-approved equivalent to LGPL.</p>
]]></content:encoded></item><item><title>URL Shortener (Core Java)</title><link>https://svenruppert.com/projects/url-shortener/</link><pubDate>Mon, 01 Dec 2025 00:00:00 +0000</pubDate><author>sven.ruppert@gmail.com (Sven Ruppert)</author><dc:creator>Sven Ruppert</dc:creator><guid isPermaLink="true">https://svenruppert.com/projects/url-shortener/</guid><description>A full URL shortener built step-by-step in Core Java — no frameworks, just the JDK. Documented in a 14-part Advent Calendar series with its own project site.</description><content:encoded>&lt;![CDATA[<p>A pure-JDK URL shortener built as a learning vehicle for the<strong>Advent Calendar 2025</strong> series. Every step is documented in a blog post —
14 parts covering everything from the route registry and persistence layer
to Server-Sent Events for live click tracking and a Vaadin Flow UI.</p><h2 id="what-it-covers">What it covers</h2><ul><li><strong>No Spring, no JPA, no magic.</strong> Pure Core Java + Vaadin Flow.</li><li><strong>Per-step incremental builds.</strong> Each post in the series adds one feature
you can run, break, and learn from in isolation.</li><li><strong>REST + UI in one binary.</strong> A REST endpoint creates short URLs; the
Vaadin Flow admin UI lists clicks live via SSE.</li><li><strong>Production-style concerns covered too</strong> — auth, observability, persistence,
rate-limiting — but always from the JDK side, not framework-side.</li></ul><h2 id="why-a-separate-project-site">Why a separate project site?</h2><p>The shortener has its own domain (<code>url.svenruppert.com</code>) because it doubles
as the live demo — every shortened link runs through this exact codebase.
Eat your own dogfood, etc.</p><p>The build details, architecture decisions and lessons-learned all live on the<a href="/series/">series page</a> on this site.</p>
]]></content:encoded></item><item><title>TypeTool</title><link>https://svenruppert.com/projects/typetool/</link><pubDate>Sun, 15 Jan 2023 00:00:00 +0000</pubDate><author>sven.ruppert@gmail.com (Sven Ruppert)</author><dc:creator>Sven Ruppert</dc:creator><guid isPermaLink="true">https://svenruppert.com/projects/typetool/</guid><description>Open-source library for type-safe generic programming in Java — utilities that lean into the type system instead of fighting it.</description><content:encoded>&lt;![CDATA[<p>A small library of building blocks for<strong>type-safe generic programming</strong> in
Java. Born out of the realisation that most &ldquo;generic&rdquo; Java code drops to<code>Object</code> and casts back — and that this is largely fixable by leaning harder
on the type system rather than around it.</p><h2 id="whats-in-the-box">What&rsquo;s in the box</h2><ul><li><strong>Type witnesses</strong> for runtime generic introspection (working around erasure)</li><li><strong>Builder patterns</strong> that retain compile-time type information</li><li><strong>Composition helpers</strong> for functions, predicates and consumers</li><li><strong>Result / Either</strong> style utilities that compose with<code>Optional</code> and<code>CompletableFuture</code></li></ul><h2 id="when-it-helps">When it helps</h2><ul><li>Library code that needs to expose generic APIs without forcing callers to cast</li><li>Domain models where a<code>Map&lt;String, Object&gt;</code> would technically work but losing
type info costs maintainability</li><li>Glue code between strongly-typed Java and weakly-typed external sources (JSON, configs)</li></ul><p>Documentation, releases and discussion live on<a href="https://github.com/svenruppert">GitHub</a>.</p>
]]></content:encoded></item></channel></rss>