Uploaded image for project: 'Camel'
  1. Camel
  2. CAMEL-16111

camel-spring-boot - Bean reference by name in properties not working when there are custom property converters

    XMLWordPrintableJSON

    Details

    • Estimated Complexity:
      Unknown

      Description

      Bean reference by name (#bean:name syntax) in properties not working when there are custom converters registered in Spring Boot Application. I use Spring Boot 2.4.2 and Camel 3.7.1 to create Quartz component with manally defined scheduler via property:

      camel.component.quartz.scheduler=#quartzScheduler

      This causes error:

      Failed to bind properties under 'camel.component.quartz.scheduler' to org.quartz.Scheduler:

      Property: camel.component.quartz.scheduler
      Value: #quartzScheduler
      Origin: class path resource [application.properties] - 93:34
      Reason: No converter found capable of converting from type [java.lang.String] to type[org.quartz.Scheduler]

      Previously, in Spring Boot 2.3.0 and Camel 3.3.0 it worked ok.

      Debugging shows that problem is caused by the fact that:

      • QuartzComponentConverter registers itself only in ApplicationConversionService.getSharedInstance
      • QuartzComponentConverter is not a bean in Spring context
      • org.springframework.boot.context.properties.ConversionServiceDeducer.Factory.create() creates separate instance of ApplicationConversionService if there are any custom converters (which indeed are present in application configuration)

      Quick workaround is to add custom property converter similar to QuartzComponentConverter that will be picked by the ConversionServiceDeducer:

      @ConfigurationPropertiesBinding
      @Component
      public class QuartzComponentPropertyConverter implements GenericConverter {
          @Autowired
          private ApplicationContext applicationContext;
      
          public Set<ConvertiblePair> getConvertibleTypes() {
              Set<ConvertiblePair> answer = new LinkedHashSet<>();
              answer.add(new ConvertiblePair(String.class, org.quartz.Scheduler.class));
              answer.add(new ConvertiblePair(String.class, org.quartz.SchedulerFactory.class));
              return answer;
          }
      
          public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
              if (source == null) {
                  return null;
              }
              String ref = source.toString();
              if (!ref.startsWith("#")) {
                  return null;
              }
              ref = ref.startsWith("#bean:") ? ref.substring(6) : ref.substring(1);
              switch (targetType.getName()) {
              case "org.quartz.Scheduler":
                  return applicationContext.getBean(ref, org.quartz.Scheduler.class);
              case "org.quartz.SchedulerFactory":
                  return applicationContext.getBean(ref, org.quartz.SchedulerFactory.class);
              }
              return null;
          }
      
      }
      

        Attachments

          Activity

            People

            • Assignee:
              davsclaus Claus Ibsen
              Reporter:
              krzysztofjamroz Krzysztof Jamróz
            • Votes:
              1 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: