Hazelcast instances created by Spring Boot do not have the SpringManagedContext set. SpringManagedContext is used to inject dependencies into for example EntryProcessors executed by Hazelcast.

The SpringManagedContext is created when HazelcastInstance bean is created via Hazelcast namespace support, but obviously the XML configuration is no longer the prefer way to configure Spring

I would be happy to send a pull request if there is an interest to add this to Spring Boot.

Comment From: snicoll

@jerrinot the documentation you've referenced is only focusing in XML, have I missed the part that explains about the context? If you feel that would be a worthwhile addition to the existing support, feel free to submit a PR and we can take it from there.

Comment From: jerrinot

Hello @snicoll

I pushed a demo project to https://github.com/jerrinot/springdemo2

There are 2 Maven modules: 1. xmlconfig - showing how @SpringAware is supposed to work. SpringdemoApplicationTests submits a Callable into Hazelcast and it gets dependencies injected. This works thanks to the Spring-specific XML namespace we have in the Hazelcast-Spring integration project. 2. javaconfig - showing this same does not work when Java config is used and Spring Boot automatically creates HazelcastInstance

In the SpringdemoApplication you can uncomment the createConfigWithSpringManagedContext() to make this working again. However in this case the Hazelcast yaml config is ignored + it does not sound as The Spring Boot Way to me.

I believe Spring Boot should inject the SpringManagedContext into Hazelcast Config automatically (when available). This sounds like a reasonable automatic behaviour to me and as a Spring Boot user I would expect it. WDYT? I can send a Pull Requests draft introducing this behaviour.

Comment From: snicoll

Thanks for the demo project.

However in this case the Hazelcast yaml config is ignored + it does not sound as The Spring Boot Way to me.

I think it is. You are creating a Config object yourself, taking control over the configuration. It makes sense that Spring Boot backs-off.

I believe Spring Boot should inject the SpringManagedContext into Hazelcast Config automatically

I don't think Spring Boot should alter an existing Config object (again, if you're creating it yourself, you want to be in control). However, if we auto-configure Hazelcast, I agree that this is a sensible thing to do.

@jerrinot the documentation you've referenced is only focusing in XML, have I missed the part that explains about the context?

The sample now explains what is required, thanks. The point I was trying to make here is that I didn't find that explanation in the Hazelcast documentation. Perhaps this is something worth improving if I haven't missed it?

Can you please confirm you're willing to submit a PR about this?

Comment From: jerrinot

I think it is. You are creating a Config object yourself, taking control over the configuration. It makes sense that Spring Boot backs-off.

That's a fair point. If a user created an instance of Config then we should probably not mutate it automatically. Is there any way how we could simplify this for users who wish the Spring context to be injected? (after an explicit opt-in) I am not really a Spring expert, but I can imagine a post-processing based on annotation? Something like:

@Bean
@SpringAwareConfig
public Config hazelcastConfig() {
  return new Config();
}

Would :point_up: make sense to you? This way we wouldn't bother users with internal details of the Spring - Hazelcast integration.

The sample now explains what is required, thanks. The point I was trying to make here is that I didn't find that explanation in the Hazelcast documentation. Perhaps this is something worth improving if I haven't missed it?

Yes, I do agree the Spring part of Hazelcast Reference Manual deserves a refresh. We should de-emphasize/remove the XML style, make it Java config first and perhaps link to Spring Boot manual too. cc @Serdaro

Can you please confirm you're willing to submit a PR about this?

Yes, I will send a pull request so the SpringManagedContext is injected when Spring Boot creates Config object instance.

One possible issue could be that not all Spring Boot - Hazelcast users have SpringManagedContext on a classpath. It's not part of Hazelcast Core JAR, it's in Hazelcast Spring JAR. So this logic has to be guarded by a condition checking an existence of the SpringManagedContext class. I am not sure what's the Spring Boot idiomatic way for doing this. @ConditionalOnClass does not seem to be straightforward in this case. Anyway, I will give it a try, once there is a PR it will make it easier for you to guide me further.

Once again thanks for your help and happy new year!

Comment From: jerrinot

I've been toying with the @SpringAwareConfig opt-in idea.

@Bean
@SpringAwareConfig
public Config hazelcastConfig() {
  return new Config();
}

It's working, but the implementation feels funky. I suspect I am missing something obvious, perhaps a much simpler way to do it.

Comment From: snicoll

@jerrinot I am not keen to add such feature. That's way too much code for something as simple as creating the SpringManagedContext. If you decide to create the Config object yourself, then a one liner is reasonable and an extra annotation isn't worth it. For that to be valid though, the Hazelcast documentation should clearly indicate to users how they can enable that feature.

Comment From: jerrinot

