Created
September 10, 2018 12:22
-
-
Save erichonorez/d56ba0f2e33952045bd3274638311475 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.demo; | |
import lombok.Value; | |
/** | |
* This example implements event sourcing using with versioning. It uses | |
* | |
* Each version has its own event interface (e.g. {@link EventV1} and {@link EventV2}) that extends the {@link Event}. | |
* | |
* In order to apply {@link Event} on a {@link State} the visitor pattern is used. Each version also define its own visitor interface (e.g. {@link VisitorV1} and {@link VisitorV2}). All visitors are aggregated with the {@link Visitor} interface. | |
* | |
* Each versioned visitor has one method for each {@link Event} of the same version. | |
* | |
* For 2 versioned events this solution has : | |
* <ol> | |
* <li>12 types</li> | |
* <li>2 types for the state (not important for the solution)</li> | |
* </ol> | |
* | |
* The main drawback is that it is a heavy solution. Lot of code and mutable state (if we want to keep the visitor reusable)! | |
* The main advantage is that there is a compile time check when creating new event (impossible to miss something). | |
*/ | |
public class EventSourcingV2 { | |
interface Event { | |
String getLoanApplicationReference(); | |
void accept(Visitor visitor); | |
default String getVersion() { | |
return "V1"; | |
} | |
} | |
interface EventV1 extends Event { | |
@Override | |
default String getVersion() { | |
return "V1"; | |
} | |
} | |
@Value | |
static class CreatedV1 implements EventV1 { | |
private String loanApplicationReference; | |
@Override | |
public void accept(Visitor visitor) { | |
visitor.visit(this); | |
} | |
} | |
@Value | |
static class GrantedV1 implements EventV1 { | |
private String loanApplicationReference; | |
@Override | |
public void accept(Visitor visitor) { | |
visitor.visit(this); | |
} | |
} | |
interface EventV2 extends Event { | |
@Override | |
default String getVersion() { | |
return "V2"; | |
} | |
} | |
@Value | |
static class CreatedV2 implements EventV2 { | |
private String loanApplicationReference; | |
@Override | |
public void accept(Visitor visitor) { | |
visitor.visit(this); | |
} | |
} | |
@Value | |
static class GrantedV2 implements EventV2 { | |
private String loanApplicationReference; | |
@Override | |
public void accept(Visitor visitor) { | |
visitor.visit(this); | |
} | |
} | |
interface VisitorV1 { | |
void visit(CreatedV1 e); | |
void visit(GrantedV1 e); | |
void visitAll(EventV1 eventV1); | |
} | |
interface VisitorV2 { | |
void visit(CreatedV2 e); | |
void visit(GrantedV2 e); | |
void visitAll(EventV2 eventV2); | |
} | |
interface Visitor extends VisitorV1, VisitorV2 { | |
} | |
interface State { | |
boolean isGranted(); | |
} | |
@Value | |
static class Data implements State { | |
boolean isGranted; | |
} | |
static void apply(Event e, State s) { | |
e.accept(new Visitor() { | |
private VisitorImplV1 v1 = new EventSourcingV2.VisitorImplV1(); | |
private VisitorImplV2 v2 = new EventSourcingV2.VisitorImplV2(); | |
@Override | |
public void visit(CreatedV1 e) { | |
v1.visit(e); | |
} | |
@Override | |
public void visit(GrantedV1 e) { | |
v1.visit(e); | |
} | |
@Override | |
public void visitAll(EventV1 e) { | |
v1.visitAll(e); | |
} | |
@Override | |
public void visit(CreatedV2 e) { | |
v2.visit(e); | |
} | |
@Override | |
public void visit(GrantedV2 e) { | |
v2.visit(e); | |
} | |
@Override | |
public void visitAll(EventV2 e) { | |
v2.visitAll(e); | |
} | |
}); | |
} | |
static class VisitorImplV1 implements VisitorV1 { | |
@Override | |
public void visit(CreatedV1 e) { | |
} | |
@Override | |
public void visit(GrantedV1 e) { | |
} | |
@Override | |
public void visitAll(EventV1 eventV1) { | |
} | |
} | |
static class VisitorImplV2 implements VisitorV2 { | |
@Override | |
public void visit(CreatedV2 e) { | |
} | |
@Override | |
public void visit(GrantedV2 e) { | |
} | |
@Override | |
public void visitAll(EventV2 eventV2) { | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment