Creating Regions Dynamically
Creating Regions Dynamically
You can dynamically create regions in your application code and automatically instantiate them on members of a distributed system.
If your application does not require partitioned regions, you can use the com.gemstone.gemfire.cache.DynamicRegionFactory class to dynamically create regions, or you can create them using the <dynamic-region-factory> element in the cache.xml file that defines the region. See <dynamic-region-factory>.
Pivotal recommends that you use functions to create regions dynamically in your application, as described in this topic.
For a complete discussion of using GemFire functions, see Function Execution. Functions use the com.gemstone.gemfire.cache.execute.FunctionService class.
For example, the following Java classes define and use a function for dynamic region creation:
#CreateRegionFunction.java import com.gemstone.gemfire.cache.Cache; import com.gemstone.gemfire.cache.CacheFactory; import com.gemstone.gemfire.cache.DataPolicy; import com.gemstone.gemfire.cache.Declarable; import com.gemstone.gemfire.cache.Region; import com.gemstone.gemfire.cache.RegionAttributes; import com.gemstone.gemfire.cache.RegionFactory; import com.gemstone.gemfire.cache.Scope; import com.gemstone.gemfire.cache.execute.Function; import com.gemstone.gemfire.cache.execute.FunctionContext; import java.util.Properties; public class CreateRegionFunction implements Function, Declarable { private final Cache cache; private final Region<String,RegionAttributes> regionAttributesMetadataRegion; private static final String REGION_ATTRIBUTES_METADATA_REGION = "__regionAttributesMetadata"; public enum Status {SUCCESSFUL, UNSUCCESSFUL, ALREADY_EXISTS}; public CreateRegionFunction() { this.cache = CacheFactory.getAnyInstance(); this.regionAttributesMetadataRegion = createRegionAttributesMetadataRegion(); } public void execute(FunctionContext context) { Object[] arguments = (Object[]) context.getArguments(); String regionName = (String) arguments[0]; RegionAttributes attributes = (RegionAttributes) arguments[1]; // Create or retrieve region Status status = createOrRetrieveRegion(regionName, attributes); // Return status context.getResultSender().lastResult(status); } private Status createOrRetrieveRegion(String regionName, RegionAttributes attributes) { Status status = Status.SUCCESSFUL; Region region = this.cache.getRegion(regionName); if (region == null) { // Put the attributes into the metadata region. The afterCreate call will actually create the region. this.regionAttributesMetadataRegion.put(regionName, attributes); // Retrieve the region after creating it region = this.cache.getRegion(regionName); if (region == null) { status = Status.UNSUCCESSFUL; } } else { status = Status.ALREADY_EXISTS; } return status; } private Region<String,RegionAttributes> createRegionAttributesMetadataRegion() { Region<String, RegionAttributes> metaRegion = this.cache.getRegion(REGION_ATTRIBUTES_METADATA_REGION); if (metaRegion == null) { RegionFactory<String, RegionAttributes> factory = this.cache.createRegionFactory(); factory.setDataPolicy(DataPolicy.REPLICATE); factory.setScope(Scope.DISTRIBUTED_ACK); factory.addCacheListener(new CreateRegionCacheListener()); metaRegion = factory.create(REGION_ATTRIBUTES_METADATA_REGION); } return metaRegion; } public String getId() { return getClass().getSimpleName(); } public boolean optimizeForWrite() { return false; } public boolean isHA() { return true; } public boolean hasResult() { return true; } public void init(Properties properties) { } }
#CreateRegionCacheListener.java import com.gemstone.gemfire.cache.Cache; import com.gemstone.gemfire.cache.CacheFactory; import com.gemstone.gemfire.cache.Declarable; import com.gemstone.gemfire.cache.EntryEvent; import com.gemstone.gemfire.cache.Region; import com.gemstone.gemfire.cache.RegionAttributes; import com.gemstone.gemfire.cache.RegionEvent; import com.gemstone.gemfire.cache.RegionExistsException; import com.gemstone.gemfire.cache.util.CacheListenerAdapter; import java.util.Map; import java.util.Properties; public class CreateRegionCacheListener extends CacheListenerAdapter<String,RegionAttributes> implements Declarable { private Cache cache; public CreateRegionCacheListener() { this.cache = CacheFactory.getAnyInstance(); } public void afterCreate(EntryEvent<String,RegionAttributes> event) { createRegion(event.getKey(), event.getNewValue()); } public void afterRegionCreate(RegionEvent<String,RegionAttributes> event) { Region<String,RegionAttributes> region = event.getRegion(); for (Map.Entry<String,RegionAttributes> entry : region.entrySet()) { createRegion(entry.getKey(), entry.getValue()); } } private void createRegion(String regionName, RegionAttributes attributes) { if (this.cache.getLogger().fineEnabled()) { this.cache.getLogger().fine("CreateRegionCacheListener creating region named: " + regionName + " with attributes: " + attributes); } try { Region region = this.cache.createRegionFactory(attributes) .create(regionName); if (this.cache.getLogger().fineEnabled()) { this.cache.getLogger().fine("CreateRegionCacheListener created: " + region); } System.out.println("CreateRegionCacheListener created: " + region); } catch (RegionExistsException e) {/* ignore */} } public void init(Properties p) { } }