Skip to content

S3StoreConfigurer forces to define a PlacementService Bean #2416

@gasteiz1921

Description

@gasteiz1921

Describe the bug
When I try to configure a S3StoreConfigurer (v3.0.17 of the library), it forces me to define a PlacementService between s3StorePlacementService/filesystemStorePlacementService and to set the @bean as @primary.

That bean, takes preference over my custom ConversionService with my custom object converters defined in a WebConfig, so when I try to @autowire a ConversionService, the PlacementService defined in S3StoreConfigurer is injected without my custom converters.

To Reproduce
1 - Define a S3StoreConfigurer

   @Configuration
   @EnableS3Stores
    public class S3StoreConfig {

    @Value( "${s3.requests.bucket}" )
    private String requestsBucket;

    @Value( "${spring.content.s3.bucket}" )
    private String measurementsBucket;

    @Bean
    public S3StoreConfigurer configurer() {
        return new S3StoreConfigurer() {
            @Override
            public void configureS3StoreConverters(ConverterRegistry registry) {
                registry.addConverter(new Converter<RequestLogFileEntity, S3ObjectId>() {
                    @Override
                    public S3ObjectId convert(RequestLogFileEntity requestLogFileEntity) {
                        return new S3ObjectId(requestsBucket, requestLogFileEntity.getContentPath());
                    }
                });

                registry.addConverter(new Converter<MeasuredParameterEntity, S3ObjectId>() {
                    @Override
                    public S3ObjectId convert(MeasuredParameterEntity measuredParameterEntity) {
                        return new S3ObjectId(measurementsBucket, measuredParameterEntity.getPath());
                    }
                });

                registry.addConverter(new Converter<DefaultParameterValueEntity, S3ObjectId>() {
                    @Override
                    public S3ObjectId convert(DefaultParameterValueEntity defaultParameterValueEntity) {
                        return new S3ObjectId(measurementsBucket, defaultParameterValueEntity.getPath());
                    }
                });
            }
        };
    }
}

2 - Launch the App. This error ir thrown:

Parameter 0 of method setS3StorePlacementService in internal.org.springframework.content.s3.config.S3StoreFactoryBean required a single bean, but 2 were found: - s3StorePlacementService: defined by method 's3StorePlacementService' in class path resource [internal/org/springframework/content/s3/config/S3StoreConfiguration.class] - filesystemStorePlacementService: defined by method 'filesystemStorePlacementService' in class path resource [internal/org/springframework/content/fs/config/FilesystemStoreConfiguration.class]

3 - Define the PlacementService @bean.

  @Configuration
  @EnableS3Stores
  public class S3StoreConfig {
  
      @Value( "${s3.requests.bucket}" )
      private String requestsBucket;
  
      @Value( "${spring.content.s3.bucket}" )
      private String measurementsBucket;
  
      @Bean
      @Primary //<- If I do not define it as primary, the error is still thrown
      public PlacementService placementService(@Qualifier("s3StorePlacementService") PlacementService s3PlacementService) {
          return s3PlacementService;
      }
  
      @Bean
      public S3StoreConfigurer configurer() {
          return new S3StoreConfigurer() {...}
      }

4- The application starts, but the PlacementService required @bean defined in S3StoreConfig is taking preference over my custom ConversionService defined in:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer { 
     private final List<Converter<?, ?>> apiConverters;

    public WebConfig(
            List<Converter<?, ?>> apiConverters,          
    ) {
        this.apiConverters = apiConverters;      
    }

    @Override
    public void addFormatters(FormatterRegistry registry) {
        apiConverters.forEach(registry::addConverter);
    }
}

public class ObjectAToObjectB implements Converter<ObjectA, ObjectB> {...}

5 - When I @autowire the conversion service, the one defined in S3StoreConfig is injected, instead of my the one defined in WebConfig, so it throws an error: No converter found capable of converting from type [ObjectA] to type [ObjectB]

@Service
public MyService {
     @Autowire
      private ConversionService conversionService


      public ObjectB transformObject(ObjectA beforeTransform) {
            return this.conversionService.convert(beforeTransform, ObjectB.class);
      } 

}

Expected behavior
In the previous version of the library I was using (1.2.6), It was not needed to define the PlacementService, so the custom ConversionService worked.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions