spring-data-rest icon indicating copy to clipboard operation
spring-data-rest copied to clipboard

custom RepositoryRestConfigurer not initialized when lazy-initialization is set to true

Open ilseva opened this issue 1 year ago • 4 comments

Hi! We need to register custom converters from our repositories exposed as RepositoryRestResource. We implement a class, annotated with @Configuration, that extends the RepositoryRestConfigurer and we implement the configureConversionService method. When the application starts with spring.main.lazy-initialization at true the custom converters are not loaded.

Spring Boot version: 2.7.7

ilseva avatar Mar 08 '23 11:03 ilseva

Thanks for bringing this to our attention. Any chance you can provide a minimal reproducer (ideally Java, Maven, as few as possible, additional dependencies)?

odrotbohm avatar May 03 '23 15:05 odrotbohm

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

spring-projects-issues avatar May 10 '23 15:05 spring-projects-issues

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.

spring-projects-issues avatar May 17 '23 15:05 spring-projects-issues

I can confirm this. It also happened to us on Spring Boot 3.2.4 with

spring:
  main:
    lazy-initialization: true

The workaround ist to not load the relevant @Configurations lazily by adding @Lazy(false). I'm not sure if this is expected behaviour or not.

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(RepositoryRestProperties.class)
@Lazy(value = false)
public class OurRepositoryRestMvcConfiguration implements RepositoryRestConfigurer {

  private final BeanFactory beanFactory;
  private final Jackson2ObjectMapperBuilder objectMapperBuilder;
  private final RepositoryRestProperties properties;

  OurRepositoryRestMvcConfiguration(
    BeanFactory beanFactory,
    Jackson2ObjectMapperBuilder objectMapperBuilder,
    RepositoryRestProperties properties
  ) {
    this.beanFactory = beanFactory;
    this.objectMapperBuilder = objectMapperBuilder;
    this.properties = properties;
  }

  @Override
  public void configureConversionService(ConfigurableConversionService conversionService) {
    final var annotatedTypeScanner = new AnnotatedTypeScanner(Component.class);
    Set<Class<?>> types = annotatedTypeScanner.findTypes(
      "com.example.ourpackage.for.converters"
    );
    types.forEach(type -> {
      try {
        Object bean = beanFactory.getBean(Class.forName(type.getName()));
        if (bean instanceof Converter) {
          conversionService.addConverter((Converter<?, ?>) bean);
        }
      } catch (ClassNotFoundException e) {
         // log error
      }
    });
  }

  @Override
  public void configureRepositoryRestConfiguration(
    RepositoryRestConfiguration config,
    CorsRegistry cors
  ) {
    this.properties.applyTo(config);
  }

  @Override
  public void configureJacksonObjectMapper(ObjectMapper objectMapper) {
    this.objectMapperBuilder.configure(objectMapper);
  }
}

Guschtel avatar Apr 19 '24 06:04 Guschtel