I was hoping there could be a simpler way to achieve this. It sounds like a simple bean processing, except I need(?) to have an access to BeanDefinition. Which regular BeanPostProcessor does not have :(

Anyway, I can live without this. The more important thing is actually including the Context when HazelcastInstance is created by Spring Boot.

Comment From: jerrinot

Hi @snicoll, I pushed an experiment.

It's not finished, it currently works only when you explicitly specify Hazelcast configuration file, but it shows the idea. Another possibility is to turn HazelcastInstanceFactory into a proper bean. So then I could inject customizer directly into it. WDYT?

Comment From: snicoll

Thanks for the experiment. From a quick glance, I don't see why a HazelcastConfigCustomizer is necessary. Perhaps you could apply the code change in HazelcastInstanceFactory directly?

Comment From: nosan

@snicoll @jerrinot

I think that it would be great in general to have a way to customize Hazelcast's Client/Server configs before the instance creation. At the moment there is no way to do this except creating your own config.

I have created a branch (https://github.com/nosan/spring-boot/commit/004f1a328ebf1eeb21b6c841302d175bdefb20f6) that provides such functionality, so for that particular issue there would be a possibility to create your own customizer and set the managedContext:



@Configuration(proxyBeanMethods = false)
static class HazelcastConfiguration {

    @Bean
    HazelcastConfigCustomizer hazelcastConfigCustomizer(ApplicationContext applicationContext) {
        return (config) -> {
            SpringManagedContext managedContext = new SpringManagedContext();
            managedContext.setApplicationContext(applicationContext);
            config.setManagedContext(managedContext);
        };
    }

}

If it is something that makes sense, I am ready to create PR.

Please let me know whether it works for you.

Comment From: snicoll

I think that it would be great in general to have a way to customize Hazelcast's Client/Server configs before the instance creation. At the moment there is no way to do this except creating your own config.

I believe this is an unrelated change/request. Wether we implement this particular feature with a customizer or a call inside the factory is entirely a technical detail. Creating a high-level customizer however is not and I've already indicated above that I am not keen to mix the two.

If you believe adding such customizer would be an improvement to the auto-configuration, please create an issue for further discussion. Or you can submit a PR if you have the code already. Please note that I am not yet convinced applying "blindly" a customizer on either a client or server config makes sense. Yet, they share the same Config type which makes this feature a bit unusual and the main reason why I am holding back.

Comment From: snicoll

In the meantime we got a PR for the customizer (#19669) but I still don't have concrete use cases for which this would be beneficial to users. I've flagged it for team attention, feel free to add feedback there.

Comment From: snicoll

I've spent a bit of time to look at this one and it turns out adding those customizers would have been interesting as a more general feature. However we can't really implement this at this point without some change in Hazelcast.

We want to apply that customization when Spring Boot creates the Config or ClientConfig object as we shouldn't alter a Config that the user has provided. There are two branches for the former case:

  • The user provided the location of a configuration file and we load that. All is good
  • There is no location provided, in which case an algorithm runs to load a configuration file according to default locations.

For this particular case, we have no control over the config object and we can't modify it before the HazelcastInstance is created, see this code (that's Hazelcast 4 but the same applies to the version we're using).

TL;DR for the most obvious case, we have no way to customize the Config object and therefore set the ManagementContext in a consistent way. Not without copy/pasting code at least and I am not keen to do that.

If Hazelcast provides such a hook-point, we can reconsider introducing this feature.

Comment From: snicoll

I've created https://github.com/hazelcast/hazelcast/issues/16809

Comment From: gurbuzali

Just as a note, for Hazelcast Jet we inject SpringManagedContext automatically if the configuration is created via a configuration file rather than a bean.

https://github.com/hazelcast/hazelcast-jet-contrib/blob/master/hazelcast-jet-spring-boot-starter/src/main/java/com/hazelcast/jet/contrib/autoconfigure/HazelcastJetServerConfiguration.java#L101

Comment From: snicoll

@gurbuzali thanks but I don't see how that is relevant here. What have I missed?

Comment From: gurbuzali

What I mean is this could be the way to go for Hazelcast IMDG auto configuration also. If user is not providing their own Config object as a bean but relying a configuration file then spring-boot can inject the SpringManagedContext.

I think this is a sensible default because SpringManagedContext cannot be configured using a configuration file thus forces users to create their own Config object If they want to configure so.

Comment From: snicoll

If user is not providing their own Config object as a bean but relying a configuration file then spring-boot can inject the SpringManagedContext.

Yes, thank you. I said the exact same thing in this issue already.

Comment From: leszko

@snicoll FYI We implemented the Config.load() here: https://github.com/hazelcast/hazelcast/pull/16864.

I'll ping you as soon as it's released.

Comment From: snicoll

I've seen that, thank you @leszko. For the record, we can't use that option until Hazelcast 4 is managed by Spring Boot. This issue is in the general backlog as a result.

Comment From: sertugkaya

Hello @snicoll just checking; is there an effort or a GH issue to address this blocker and make Spring Boot able to manage Hazelcast 4.x (or even 5, being the latest release)?

Comment From: snicoll

Thanks for the nudge. The related issue has been merged in Hazelcast 4.1, which Spring Boot 2.5.x manages so this is no longer blocked

Comment From: jerrinot

@snicoll: I sent https://github.com/spring-projects/spring-boot/pull/28801 any guidance/comments/review/suggestions are very much appreciated!

Comment From: wilkinsona

Closing in favor of #28801. Thanks again for the PR, @jerrinot.