I have a clustered java application (Spring + Hibernate) that uses a Hazecast (hazelcast-spring, v3.4) as a 2nd level cache, and also uses a Hazelcast Mapstore that persist the changes to the DB
using Hibernate (
adapted from this example).
So my application has to initialize a Hazelcast instance (that joins a existing cluster if present) as part of its loading process.
This woks well with only 1 member in the cluster. So the Mapstore gets new data and this is being persisted normally to the database.
However, when a new application joins the cluster (and in turns joins the hazelcast cluster), Hazelcast tries to partition the data immediately to the new member before the new application has initializes its database own sessionfactory completely, this causes a null-pointer exception (see below) since the session factory (on the 2nd instance) depends on hazelcast for the 2nd level cache and hazelcast (on the 1st instance) depends on the session factory to partition the data of the Mapstore.
So I need a way to avoid the partition process from happening until the new application is fully initialized and only then let Hazelcast know so it can start the partitioning to the new member.
I checked the
hazelcast advanced configuration properties but couldn't find anything that could control this. In any case, I will prefer something that gives me more control, rather than some time-based delay (e.g. a new listener/event or something similar if available)
Any ideas?
I hope question is clear and thanks in advance for any assistance...
P.S:
Error when the new application member joins the cluster:
hz.hazelCastInstance.partition-operation.thread-1] 18Sep15-10:10:29 ERROR(TokenMapStore.java:96)-Failed to load
java.lang.NullPointerException
at xxx.hazelcast.map.hibernate.HazelcastMapStoreHibernateDao.getCurrentSession(HazelcastMapStoreHibernateDao.java:104)
...
at com.hazelcast.map.impl.MapStoreWrapper.load(MapStoreWrapper.java:110)
at com.hazelcast.map.impl.mapstore.writebehind.WriteBehindStore.load(WriteBehindStore.java:137)
at com.hazelcast.map.impl.mapstore.writebehind.WriteBehindStore.load(WriteBehindStore.java:24)
at com.hazelcast.map.impl.DefaultRecordStore.loadRecordOrNull(DefaultRecordStore.java:313)
at com.hazelcast.map.impl.DefaultRecordStore.get(DefaultRecordStore.java:580)
at com.hazelcast.map.impl.operation.GetOperation.run(GetOperation.java:43)
at com.hazelcast.spi.impl.BasicOperationService$OperationHandler.handle(BasicOperationService.java:733)
at com.hazelcast.spi.impl.BasicOperationService$OperationHandler.access$500(BasicOperationService.java:709)
at com.hazelcast.spi.impl.BasicOperationService$OperationPacketHandler.handle(BasicOperationService.java:683)
at com.hazelcast.spi.impl.BasicOperationService$OperationPacketHandler.handle(BasicOperationService.java:627)
at com.hazelcast.spi.impl.BasicOperationService$OperationPacketHandler.access$1500(BasicOperationService.java:614)
at com.hazelcast.spi.impl.BasicOperationService$BasicDispatcherImpl.dispatch(BasicOperationService.java:566)
at com.hazelcast.spi.impl.BasicOperationScheduler$OperationThread.process(BasicOperationScheduler.java:466)
at com.hazelcast.spi.impl.BasicOperationScheduler$OperationThread.doRun(BasicOperationScheduler.java:458)
at com.hazelcast.spi.impl.BasicOperationScheduler$OperationThread.run(BasicOperationScheduler.java:432)
...
Sample of my sectionFactory configuration:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" depends-on="hazelCastInstance">
<property name="dataSource" ref="dataSource" />
<property name="mappingLocations" ref="defaultHibernateMappingLocationList"/>
<property name="hibernateProperties">
<props>
<prop key="org.hibernate.FlushMode">COMMIT</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
<prop key="hibernate.cache.use_minimal_puts">true</prop>
<prop key="hibernate.cache.region.factory_class">com.hazelcast.hibernate.HazelcastLocalCacheRegionFactory</prop>
<prop key="hibernate.cache.use_structured_entries">${hibernate.cache.use_structured_entries}</prop>
<prop key="hibernate.cache.hazelcast.instance_name">hazelCastInstance</prop>
<prop key="hibernate.default_batch_fetch_size">${hibernate.default_batch_fetch_size}</prop>
<prop key="hibernate.order_inserts">${hibernate.order_inserts}</prop>
<prop key="hibernate.order_updates">${hibernate.order_updates}</prop>
<prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>
</props>
</property>
</bean>