Skip to content

State Consumers

Gal Koren edited this page Nov 12, 2020 · 1 revision

In the previous chapter, we saw some basic validators which are simple but with a limited functionality.
Now we advance to the more flexible components: generic validators, enrichers and output generators. All of which are State Consumers.

The CurrentStateConsumer interface presents a method for you to declare which fields you want to fetch from the database before the flow begins. This method is called requiredFields.
These could be fields of any type of entity as long as these entities are all related by foreign keys.

When the component is invoked, it has a method that consumes the requested state and does the work. In this chapter we shall call it doWork which is a placeholder name. For validators, the real method is validate, for enrichers it is enrich, etc...

class MyAdComponent implements CurrentStateConsumer<AdEntity> {

    @Override
    public Stream<? extends EntityField<?, ?>> requiredFields(Collection<? extends EntityField<AdEntity, ?>> fieldsToUpdate, ChangeOperation operator) {
        return Stream.of(
            CampaignEntity.CAMPAIGN_TYPE, 
            AdEntity.URL, 
            AdEntity.HEADLINE);
    }

    @Override
    public void doWork(Collection<? extends EntityChange<AdEntity>> commands, ChangeOperation op, ChangeContext ctx) {
        commands.forEach(cmd -> {

            final String headlineValue = ctx.getFinalEntity(cmd).get(HEADLINE);
            final String urlValue      = ctx.getFinalEntity(cmd).get(URL);

            // some logic with these values
        });

    }
}

CurrentEntityState vs FinalEntityState

The ctx (the ChangeContext) is where we can find the values fetched from DB.
For each command, we get it as follows:

var currentValue = ctx.getEntity(command).get(THE_FIELD);
var finalValue = ctx.getFinalEntity(command).get(THE_FIELD);

We have two variations when looking at the entity state

  • CurrentEntityState - is what we fetched from the DB.
  • FinalEntityState - is the current state after applying the command.

Of course, if our command does not change the THE_FIELD, then the final and current values are the same.
When writing validators, we mostly interested in the final state because we want to assert that the final state is going to be valid.

We can now move on and talk about the really interesting flow components.