package com.kryptnostic.rhizome.pods.hazelcast; import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentMap; import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import com.google.common.base.Preconditions; import com.google.common.collect.HashMultiset; import com.google.common.collect.Maps; import com.google.common.collect.Multiset; import com.hazelcast.config.MapConfig; import com.hazelcast.config.QueueConfig; import com.hazelcast.config.SerializerConfig; import com.hazelcast.nio.serialization.Serializer; import com.kryptnostic.rhizome.mapstores.SelfRegisteringMapStore; import com.kryptnostic.rhizome.mapstores.SelfRegisteringQueueStore; @Configuration public class RegistryBasedHazelcastInstanceConfigurationPod extends BaseHazelcastInstanceConfigurationPod { private static final Logger logger = LoggerFactory .getLogger( RegistryBasedHazelcastInstanceConfigurationPod.class ); private static final ConcurrentMap<Class<?>, Serializer> serializerRegistry = Maps .newConcurrentMap(); private static final ConcurrentMap<String, SelfRegisteringMapStore<?, ?>> mapRegistry = Maps .newConcurrentMap(); private static final ConcurrentMap<String, SelfRegisteringQueueStore<?>> queueRegistry = Maps .newConcurrentMap(); @Override protected Collection<SerializerConfig> getSerializerConfigs() { final Multiset<Integer> typeIds = HashMultiset.create(); Set<SerializerConfig> configs = serializerRegistry.entrySet() .stream() .peek( e -> typeIds.add( e.getValue().getTypeId() ) ) .map( e -> new SerializerConfig().setTypeClass( e.getKey() ).setImplementation( e.getValue() ) ) .collect( Collectors.toSet() ); logger.info("Detected the following serializer configurations at startup {}." , configs ); typeIds.entrySet() .stream() .filter( e -> e.getCount() > 1 ) .forEach( e -> logger.warn( "Found {} duplicate serializers for type id: {}", e.getCount(), e.getElement() ) ); return configs; } @Override protected Map<String, MapConfig> getMapConfigs() { return Maps.transformEntries( mapRegistry, ( k, v ) -> v.getMapConfig() ); } @Override protected Map<String, QueueConfig> getQueueConfigs() { return Maps.transformEntries( queueRegistry, ( k, v ) -> v.getQueueConfig() ); } /* * The following three methods use @Autowired instead of @Inject, since that functionality is not provided by the * spec :-/ */ @Autowired( required = false ) public void registerMapStores( Set<SelfRegisteringMapStore<?, ?>> mapStores ) { if ( mapStores.isEmpty() ) { logger.warn( "No map stores were configured." ); } for ( SelfRegisteringMapStore<?, ?> s : mapStores ) { register( s.getMapConfig().getName(), s ); } } @Autowired( required = false ) public void registerQueueStores( Set<SelfRegisteringQueueStore<?>> queueStores ) { if ( queueStores.isEmpty() ) { logger.warn( "No queue stores were configured." ); } for ( SelfRegisteringQueueStore<?> s : queueStores ) { queueRegistry.put( s.getQueueConfig().getName(), s ); } } @Autowired( required = false ) public void register( Set<SelfRegisteringStreamSerializer<?>> serializers ) { if ( serializers.isEmpty() ) { logger.warn( "No serializers were configured." ); } for ( SelfRegisteringStreamSerializer<?> s : serializers ) { serializerRegistry.put( s.getClazz(), s ); } } public static void register( String queueName, SelfRegisteringQueueStore<?> queueStore ) { Preconditions.checkNotNull( queueStore, "Cannot register null queue-store." ); queueRegistry.put( queueName, queueStore ); } public static void register( String mapName, SelfRegisteringMapStore<?, ?> mapStore ) { Preconditions.checkNotNull( mapStore, "Cannot register null map-store." ); mapRegistry.put( mapName, mapStore ); } public static void register( Class<?> hzSerializableClass, Serializer serializer ) { Preconditions.checkNotNull( serializer, "Cannot register null serializer." ); serializerRegistry.put( hzSerializableClass, serializer ); } }