Skip to content

Commit 1b0e287

Browse files
committed
Java Vanilla API
1 parent 0806ba9 commit 1b0e287

File tree

3 files changed

+350
-42
lines changed

3 files changed

+350
-42
lines changed

docs/manual/api.html

Lines changed: 212 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -150,19 +150,216 @@
150150
<div class="page-content row">
151151
<div class="small-12 large-9 column" id="docs">
152152
<h1><a href="#words-on-api" name="words-on-api" class="anchor"><span class="anchor-link"></span></a>Words on API</h1>
153-
<p>Thoth is non-blocking by default and rely on vavr but, you can choose if you use it or not. </p>
154-
<h2><a href="#basic-api" name="basic-api" class="anchor"><span class="anchor-link"></span></a>Basic API</h2>
155-
<p>The basic API use vavr for several reasons : * <code>Either</code> : to handle success or error * <code>Option</code> : instead of java Optional to handle missing values * <code>Tuple</code> : to collect data * <code>Tuple0</code> : to return values not handled (like Void but not exactly the same) * <code>List</code> : instead of java List, because the API is better * <code>Lazy</code> : for lazy values </p>
156-
<p>The basic API, is exposed with package <code>fr.maif.eventsourcing</code>. </p>
157-
<h2><a href="#vanilla-api" name="vanilla-api" class="anchor"><span class="anchor-link"></span></a>Vanilla API</h2>
158-
<p>If you don&rsquo;t want to use vavr, there is a vanilla API : * <code>Either</code> -&gt; <code>fr.maif.eventsourcing.Result</code>: a custom type to handle success or error * <code>Option</code> -&gt; <code>Optional</code> * <code>Tuple</code> : internal * <code>Tuple0</code> -&gt; <code>fr.maif.eventsourcing.Unit</code> : a custom type to return values not handled (like Void but not exactly the same) * <code>List</code> : -&gt; <code>java.util.List</code><br/>* <code>Lazy</code> : for lazy values</p>
159-
<p>The package to use is <code>fr.maif.eventsourcing.vanilla</code> : * <code>AggregateStore</code> * <code>CommandHandler</code> * <code>EventHandler</code> * <code>EventProcessor</code> * <code>EventPublisher</code> * <code>Events</code> * <code>EventStore</code> * <code>ProcessingSuccess</code> * <code>Projection</code> * <code>SimpleCommand</code></p>
160-
<h2><a href="#blocking-api" name="blocking-api" class="anchor"><span class="anchor-link"></span></a>Blocking API</h2>
161-
<p>If you don&rsquo;t to handle the non-blocking aspect, you can implement blocking interface, ie the blocking <code>CommandHandler</code>. </p>
162-
<p>The component to use * <code>fr.maif.eventsourcing.blocking.CommandHandler</code> : with standard API (vavr) * <code>fr.maif.eventsourcing.vanilla.blocking.CommandHandler</code> : with vanilla API</p>
163-
<h2><a href="#reactive-api-using-reactor" name="reactive-api-using-reactor" class="anchor"><span class="anchor-link"></span></a>Reactive API using reactor</h2>
164-
<p>There is a reactor API to use <code>Mono</code> instead of <code>CompletionStage</code>. The classes are prefixed with <code>Reactor</code> : * <code>ReactorAggregateStore</code> * <code>ReactorCommandHandler</code> * <code>ReactorEventProcessor</code> * <code>ReactorEventStore</code> * <code>ReactorPostgresKafkaEventProcessorBuilder</code> * <code>ReactorProjection</code> * <code>ReactorTransactionManager</code></p>
165-
<p>At the moment, the reactor API use vavr, there is no vanilla API. </p>
153+
<p>Thoth is non-blocking by default and rely on vavr but, you can choose if you use it or not.</p>
154+
<h2><a href="#fifty-shades-of-apis" name="fifty-shades-of-apis" class="anchor"><span class="anchor-link"></span></a>Fifty shades of APIs</h2>
155+
<h3><a href="#basic-api" name="basic-api" class="anchor"><span class="anchor-link"></span></a>Basic API</h3>
156+
<p>The basic API use vavr for several reasons :</p>
157+
<ul>
158+
<li><code>Either</code> : to handle success or error</li>
159+
<li><code>Option</code> : instead of java Optional to handle missing values</li>
160+
<li><code>Tuple</code> : to collect data</li>
161+
<li><code>Tuple0</code> : to return values not handled (like Void but not exactly the same)</li>
162+
<li><code>List</code> : instead of java List, because the API is better</li>
163+
<li><code>Lazy</code> : for lazy values</li>
164+
</ul>
165+
<p>The basic API, is exposed with package <code>fr.maif.eventsourcing</code>.</p>
166+
<p>With the basic API, you&rsquo;ll have to implement something like :</p>
167+
<pre class="prettyprint"><code class="language-java">public class BankCommandHandler implements CommandHandler&lt;String, Account, BankCommand, BankEvent, List&lt;String&gt;, TxCtx&gt; {
168+
169+
@Override
170+
public CompletionStage&lt;Either&lt;String, Events&lt;BankEvent, List&lt;String&gt;&gt;&gt;&gt; handleCommand(
171+
TxCtx transactionContext,
172+
Option&lt;Account&gt; previousState,
173+
BankCommand command) {
174+
return switch (command) {
175+
case Withdraw withdraw -&gt; this.handleWithdraw(previousState, withdraw);
176+
case Deposit deposit -&gt; this.handleDeposit(previousState, deposit);
177+
case OpenAccount openAccount -&gt; this.handleOpening(openAccount);
178+
case CloseAccount close -&gt; this.handleClosing(previousState, close);
179+
};
180+
}
181+
}
182+
</code></pre>
183+
<h3><a href="#vanilla-api" name="vanilla-api" class="anchor"><span class="anchor-link"></span></a>Vanilla API</h3>
184+
<p>If you don&rsquo;t want to use vavr, there is a vanilla API :</p>
185+
<ul>
186+
<li><code>Either</code> -&gt; <code>fr.maif.eventsourcing.Result</code>: a custom type to handle success or error</li>
187+
<li><code>Option</code> -&gt; <code>Optional</code></li>
188+
<li><code>Tuple</code> : internal</li>
189+
<li><code>Tuple0</code> -&gt; <code>fr.maif.eventsourcing.Unit</code> : a custom type to return values not handled (like Void but not exactly the same)</li>
190+
<li><code>List</code> : -&gt; <code>java.util.List</code></li>
191+
<li><code>Lazy</code> : for lazy values</li>
192+
</ul>
193+
<p>The package to use is <code>fr.maif.eventsourcing.vanilla</code> :</p>
194+
<ul>
195+
<li><code>AggregateStore</code></li>
196+
<li><code>CommandHandler</code></li>
197+
<li><code>EventHandler</code></li>
198+
<li><code>EventProcessor</code></li>
199+
<li><code>EventPublisher</code></li>
200+
<li><code>Events</code></li>
201+
<li><code>EventStore</code></li>
202+
<li><code>ProcessingSuccess</code></li>
203+
<li><code>Projection</code></li>
204+
<li><code>SimpleCommand</code></li>
205+
</ul>
206+
<p>With the vanilla API, you&rsquo;ll have to implement something like :</p>
207+
<pre class="prettyprint"><code class="language-java">public class BankCommandHandler implements CommandHandler&lt;String, Account, BankCommand, BankEvent, List&lt;String&gt;, TxCtx&gt; {
208+
209+
@Override
210+
public CompletionStage&lt;Result&lt;String, Events&lt;BankEvent, List&lt;String&gt;&gt;&gt;&gt; handleCommand(
211+
TxCtx transactionContext,
212+
Optional&lt;Account&gt; previousState,
213+
BankCommand command) {
214+
return switch (command) {
215+
case Withdraw withdraw -&gt; this.handleWithdraw(previousState, withdraw);
216+
case Deposit deposit -&gt; this.handleDeposit(previousState, deposit);
217+
case OpenAccount openAccount -&gt; this.handleOpening(openAccount);
218+
case CloseAccount close -&gt; this.handleClosing(previousState, close);
219+
};
220+
}
221+
}
222+
</code></pre>
223+
<h3><a href="#blocking-api" name="blocking-api" class="anchor"><span class="anchor-link"></span></a>Blocking API</h3>
224+
<p>If you don&rsquo;t to handle the non-blocking aspect, you can implement blocking interface, ie the blocking <code>CommandHandler</code>.</p>
225+
<p>The component to use</p>
226+
<ul>
227+
<li><code>fr.maif.eventsourcing.blocking.CommandHandler</code> : with standard API (vavr)</li>
228+
<li><code>fr.maif.eventsourcing.vanilla.blocking.CommandHandler</code> : with vanilla API</li>
229+
</ul>
230+
<p>With the blocking API, you&rsquo;ll have to implement something like :</p>
231+
<pre class="prettyprint"><code class="language-java">public class BankCommandHandler implements CommandHandler&lt;String, Account, BankCommand, BankEvent, List&lt;String&gt;, TxCtx&gt; {
232+
233+
@Override
234+
public Result&lt;String, Events&lt;BankEvent, List&lt;String&gt;&gt;&gt; handleCommand(
235+
TxCtx transactionContext,
236+
Optional&lt;Account&gt; previousState,
237+
BankCommand command) {
238+
return switch (command) {
239+
case Withdraw withdraw -&gt; this.handleWithdraw(previousState, withdraw);
240+
case Deposit deposit -&gt; this.handleDeposit(previousState, deposit);
241+
case OpenAccount openAccount -&gt; this.handleOpening(openAccount);
242+
case CloseAccount close -&gt; this.handleClosing(previousState, close);
243+
};
244+
}
245+
}
246+
</code></pre>
247+
<h3><a href="#reactive-api-using-reactor" name="reactive-api-using-reactor" class="anchor"><span class="anchor-link"></span></a>Reactive API using reactor</h3>
248+
<p>There is a reactor API to use <code>Mono</code> instead of <code>CompletionStage</code>. The classes are prefixed with <code>Reactor</code> :</p>
249+
<ul>
250+
<li><code>ReactorAggregateStore</code></li>
251+
<li><code>ReactorCommandHandler</code></li>
252+
<li><code>ReactorEventProcessor</code></li>
253+
<li><code>ReactorEventStore</code></li>
254+
<li><code>ReactorPostgresKafkaEventProcessorBuilder</code></li>
255+
<li><code>ReactorProjection</code></li>
256+
<li><code>ReactorTransactionManager</code></li>
257+
</ul>
258+
<p>At the moment, the reactor API use vavr, there is no vanilla API.</p>
259+
<p>With the reactive API, you&rsquo;ll have to implement something like :</p>
260+
<pre class="prettyprint"><code class="language-java">public class BankCommandHandler implements CommandHandler&lt;String, Account, BankCommand, BankEvent, List&lt;String&gt;, TxCtx&gt; {
261+
262+
@Override
263+
public Mono&lt;Either&lt;String, Events&lt;BankEvent, List&lt;String&gt;&gt;&gt;&gt; handleCommand(
264+
TxCtx transactionContext,
265+
Option&lt;Account&gt; previousState,
266+
BankCommand command) {
267+
return switch (command) {
268+
case Withdraw withdraw -&gt; this.handleWithdraw(previousState, withdraw);
269+
case Deposit deposit -&gt; this.handleDeposit(previousState, deposit);
270+
case OpenAccount openAccount -&gt; this.handleOpening(openAccount);
271+
case CloseAccount close -&gt; this.handleClosing(previousState, close);
272+
};
273+
}
274+
}
275+
</code></pre>
276+
<h2><a href="#cheat-sheet" name="cheat-sheet" class="anchor"><span class="anchor-link"></span></a>Cheat sheet</h2>
277+
<h3><a href="#concepts-and-vocabulary" name="concepts-and-vocabulary" class="anchor"><span class="anchor-link"></span></a>Concepts and vocabulary</h3>
278+
<ul>
279+
<li>a command : an action coming from the user that the system has to handle</li>
280+
<li>an event : something that append in the system</li>
281+
<li>a journal : a place where the events are stored</li>
282+
<li>a state or aggregate : the current state, the results of the previous events</li>
283+
<li>a projection : an alternative view of the events, this is a read model</li>
284+
</ul>
285+
<h3><a href="#overview-of-interface-to-implement" name="overview-of-interface-to-implement" class="anchor"><span class="anchor-link"></span></a>Overview of interface to implement</h3>
286+
<p>Here the list of interface you need or, you could implement (and the reason why).</p>
287+
<table>
288+
<thead>
289+
<tr>
290+
<th>Interface </th>
291+
<th>Required </th>
292+
<th>Role </th>
293+
</tr>
294+
</thead>
295+
<tbody>
296+
<tr>
297+
<td><code>State</code> </td>
298+
<td>yes </td>
299+
<td>The current state built from events </td>
300+
</tr>
301+
<tr>
302+
<td><code>Command</code> </td>
303+
<td>yes </td>
304+
<td>The command represents the data that comes in </td>
305+
</tr>
306+
<tr>
307+
<td><code>CommandHandler</code> </td>
308+
<td>yes </td>
309+
<td>The component that handle commands and produce events </td>
310+
</tr>
311+
<tr>
312+
<td><code>EventHandler</code> </td>
313+
<td>yes </td>
314+
<td>The component that handle events and produce a state </td>
315+
</tr>
316+
<tr>
317+
<td><code>Projection</code> </td>
318+
<td>if you need read models </td>
319+
<td>The component that handle events and produce read model </td>
320+
</tr>
321+
<tr>
322+
<td><code>AbstractDefaultAggregateStore</code> </td>
323+
<td>if you need snapshots </td>
324+
<td>The component that load state from events in the journal </td>
325+
</tr>
326+
<tr>
327+
<td><code>EventFormat</code> </td>
328+
<td>no </td>
329+
<td>The component that serialize / deserialize events </td>
330+
</tr>
331+
<tr>
332+
<td><code>JacksonEventFormat</code> </td>
333+
<td>yes (prefered) </td>
334+
<td>The component that serialize / deserialize events to json </td>
335+
</tr>
336+
<tr>
337+
<td><code>SimpleFormat</code> </td>
338+
<td>yes </td>
339+
<td>The component that serialize / deserialize events ignoring errors </td>
340+
</tr>
341+
<tr>
342+
<td><code>JacksonSimpleFormat</code> </td>
343+
<td>yes </td>
344+
<td>The component that serialize / deserialize events to json ignoring errors </td>
345+
</tr>
346+
<tr>
347+
<td><code>EventPublisher</code> </td>
348+
<td>no (only if don&rsquo;t use Kafka) </td>
349+
<td>The component that publish events </td>
350+
</tr>
351+
<tr>
352+
<td><code>EventStore</code> </td>
353+
<td>no (only if don&rsquo;t use PG) </td>
354+
<td>The component that store and query events </td>
355+
</tr>
356+
<tr>
357+
<td><code>EventProcessor</code> </td>
358+
<td>no </td>
359+
<td>The component orchestrate all the magic </td>
360+
</tr>
361+
</tbody>
362+
</table>
166363
<div class="nav-next">
167364
<p><strong>Next:</strong> <a href="technical-considerations.html">Technical considerations</a></p>
168365
</div>
@@ -175,10 +372,8 @@ <h2><a href="#reactive-api-using-reactor" name="reactive-api-using-reactor" clas
175372
<ul>
176373
<li><a href="api.html#words-on-api" class="header">Words on API</a>
177374
<ul>
178-
<li><a href="api.html#basic-api" class="header">Basic API</a></li>
179-
<li><a href="api.html#vanilla-api" class="header">Vanilla API</a></li>
180-
<li><a href="api.html#blocking-api" class="header">Blocking API</a></li>
181-
<li><a href="api.html#reactive-api-using-reactor" class="header">Reactive API using reactor</a></li>
375+
<li><a href="api.html#fifty-shades-of-apis" class="header">Fifty shades of APIs</a></li>
376+
<li><a href="api.html#cheat-sheet" class="header">Cheat sheet</a></li>
182377
</ul></li>
183378
</ul>
184379
</div>

docs/manual/index.html

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,8 @@ <h2><a href="#installation" name="installation" class="anchor"><span class="anch
234234
</ul></li>
235235
<li><a href="api.html" class="page">Words on API</a>
236236
<ul>
237-
<li><a href="api.html#basic-api" class="header">Basic API</a></li>
238-
<li><a href="api.html#vanilla-api" class="header">Vanilla API</a></li>
239-
<li><a href="api.html#blocking-api" class="header">Blocking API</a></li>
240-
<li><a href="api.html#reactive-api-using-reactor" class="header">Reactive API using reactor</a></li>
237+
<li><a href="api.html#fifty-shades-of-apis" class="header">Fifty shades of APIs</a></li>
238+
<li><a href="api.html#cheat-sheet" class="header">Cheat sheet</a></li>
241239
</ul></li>
242240
<li><a href="technical-considerations.html" class="page">Technical considerations</a></li>
243241
<li><a href="banking.html" class="page">In memory example</a>

0 commit comments

Comments
 (0)