Spring Boot + Hazelcast MapStore can't Autowire Repository
Asked Answered
T

3

5

I started exploring about Hazelcast functionalities and I've been trying use a MapStore as a Write-Behind buffer for my database through HazelcastRepository. My goal is to use a JpaRepository inside my MapStore to load and store to/from the cache.

I'm using Spring Boot and after doing some research i found that i could use the @SpringAware to Autowire my Repository inside MapStore but every-time it gets there my Bean is null and I get a NullPointerException. I can't get it working even after lots of different tests I was not able to Autowire my bean inside the MapStore

is something wrong with this configuration to enable SpringAware or am I looking at the wrong place?

Found This stackoverflow post and it gave me clues but I still couldn't figure out the issue since most configurations were xml and not java. Also Found this Github Issue on how to configure SpringAware in Hazelcast through Java configurations

And I committed my example code in this Git Repo Here.

Debugger Screenshot null Bean

Tendency answered 21/8, 2018 at 23:32 Comment(5)
I Added a screenshot with the main pieces of the code where we can see the @Autowired Bean as Null in the MapStoreTendency
Can you please fix the link to your Git Repo with example? It points currently to the screenshotHunterhunting
Fixed it, i messed up when adding the screenshot in the edit.Tendency
What was the fix?Kurtzman
oh i guess i didn't express me well, i only fixed the link to the Github that @Kostrianlyn mentioned when i added the screenshoot.Tendency
F
7

After investigation the provided code, I noticed that the @SpringAware was never enabled by default as per a GitHub issue I found on Hazelcast. The issue described that SpringAware was disabled because it was affecting the performance, which forwarded me to another closed ticket solving enabling the annotation by code using the SpringManagedContext (avoiding the use of XML), but it doesn't still solve the issue.

The real solution was found here, add MapLoaderLifecycleSupport interface to your MapStore implementation and implement the init method as shown in the ticket:

@Override
public void init(HazelcastInstance hazelcastInstance, Properties properties, String mapName) {
    hazelcastInstance.getConfig().getManagedContext().initialize(this);
}

This will force @SpringAware to be enabled in the MapStore class, therefore, being able to autowire any spring component into the class as shown in the image below.

working-jpa-repository-map-store-screenshot

Foodstuff answered 12/9, 2018 at 21:31 Comment(3)
this actually worked really well, so we have to have the SpringAware and also set the context 'manually' in the init, great catch.. accepted your pull request with the fixed changeTendency
Hi..@FernandoNakano I'm also facing similar issue.. so Can you please the git source code link..Or Any suggestions would be helpful..Objective
for me this worked only starting from spring boot version 2.7.0 (github.com/spring-projects/spring-boot/pull/28801). Before managed context was not injected during auto configuration and I was getting npe. please be aware of thatSimpleminded
K
1

Here the problem is you are creating the spring bean with name pr, when auto wiring you are using personRepository.

Either change pr to personRepository in PersonRepository.java OR remove ("pr") from PersonRepository.java

@Autowired
PersonRepository personRepository; 

DAO

@Repository("pr")
public interface PersonRepository extends JpaRepository<Person, Integer> {

    @Query("SELECT id FROM Person")
    Iterable<Integer> findAllId();
}
Kurtzman answered 22/8, 2018 at 6:5 Comment(1)
Good point, thanks for finding that out, this is actually something i added after doing some tests, i removed the bean name back for just @Repository but it still doesn't work, the personRepository is still null inside the MapStore.Tendency
D
0

Lazily injecting the MapStore bean to the class where you initialise your maps works too:

    @Inject
    HazelcastConfiguration(@Lazy MyMapStore myMapStore) {
        this.myMapStore = myMapStore;
    }

In this example the MyMapStore bean contains an injected MyRepository bean.

Dryly answered 11/2, 2019 at 15:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.