<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>DDI – Dynamic Dependency Injection</title><link>https://ddi.svenruppert.com/</link><description>Recent content on DDI – Dynamic Dependency Injection</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Mon, 18 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://ddi.svenruppert.com/index.xml" rel="self" type="application/rss+xml"/><item><title>Getting Started</title><link>https://ddi.svenruppert.com/docs/getting-started/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://ddi.svenruppert.com/docs/getting-started/</guid><description>&lt;h2 id="1-add-the-dependency"&gt;1. Add the dependency&lt;/h2&gt;&#10;&lt;p&gt;DDI is published to Maven Central. Add the artifact to your build:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.svenruppert&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;ddi&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;06.01.01&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Gradle (Kotlin DSL):&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-kotlin" data-lang="kotlin"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;com.svenruppert:ddi:06.01.01&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;DDI targets &lt;strong&gt;JDK 21+&lt;/strong&gt;. The 1.0.x line targets JDK 8 if you need it.&lt;/p&gt;&#10;&lt;h2 id="2-bootstrap-the-container"&gt;2. Bootstrap the container&lt;/h2&gt;&#10;&lt;p&gt;DDI scans the classpath for implementations, producers and resolvers. Tell it&#10;which package(s) to scan — typically your application&amp;rsquo;s root:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.svenruppert.ddi.DI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;activatePackages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;com.example&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;activateDI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s the whole bootstrap. No XML, no annotation processor, no container&#10;configuration. Repeated calls to &lt;code&gt;activatePackages&lt;/code&gt; add more packages to the&#10;scan.&lt;/p&gt;</description></item><item><title>Resolution Rules</title><link>https://ddi.svenruppert.com/docs/resolution-rules/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://ddi.svenruppert.com/docs/resolution-rules/</guid><description>&lt;p&gt;When DDI encounters an &lt;code&gt;@Inject&lt;/code&gt;-annotated field, it walks a deterministic&#10;decision tree to pick &lt;strong&gt;one&lt;/strong&gt; class or producer to instantiate. This page is&#10;the exact rule set, lifted from the project README and grouped by the kind of&#10;target you injected.&lt;/p&gt;&#10;&lt;p&gt;The rules use four building blocks:&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Concept&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;What it is&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Impl&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;A class implementing the injected interface.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Producer&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;A method or class annotated &lt;code&gt;@Produces&lt;/code&gt;, returning the interface or an impl.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;ClassResolver&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;A &lt;code&gt;ClassResolver&amp;lt;T&amp;gt;&lt;/code&gt; annotated &lt;code&gt;@ResponsibleFor(T.class)&lt;/code&gt; — runs on every lookup and returns the class to use.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;ProducerResolver&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;A resolver that picks between multiple producers for the same impl.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="when-you-inject-an-interface"&gt;When you inject an interface&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@Inject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Setup&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Resolution&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;0 Impl&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Exception&lt;/strong&gt; — nothing to inject.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;0 Impl, 1 Producer for the interface&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;The producer is used.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1 Impl, 0 Producer&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;The single impl is used.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1 Impl, 1 Producer for the impl&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;The producer for the impl is used.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1 Impl, &lt;em&gt;n&lt;/em&gt; Producers for the impl&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Exception&lt;/strong&gt; — ambiguous.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1 Impl, 1 Producer for the interface&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;The producer for the interface is used.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1 Impl, &lt;em&gt;n&lt;/em&gt; Producers for the interface&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Exception&lt;/strong&gt; — ambiguous.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1 Impl, 1 Producer for the interface + 1 Producer for the impl&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Exception&lt;/strong&gt; — ambiguous.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;em&gt;n&lt;/em&gt; Impls, no resolver&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Exception&lt;/strong&gt; — ambiguous.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;em&gt;n&lt;/em&gt; Impls, 1 responsible ClassResolver&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;The class returned by the resolver is used.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;em&gt;n&lt;/em&gt; Impls, 1 Producer for the interface&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;The producer for the interface is used.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;em&gt;n&lt;/em&gt; Impls, 1–&lt;em&gt;n&lt;/em&gt; Producers for an impl&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Exception&lt;/strong&gt; — ambiguous.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;em&gt;n&lt;/em&gt; Impls, 1 ClassResolver + 1 Producer for the interface&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;The producer for the interface is used.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;em&gt;n&lt;/em&gt; Impls, 1 ClassResolver + 1–&lt;em&gt;n&lt;/em&gt; Producers for impls&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;The class returned by the resolver is used, or its matching producer if one exists.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;em&gt;n&lt;/em&gt; Impls, &lt;em&gt;n&lt;/em&gt; responsible ClassResolvers&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Exception&lt;/strong&gt; — conflicting responsibility.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1 Impl, &lt;em&gt;n&lt;/em&gt; Producers for impl, 1 ProducerResolver&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;The producer selected by the ProducerResolver is used.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;em&gt;n&lt;/em&gt; Impls, 1 ClassResolver, 0–&lt;em&gt;n&lt;/em&gt; Producers per impl, 1 ProducerResolver per impl&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;The producer selected by the ProducerResolver is used, for the impl selected by the ClassResolver.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="when-you-inject-an-implementation-directly"&gt;When you inject an implementation directly&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@Inject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FriendlyGreeter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;greeter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Setup&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Resolution&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Impl, no producer&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;The impl is used.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Impl, 1 producer&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;The producer is used.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="reading-the-table"&gt;Reading the table&lt;/h2&gt;&#10;&lt;p&gt;The two principles behind every row:&lt;/p&gt;</description></item><item><title>ClassResolver</title><link>https://ddi.svenruppert.com/docs/class-resolvers/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://ddi.svenruppert.com/docs/class-resolvers/</guid><description>&lt;blockquote&gt;&#10;&lt;p&gt;&lt;strong&gt;Work in progress.&lt;/strong&gt; This page is the canonical reference for the&#10;&lt;code&gt;ClassResolver&lt;/code&gt; API. Full content lands with the SaaS-policy tutorial series&#10;(see the &lt;a href="https://ddi.svenruppert.com/roadmap/"&gt;roadmap&lt;/a&gt;).&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;h2 id="the-contract"&gt;The contract&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.svenruppert.ddi.implresolver&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ClassResolver&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;extends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;interf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Annotate the resolver with &lt;code&gt;@ResponsibleFor(Service.class)&lt;/code&gt; so DDI knows which&#10;interface it claims. &lt;strong&gt;One&lt;/strong&gt; &lt;code&gt;ClassResolver&lt;/code&gt; per interface — competing claims&#10;are a hard error.&lt;/p&gt;&#10;&lt;h2 id="minimum-viable-example"&gt;Minimum viable example&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@ResponsibleFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ServicePolicy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;implements&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ClassResolver&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;extends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SecurityContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;current&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="na"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ENTERPRISE&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PremiumService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BasicService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;DDI calls &lt;code&gt;resolve(...)&lt;/code&gt; &lt;strong&gt;every time&lt;/strong&gt; the field is injected. That&amp;rsquo;s the&#10;defining property of the library — and the reason classic DI containers can&amp;rsquo;t&#10;do this cleanly.&lt;/p&gt;</description></item><item><title>Producers</title><link>https://ddi.svenruppert.com/docs/producers/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://ddi.svenruppert.com/docs/producers/</guid><description>&lt;blockquote&gt;&#10;&lt;p&gt;&lt;strong&gt;Work in progress.&lt;/strong&gt; This page is the canonical reference for &lt;code&gt;Producer&amp;lt;T&amp;gt;&lt;/code&gt;&#10;and &lt;code&gt;@Produces&lt;/code&gt;. Full content lands alongside the producer-vs-resolver&#10;tutorial (see the &lt;a href="https://ddi.svenruppert.com/roadmap/"&gt;roadmap&lt;/a&gt;).&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;h2 id="when-you-need-a-producer"&gt;When you need a producer&lt;/h2&gt;&#10;&lt;p&gt;Direct class instantiation works for the common case: DDI calls the no-arg&#10;constructor, injects fields, runs &lt;code&gt;@PostConstruct&lt;/code&gt;, done. You need a&#10;&lt;strong&gt;producer&lt;/strong&gt; when:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;The instance requires constructor arguments DDI can&amp;rsquo;t supply.&lt;/li&gt;&#10;&lt;li&gt;The factory call has side effects you want explicit (opening a connection, reading config).&lt;/li&gt;&#10;&lt;li&gt;The decision &lt;em&gt;which subtype&lt;/em&gt; to instantiate is data-driven and you don&amp;rsquo;t want a &lt;code&gt;ClassResolver&lt;/code&gt; for it.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="the-shape"&gt;The shape&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.svenruppert.ddi.producer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Producer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Annotate the producer with &lt;code&gt;@Produces&lt;/code&gt; to advertise it to the container:&lt;/p&gt;</description></item><item><title>Scopes</title><link>https://ddi.svenruppert.com/docs/scopes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://ddi.svenruppert.com/docs/scopes/</guid><description>&lt;blockquote&gt;&#10;&lt;p&gt;&lt;strong&gt;Work in progress.&lt;/strong&gt; This page is the canonical reference for the scope API.&#10;Full content lands alongside the &lt;em&gt;Writing a custom scope&lt;/em&gt; tutorial (see the&#10;&lt;a href="https://ddi.svenruppert.com/roadmap/"&gt;roadmap&lt;/a&gt;).&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;h2 id="the-built-in-scope"&gt;The built-in scope&lt;/h2&gt;&#10;&lt;p&gt;Out of the box DDI ships a single scope:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;code&gt;JVMSingletonInjectionScope&lt;/code&gt;&lt;/strong&gt; — one instance per class, for the lifetime&#10;of the JVM. The simplest possible model, and a good default for stateless&#10;services.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Register a class with the singleton scope explicitly:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;DI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;registerClassForScope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;jvm-singleton&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="writing-your-own-scope"&gt;Writing your own scope&lt;/h2&gt;&#10;&lt;p&gt;The scope interface (&lt;code&gt;InjectionScope&lt;/code&gt;) lets you implement other lifetimes —&#10;per-request, per-tenant, per-session, per-virtual-thread. The mechanism is&#10;intentionally small. Documentation and a worked example are on the&#10;&lt;a href="https://ddi.svenruppert.com/roadmap/"&gt;roadmap&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Compatibility</title><link>https://ddi.svenruppert.com/docs/compatibility/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://ddi.svenruppert.com/docs/compatibility/</guid><description>&lt;h2 id="jdk-matrix"&gt;JDK matrix&lt;/h2&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;DDI version line&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;JDK baseline&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Status&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;06.x (current)&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;JDK 21 LTS&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Active development&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;05.x&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;JDK 21 LTS&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Maintenance only&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;04.x&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;JDK 8 source / JDK 11+ build&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;End-of-life&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1.0.x&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;JDK 8&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Frozen — for legacy projects&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Newer JDKs (22, 23, …) are tested but not officially declared &amp;ldquo;supported&amp;rdquo; until&#10;they have reached at least one quarterly maintenance release.&lt;/p&gt;&#10;&lt;h2 id="runtime-environments"&gt;Runtime environments&lt;/h2&gt;&#10;&lt;p&gt;DDI is plain Java — there is no servlet, no container, no agent. It works&#10;wherever the JDK works:&lt;/p&gt;</description></item><item><title>DDI 06.01.01 — standalone documentation site</title><link>https://ddi.svenruppert.com/blog/release-06-01-01/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://ddi.svenruppert.com/blog/release-06-01-01/</guid><description>&lt;p&gt;DDI has lived for over a decade inside the umbrella &lt;strong&gt;dependencies&lt;/strong&gt; repository.&#10;That worked while the library was an internal helper. It stopped working once&#10;the dynamic-resolution story — &lt;em&gt;the&lt;/em&gt; reason DDI exists — got buried under the&#10;parent project&amp;rsquo;s release notes for everything else.&lt;/p&gt;&#10;&lt;p&gt;So: this site.&lt;/p&gt;&#10;&lt;h2 id="whats-new-in-060101"&gt;What&amp;rsquo;s new in 06.01.01&lt;/h2&gt;&#10;&lt;p&gt;This is primarily a documentation release. The library API did not change in a&#10;breaking way; the source still lives in&#10;[&lt;code&gt;svenruppert/dependencies&lt;/code&gt;]({{ .Site.Params.github }}) as the&#10;&lt;code&gt;ddi&lt;/code&gt; module.&lt;/p&gt;</description></item></channel></rss>