How does the configuration of TokenStore work?

Hello,

Actually I wanted to choose the title “Java question: How does the configuration with EventProcessingConfigurer#registerTokenStore work?” but when clicking on “+ Create Topic” the forum software just spawned a popup that reads “Title seems unclear, one or two words is very long?”

I’m sorry for asking a question that is rather on Java but I didn’t receive an answer on stackoverflow. Yet it is of course Axon related because it’s about understanding an idiom that is used in order to configure it. I come from Ruby and I am still quite new to Java and I know from Ruby that some idioms are not obvious on the first glance and probably hard to understand for people who are new to Ruby.

So could you please explain to me how following code works ?

public class AxonConfig { 
    // ...
    public void registerTokenStore(EventProcessingConfigurer processingConfigurer) {
        TokenStore tokenStore = JpaTokenStore.builder()
                                             // …
                                             .build();
    
        processingConfigurer.registerTokenStore(config -> tokenStore);
    }
}

I have found out about the idiom of functional interfaces with a single method and lambda expressions. Like in the case of EventProcessingConfigurer.PooledStreamingProcessorConfiguration

But this one is different.

registerTokenStore()

is an interface method. Check. The argument is a lambda-expression. Check. But it has a proper argument list, where the return type of the single parameter is a Function placeholder Object (what do you call it in Java?) and the parameter-name is tokenStore, so the method registerTokenStore() is a functional.

I don’t understand what is the config object that is the single input-parameter of the lambda expression,i.e. what object is passed for this argument and how? Then how is this configuration object which is obviously passed as argument connected to the tokenStore object that it (the lambda expression) returns, and why don’t you pass the tokenStore object directly to the EventProcessingConfigurer ?

And where does finally happen something with the lambda-expression object that you pass as argument?

Thanks !

Yours sincerely,
uberSpotz

Hi uberSpotz.

We just had our conference, so that’s probably why the Stackoverflow question was not answered yet. The fiction takes an instance of the Configuration, which might, or might not be used.

For example depending on the eventbus used, you might want to have a different Tokenstore. Or use some property from the Configuration, to pass to the Tokenstore builder. It’s mostly there to have that flexibility, in most cases you probably won’t need to use it. But as it’s need to match the type signature, you need to supply a lambda that takes the configuration.

I hope I explained it well enough, feel free to ask follow up questions. It can be quite complex even for people used to Java.

Dear @Gerard Klijs,

thank you very much for your really kind answer ! This is quite another tone than on stackoverflow I must say. It can be quite rude there.

I hope you had a fun time at the convention and many new ideas to improve Axon !

Amsterdam is not that far, maybe I will be there next time? :slight_smile:

Side-question: Is there a way to reply and quote the post you are referencing?

To your answer:

I think we talked passed each other. Maybe I didn’t/couldn’t formulate my question precise enough.

But my problem is not the first part of the configuration example, but it is the latter part:

processingConfigurer.registerTokenStore(config -> tokenStore);

So the method registerTokenStore takes an anonymous function, i.e. a Function<Configuration, TokenStore> and binds this parameter to the symbol tokenStore in the function definition

Well, I could try again to list things I don’t understand, but this is probably asked wrong for exactly that reason that I don’t understand the idiom used here. Then I don’t know what the further inner workings are which may nonetheless be the reason why the authors chose to communicate that built tokenstore instance to the EventProcessingConfigurer as “return value” of a lambda-expression.

Sincerely yours

It depends, when used with Spring Boot for example, you probably don’t even need to configure the Tokenstore this way, but either a Tokenstore will be created and configured for you, or it will pick a Tokenstore bean you defined if you did so.

As the mongo extension hasn’t got any auto configuration this moment it might be a nice example. Here a new Tokenstore is created, and configured.

I hope this was helpful, Stackoverflow can indeed be less pleasant.

Dear Gerard,

thank you for your answer, pointing me at possibly another lambda-expression idiom.

The problem I think is that I could not enter the Thread Title that I originally wanted to because I received this error popup.

My question is really not how to configure a TokenStore in particular but my question is on one of a few probably “Java-Idioms” that the Axon library uses in various contexts but which I don’t understand. Though I have to understand these idioms that are used for configuration because otherwise… well… I can’t move on learning things because I don’t understand the used idioms in the first place.

If I don’t understand these Idioms that involve passing lambda-expressions for a reason that I don’t understand in this context, that is, I don’t understand this particular Idiom, then it consequentially does not matter “what?” I want to configure. Then I can’t configure anything.

Hence my concern would be that someone would be so kind to explain to me “what happens” in the original example I posted in the opening post.

Let’s recapitulate.

in the registerTokenStore() bean the example builds a JpaTokenStore through the builder and assigns it to the symbol tokenStore

This is absolutely unproblematic.

The problem is the expression that follows and concerns the EventProcessingConfigurer object.

Here comes the idiom into play which I don’t understand. To be exact, the EventProcessingConfigurer#registerTokenStore method.

Usage:

processingConfigurer.registerTokenStore(config -> tokenStore);

The question: Please explain this idiom to me ! What is this idiom doing? Why do I pass the lambda expression to an Interface method and more exactly to a parameter named tokenStore as tells us the source code with the type Function<Configuration, TokenStore> ? Where is the argument for the config parameter of the lambda-expression passed into it? It is a closure obviously that saves the above created tokenStore object and gives that back, no matter actually what you pass in for the config parameter.

I don’t know how I could ask better. I’m sorry.

In the example that you linked also contains an Idiom that encompasses passing in an anonymous function / closure (lambda expression) instead of directly passing the object. But im not familiar enough with kotlin. This would only make things more complicated at this moment.

Thanks.

Yours sincerely,
Maximilian

Hello,

I don’t know if the example from the documentation isn’t just something to be substituted by the user or by Spring dependency injection because you can’t call methods on a Java Interface, can you?

And the class EventProcessingModule is an implementation of that Interface.

here is the implementation code of the same method: Github AxonFramework / EventProcessingModule.java

    @Override
    public EventProcessingConfigurer registerTokenStore(Function<Configuration, TokenStore> tokenStore) {
        this.defaultTokenStore.update(tokenStore);
        return this;
    }

It makes more sense that this is what is actually invoked when you invoke

processingConfigurer.registerTokenStore(config -> tokenStore);

like in the documentation example which is not defined as EventProcessingConfigurer which isn’t more than an Interface.

So am I right that instead of the Interface there actually occurs dependenccy injection?

Or is it a special Java Idiom after all to pass anonymous functions (lambda-expressions) to interface methods?

Yours sincerely
überSpotz

You can actually call methods from an interface, but only on an instance of a class that implements the interface.

I’m not sure how to help further. Using lambda’s for configuration is a way to give control to when the function is invoked to the EventProcessingModule. Also, it allows using the Configuration as input, which might be useful in some cases.