spring-projects / spring-data-geode

Spring Data support for Apache Geode
Apache License 2.0
50 stars 37 forks source link

Consider extending API to configure PARTITION Region attributes on PartitionRegionFactoryBean #566

Open jxblum opened 2 years ago

jxblum commented 2 years ago

It should be possible via the o.s.data.gemfire.PartitionedRegionFactoryBean API to directly configure or customize PARTITION Region attributes, such as, but not limited to:

Essentially, any property or attribute exposed in the org.apache.geode.cache.PartitionAttributes API (Javadoc), or rather the org.apache.geode.cache.PartitionAttributesFactory API (Javadoc), should be configurable via the SDG PartitionedRegionFactoryBean API (Javadoc).

The Apache Geode API is a bit confusing in that the attributes specific to PARTITION Regions are still configured with generic Region attributes (i.e. RegionAttributes) set on the RegionFactory used when creating a Region, regardless if it is a PARTITION Region or otherwise.

For example, a developer using the Apache Geode API would need to use the peer Cache instance to create a RegionFactory and then set the appropriate attributes when creating a Region of the desired type (e.g. PARTITION).


RegionFactory regionFactory = cache.createRegionFactory(RegionShortcut.PARTITION);

regionFactory.setPartitionAttributes(new PartitionAttributesFactory().setColocatedWith("/B"));

Region A = regionFactory.create("A");

While the SDG XML namespace is quite convenient when configuring a PARTITION Region, using JavaConfig is less apparent in its approach given the SDG Java API (Javadoc) more closely aligns with the Apache Geode API (Javadoc).

For example, in the SDG XML namespace, it is quite easy to collocate a PARTITION Region (B) with another PARTITION Region (A) by doing the following:

<beans>

  <gfe:partitioned-region id="A"/>

  <gfe:patitioned-region id="B" colocated-with="A"/>

</beans>

However, it is less apparent, perhaps, when using Spring JavaConfig and API (and specifically, the SDG PartitionedRegionFactoryBeanclass in JavaConfig), and especially SDG Annotations, such as @EnableEntityDefinedRegions to say, collocate 2 PARTITION Regions, or even configure other PARTITION Region attributes (e.g. PartitionResolvers).

By way of example, using SDG Annotation a user would do the following in his/her Spring Boot, Spring Data Geode application:

@SpringBootApplication
@PeerCacheApplication
@EnableEntityDefinedRegions(basePackageClasses = NonEntityType.class)
public class SpringBootSpringDataGeodeApplication {

...
}

NOTE: Alternatively, the @PeerCacheApplication annotation can be replaced with the @CacheServerApplication annotation if the application needs to serve cache clients as well. A @CacheServerApplication creates a peer Cache in addition to a CacheServer to serve cache clients (ClientCache instances, most likely running in a separate JVM process, particularly when using the client/server topology).

Then, a package of [persistent] entities used by the application could be defined as:

package example.app.model;

import ...;

@PartitionRegion(name = "A")
class AEntity { }
package example.app.model;

import ...;

@PartitionRegion(name = "B", collocatedWith = "A");
class BEntity { } 
package example.app.model;

interface NonEntityType { }
jxblum commented 2 years ago

To confirm the 3 different methods for the configuration of collocated PARTITION Regions using SDG, I added new test classes / test cases and modified existing ones to confirm the configuration is correct and works as expected.

Given SDG XML configuration is likely the easiest and arguably most familiar approach to configuring Apache Geode objects, and specifically collocated PARTITION Regions, I reaffirmed the existing test class in SDG, the o.s.d.gemfire.CollocatedRegionsXmlConfigurationIntegrationTests, is correct.

The test class can be seen here along with the XML configuration.

The XML configuration approach for configuring collocated PARTITION Regions should hopefully not come as a surprise and be familiar to most.

jxblum commented 2 years ago

Next, I explored the use of Spring JavaConfig using the SDG API, and specifically the PartitionedRegionFactoryBean class, RegionAttributesFactoryBean class and PartitionAttributesFactoryBean class.

Again, these SDG API classes were intentionally designed to resemble the Apache Geode API as closely as possible, but to marry the corresponding Apache Geode classes (i.e. RegionFactory and PartitionAttributesFactory) with the Spring programming model.

The test class can be seen here along with the corresponding Java configuration using the SDG API, here.

It is necessary in this case due to the collocation between PARTITION Region "A" and PARTITION Region "B" ("B" being collocated with "A") that the bean definition for PARTITION Region "B" be dependent on the bean definition for PARTITION Region "A" given the bean declaration order (i.e. "B" before "A"), which was deliberate. Spring will follow declaration order when creating and initializing beans unless a dependency order is defined (e.g. using @DependsOn), since the dependency (collocation) maybe implicit and non-logical for Spring to derive. It is Apache Geode that requires the Region ("A") to be collocated with, to be created before the collocated Region ("B").

Anyway, this should be apparent from the test class and test configuration linked above.

jxblum commented 2 years ago

Finally, we explore the use of SDG's Annotation-based configuration model to create collocated PARTITION Regions from application domain model, persistent entity classes.

The test class is here, the test configuration is here, and the application domain model classes (persistent entities) are here.

There is a AfterEntity class (here), which will create the "After" PARTITION Region (from the SDG @PartitionRegion mapping annotation, here) and collocate the "After" PARTITION Region with the "Before" PARTITION Region, which is defined by the BeforeEntity application domain model class, persistent entity, here.

Both entity classes also defined redundantCopies (1) for the resulting PARTITION Regions, "Before" and "After", to assert additional PARTITION Region only attributes (in addition to the colocatedWith attribute on the "After" PARTITION Region, which is set to "Before").

Apache Geode additionally requires the number of redundant copies to match between collocated PARTITION Regions. This is not a Spring requirement.

The configuration of these collocated PARTITION Regions is only applied when the Spring Boot, Spring Data Geode application is annotated with @EnableEntityDefinedRegions (see here).

Anyway, it should be apparent that the XML and Annotation-based approaches are the easiest and most concise. Annotation-based configuration is the most convenient as it is expressed in Java, close to your application code.

While Spring does not have a strong preference, Annotation-config is recommended and encouraged since it can enable other Spring Boot auto-configuration capabilities. It is also easier to catch configuration errors earlier given the Annotation-config follows Java's strong typing system.

At any rate, SDG has your approach covered.