spring-projects / spring-data-geode

Spring Data support for Apache Geode
Apache License 2.0
52 stars 39 forks source link

EnableEntityDefinedRegions.includeFilters are inappropriately overridden by framework provided include filters [DATAGEODE-352] #401

Closed spring-projects-issues closed 4 years ago

spring-projects-issues commented 4 years ago

John Blum opened DATAGEODE-352 and commented

As an Spring [Boot] application developer developing Spring applications using Apache Geode or VMware GemFire, and I declare and use the @EnableEntityDefinedRegions annotation in my Spring application @Configuration class to create GemFire/Geode Regions from application entity classes, then I expect the includeFilters to limit entity classes discovered in the scan when identifying GemFire/Geode Regions to create.

Currently, all Regions defined by application entities in the declared application entity class packages are created because the SDG framework include filters are overriding the user-defined includeFilters.

Keep in mind, the includeFilters, as implied in the Spring Framework @ComponentScan annotation, includeFilters attribute, are combined using the logical OR operator. Additionally, includeFilters can cancel the effect of 1 or more excludeFilters. So be mindful when using these 2 attributes in conjunction with each other.

The SDG framework provides @Region annotated (and variants) AnnotationTypeFilters for all the @Region like mapping annotations (see here). If an application entity class matches 1 of the user-defined includeFilters or 1 of the SDG framework @.*Region AnnotationTypeFilters during the scan then the entity class is included and the declared Region will be created.

While application entity classes should and must include an @.*Region mapping annotation to be included in the scan, this should not be either "OR". Rather, the includeFilters defined by a user should be ANDed with the framework includeFilters


Reference URL: https://stackoverflow.com/questions/62445958/how-to-add-componentscan-filter-in-enableentitydefinedregion

Backported to: 2.3.2 (Neumann SR2), 2.2.9 (Moore SR9), 2.1.19 (Lovelace SR19)

spring-projects-issues commented 4 years ago

John Blum commented

The mileage to work around this issues varies.

If you only want a single Region created from an application entity class (out of of many), then rather than target the Region specifically with Regex, you can use an explicit Region bean definition, like so:

Given an entity class:

@Region("Example")
class Example { ... }

Then, define the "Example" Region with an explicit Region bean definition:

@Configuration
class GeodeConfiguration {

    @Bean("Example")
    public ClientRegionFactoryBean<Object, Object> example(GemFireCache gemfireCache) {

        ClientRegionFactoryBean<Object, Object> clientRegion = new ClientRegionFactoryBean<>();

        clientRegion.setCache(gemfireCache);
        clientRegion.setShortcut(ClientRegionShortcut.PROXY);

        return clientRegion;
    }
}

And disable the @EnableEntityDefinedRegion annotation

@Configuration
//@EnableEntityDefinedRegions(..)
class GeodeConfiguration { ... }

Of course, making use of Spring Profiles here is helpful, especially during development.

@Configuration
@Profile("ExplicitRegionBeanDefinitions")
class GeodeConfiguration {

    @Bean("Example")
    ClientRegionFactoryBean example(GemFireCache gemfireCache) { ... }

    ...
}

@Configuration
@EnableEntityDefinedRegions(..)
@Profile("EntityDefinedRegions")
class GeodeCofiguration { }
spring-projects-issues commented 4 years ago

John Blum commented

Alternatively, you could use a BeanFactoryPostProcessor to post-process the Spring Container BeanDefinitions, or a Spring BeanPostProcessor to post-process the bean (instance) either before or after initialization.

See documentation for more details