Annotation Interface Subscription


@Target(METHOD) @Retention(RUNTIME) @Documented @Inherited public @interface Subscription
An annotation that can be used to start/resume subscriptions. For example:
 @Subscription(id = "mySubscription")
 void mySubscription(MyDomainEvent event) {
     System.out.println("Received event: " + event);
 }
 

Start Position

You can also specify at which time the subscription should start:

 @Subscription(id = "mySubscription", startAt = StartPosition.BEGINNING_OF_TIME)
 void mySubscription(MyDomainEvent event) { .. }
 
This will first replay all historic events from the beginning of time and then continue subscribing to new events continuously. You can also start at a specific date by using startAtISO8601() or startAtTimeEpochMillis().

Note that the example above will start replay historic events from the beginning of time when the subscription is started the first time. However, once the subscription is resumed, e.g. on application restart, it'll continue from the last received event. If you want a different behavior, configure a different resumeBehavior().

Note also that if MyDomainEvent is a sealed interface/class, then all events implementing this interface/class will be received. If you want to receive only some of the events that implements this interface, see eventTypes().

Metadata

Sometimes it can be useful to get the metadata associated with the received event. For this reason, you can add a parameter to the method annotated with @Subscription of type

invalid reference
org.occurrent.dsl.subscription.blocking.EventMetadata
. For example:
 @Subscription(id = "mySubscription")
 void mySubscription(MyDomainEvent event, EventMetadata metadata) {
   String streamId = metadata.getStreamId();
   long streamVersion = metadata.getStreamVersion();
   Object myCustomValue = metadata.get("MyCustomValue");
   ..
 }
 
  • Element Details

    • id

      String id
      The unique identifier of the subscription.
    • eventTypes

      Class<?>[] eventTypes
      Specify event types to subscribe to. Useful if you want to, for example, subscribe to two events, MyEvent1 and MyEvent2 and you want them to be received as "MyEvent", which may have other subtypes besides MyEvent1 and MyEvent2. For example let's say you have this event hierarchy:
       public sealed interface Event permits MyEvent1, MyEvent2, MyEvent3, .. {
       }
       record MyEvent1(..) implements Event { .. }
       record MyEvent2(..) implements Event { .. }
       record MyEvent3(..) implements Event { .. }
       

      Now lets say that you want to create subscription in which you want to receive either MyEvent1 or MyEvent2. You can then do:

       @Subscription(id="mySubscription", eventTypes = {MyEvent1.class, MyEvent2.class})
       void subscribeToMyEvent1Or2(MyEvent event1Or2) { .. }
       

      This will create a subscription filter that only subscribes to "MyEvent1" or "MyEvent2" and receives it as type "MyEvent".

      Default:
      {}
    • startAt

      Specify the start position to one if the predefined ones in Subscription.StartPosition.
      Default:
      DEFAULT
    • startAtTimeEpochMillis

      long startAtTimeEpochMillis
      Specify the start position as time epoch milliseconds
      Default:
      -1L
    • startAtISO8601

      String startAtISO8601
      Start a subscription from the specified ISO8601 date/time. Valid dates are e.g.
       2024-05-10T10:48:00.838
       2024-05-10T10:48:00.838Z
       2024-05-10T15:30:37.123+02:00
       
      Default:
      ""
    • resumeBehavior

      Specify if the resume behavior for the subscription should differ from when its started. For example, if you specify startAt=BEGINNING_OF_TIME, the resumeBehavior defines how the subscription should behave on restart of the application. By default, if you've specified startAt (or epoch/iso date), then the subscription will be resumed from the last received event when the application is restarted. I.e. first the subscription is caught-up (by reading the events from the beginning of time in this example) and then it'll continue by listening to new events, without_ starting from the beginning of time when the application is restarted. If you always want to start from the beginning of time, you can set the resume behavior to Subscription.ResumeBehavior.SAME_AS_START_AT. This means that the subscription will start the "catching-up" even on application restarts. This can be useful for in-memory projections/read-models where you don't want to maintain any state at all.
      Default:
      DEFAULT
    • startupMode

      Default:
      DEFAULT